Если нельзя, но очень хочется, то нужно обязательно и ничего в мире не стоит того, чтобы делать из этого проблему!


Интересна Java? Кликай по ссылке и изучай!
Если тебе полезно что-то из того, чем я делюсь в своем блоге - можешь поделиться своими деньгами со мной.
с пожеланием
столько времени читатели провели на блоге - 
сейчас онлайн - 

вторник, 30 апреля 2013 г.

Чердак - это машина времени

Картонные коробки на чердаке или старый шкаф в подвале - это машина времени. Решил сегодня поковыряться там. Нашел очень много вещей - якорей из прошлого. Но самое главное - негативы. Я не мог ждать, когда отпечатают фотки...



...вот так выглядел мой Папка, когда ему было лет как мне сейчас... И эту фотографию я никогда раньше не видел.

Смотреть на негатив сложно - там все инвертировано, но если фотнуть негатив на свету, а потом инвертировать Ч/Б изображение в любом редакторе (даже paint это поддерживает), то можно увидеть то, что хранит негатив.

Когда-нибудь наши внуки будут находить на чердаках флешки или SSD-винчесетры. Undelete покажет, что там когда-то были фотки и видео...

Хотя, чем дальше - тем больше все заливается в облачко. И "захламленный чердак" - это будет какой-то старый-пре-старый портал, который в свое время копипастил контент с паблик аккаунтов соцсетей...

И все же, старые заброшенные чердаки хранят в себе не мало тайн. Жаль, что другие негативы не сохранились. Я помню, их в моем детстве было несколько коробок. Тогда они небыли для меня ценными и я ними небрежно игрался, а сейчас я бы очень хотел их найти...

Кто знает, что будет ценным для меня еще лет через 20?...

среда, 24 апреля 2013 г.

Что могут 100 000 000 000 нейронов и много лет опыта

Потому-то я и переживаю, когда кто-то просто выполняет свою рутинную (не интересную, не вдохновляющую, не сложную, которую можно было бы автоматизировать и поручить роботу) работу... Мозг не за тем был дан человеку...

TDD что он может?

На прошлом Bomberman Cdenjoy всплыла задачка makeBricks из codingbat.com. Вопрос был в том, как бы я решал эту задачу ТДД. Ну, начал бы с самого простого кейса, а там по ситуации. Лучший способ демонстрации - парное программирование, потому мы с Виталиком сели в пару за комп и начали. Первый наш код получился таким.
public class Main {
    @Test
    public void test1() {
        assertBricks(true, 0, 1, 5);
        assertBricks(true, 1, 0, 1);
        assertBricks(false, 1, 0, 2);
    }

    public boolean makeBricks(int small, int big, int goal) {
        return small + big * 5 == goal;
    }

    private void assertBricks(boolean expected, int c1, int c5, int l) {
        boolean actual = makeBricks(c1, c5, l);
        assertEquals(String.format("C1 = %s, C5 = %s, L = %s, Actual = %s, But expected = True", c1, c5, l, actual, expected),
                expected, actual);
    }
}
Но уже после 4го теста (ассерта) мы пришли к тому, что начали путаться... И я предложил выйти в тестах на более высокий уровень абстракции. Код преобразился и стал понятнее описывать доменную область.
public class Main {
    private static final int HHHHH = 5;
    private static final int H = 1;
    public static final boolean NO = false;
    public static final boolean YES = true;

    @Test
    public void test1() {
        YES(5, HHHHH);
        YES(1, H);
        NO(2, H);
    }

    public boolean makeBricks(int small, int big, int goal) {
        return small + big * 5 >= goal;
    }


    private void YES(int l, int... bricks) {
        assertBricks(YES, l, bricks);
    }

    private void NO(int l, int... bricks) {
        assertBricks(NO, l, bricks);
    }

    private void assertBricks(boolean expected, int l, int... bricks) {
        int c1 = 0;
        int c5 = 0;
        for (int i : bricks) {
            if (i == H) {
                c1++;
            }
            if (i == HHHHH) {
                c5++;
            }
        }
        assertL(expected, c1, c5, l);
    }

    private void assertBricks(boolean expected, int c1, int c5, int l) {
        boolean actual = makeBricks(c1, c5, l);
        assertEquals(String.format("C1 = %s, C5 = %s, L = %s, Actual = %s, But expected = True", c1, c5, l, actual, expected),
                expected, actual);
    }
}
Работа пошла быстрее! В следующие пару минут мы написали еще пачку тестов
    @Test
    public void test1() {
        YES(5, HHHHH);
        YES(1, H);
        NO(2, H);
        YES(7, HHHHH, H, H, H);
        YES(14, HHHHH, HHHHH, H, H, H, H);
        NO(14, HHHHH, HHHHH,  H, H, H);
        YES(5, HHHHH, HHHHH);
        YES(6, HHHHH, H, H, H);
        NO(9, HHHHH, H, H, H);
    }
Реализация совсем немного изменилась, чтобы соответствовать тестам.
    public boolean makeBricks(int small, int big, int goal) {
        return small + big * 5 >= goal;
    }
И тут началось самое интересное. Мы больше не могли добавить ни одного красного теста. И так и сяк. Зависли. Но в то же время http://codingbat.com/prob/p183562 сказал нам, что мы забыли как минимум один кейс.
    @Test
    public void test2() {
        NO(9, HHHHH, HHHHH, H, H, H); 
    }
И тут возник заслуженный вопрос. Какова роль ТДД тут? Почему он не помогает решить эту задачу - найти еще один красный кейс? Ответ был таким - ТДД помогает убедиться в том что, что все кейсы которые ты придумал работают (более вероятно, чем если бы ты писал без тестов). ТДД помагает в поиске новых кейсов только тем, что сразу же сигнализирует о твоих ошибках, что со временем приводит к осознанию, что "я ошибаюсь часто", "я что-то недопроверил" - а этот скепсис по направлению к своему коду, помогает задуматься над поиском дополнительных кейсов. А вот как их искать, нам подсказал уже Лёня. Комментарий Виталика был такой (и я с ним полностью согласен)
Цікаво шо ці всі викрутаси можна почати тільки від одного "чувстуетсья что что-то не то", в тому випадку у нас були тести які явно показали, якшо їх нема, то може або провтикатись, або "почувствоваться", це з досвідом приходить, професійна подозрітєльность на такі штуки. Да і рішення в тих варіантах які запропоновано в основному інтуітивні, або направлені на то шоб допомогти інтуіції прийти до червоного кейса.
Только вот хотелось бы какой-то более конкретный математический аппарат для поиска красных кейсов. Уверен, что опытные тестировщики уладеют такими инструментами. На этом пока все. Пока буду искать ответ. Как появится - опишу его тут.... Спасибо Леня, Виталик! P.S. Вот та причина, почему я люблю блог. Описал в нем проблему, отложил ее в сторону и мозг твой сгенерил решение. Мой мне напомнил про то, что есть такая чудная библиотека, которая называется Approvals (кстати в прошлом месяце вышла новая версия). Что я с ней сделал? Ну кроме того, что скачал ее отсюда. А потом прописал maven dependency
<dependency>
 <groupId>net.sourceforge.approvaltests</groupId>
 <artifactId>approvaltests</artifactId>
 <version>0.1.3</version>
 <scope>system</scope>
 <systemPath>${project.basedir}/lib/ApprovalTests-0.1.3/ApprovalTests.jar</systemPath>
</dependency>
Я написал вот такой вот несложный тест
import org.approvaltests.legacycode.LegacyApprovals;
import org.approvaltests.legacycode.Range;
...
public class Main {
...
    @Test
    public void testApprovals() throws Exception {
        LegacyApprovals.LockDown(this, "approveMakeBricks", Range.get(0, 10), Range.get(0, 10), Range.get(0, 100));
    }

    public boolean approveMakeBricks(Integer small, Integer big, Integer goal) {
        return makeBricks(small, big, goal);
    }
Запустив его я увидел что возвращает метод во всех комбинациях входных параметров. Я стал критиковать эти результаты, и уже на 133 строчке (через минуту беглого просмотра) я первую увидел неточность.
[0, 0, 0] = true 
[1, 0, 0] = true 
[2, 0, 0] = true 
[3, 0, 0] = true 
[4, 0, 0] = true 
[5, 0, 0] = true 
[6, 0, 0] = true 
...
[6, 10, 0] = true 
[7, 10, 0] = true 
[8, 10, 0] = true 
[9, 10, 0] = true 
[10, 10, 0] = true // Все что выше всегда тру, это и ежу понятно - длину 0 мы составим из элементов любого набора
[0, 0, 1] = false // тут ок потому, как материала не хватает 
[1, 0, 1] = true // все что ниже тоже ок, потому как имея хоть одну H мы сможем составить длину 1 всегда 
[2, 0, 1] = true 
[3, 0, 1] = true 
[4, 0, 1] = true 
[5, 0, 1] = true 
[6, 0, 1] = true 
[7, 0, 1] = true 
[8, 0, 1] = true 
[9, 0, 1] = true 
[10, 0, 1] = true 
[0, 1, 1] = true // а вот тут интересно! Мой алгоритм считает, что можно взять HHHHH и c нее составить L=1, что не ок. 
[1, 1, 1] = true 
...
Вот вам и красный тест
    @Test
    public void test2() {
        NO(1, HHHHH); 
    }
Главная фишка аппрувалса - пусть каждый делает то, что ему свойственно: комп пусть считает комбинации, а человек пусть оценивает правильность результата. Решилось это как-то так
    public boolean makeBricks(int small, int big, int goal) {
        if (goal == 0) {
            return true;
        }
        if (small == 0) {
            return goal % 5 == 0 && goal / 5 <= big;
        }
        return small + big * 5 >= goal;
    }
И главное теперь тест написанный на аппрувалсе тоже стал говорить!
 Поехали дальше...
...
[0, 0, 2] = false // не хватает материала
[1, 0, 2] = false // не хватает материала
[2, 0, 2] = true  // тут и дальше все хватает
[3, 0, 2] = true 
[4, 0, 2] = true 
[5, 0, 2] = true 
[6, 0, 2] = true 
[7, 0, 2] = true 
[8, 0, 2] = true 
[9, 0, 2] = true 
[10, 0, 2] = true 
[0, 1, 2] = false // снова не хватает материала
[1, 1, 2] = true  // а тут интересно! Опять пытаемся поделить пятерку чтобы сделать из нее что-то... Прошлый фикс не совершенен!
[2, 1, 2] = true 
[3, 1, 2] = true 
[4, 1, 2] = true  
...
Итого красный тест таков. Я сразу добавил однотипные кейсы, потому что чувствую мощь!
    @Test
    public void test3() {
        NO(1, HHHHH);
        NO(2, HHHHH, H);
        NO(3, HHHHH, H, H);
        NO(4, HHHHH, H, H, H);
    }
Получилось как-то так
    public boolean makeBricks(int small, int big, int goal) {
        if (goal == 0) {
            return true;
        }
        return (goal - small) / 5 <= big && (goal - small) % 5 == 0 || (goal - big*5) <= small && goal >= big*5;
    }
Не спрашивай как я пришел к этому. Просто как-то уивделось такое решение. Кроме того оно не оптимальное, так как я поломал старое (то что засек approvals но не засекли мои тестики) потому я решил добавить в свой набор тестов этот кейс.
    @Test
    public void test4() {
        YES(1, HHHHH, H, H);
    }
Этот тест проверяет, что у меня и больших и маленьких в избытке.
    public boolean makeBricks(int small, int big, int goal) {
        if (goal == 0) {
            return true;
        }
        return (goal - small) / 5 <= big && (goal - small) % 5 == 0 
                || (goal - big*5) <= small && goal >= big*5 
                || goal < small; // фикс простой как двери
    }
А как на счет этого теста?
    YES(6, HHHHH, HHHHH, H, H);
Потом мне приспичило в туалет. А возвращался я уже с этой идеей
    public boolean makeBricks(int small, int big, int goal) {
        return goal / 5 <= big && goal % 5 <= small;
    }
И как я до этого сразу не додумался? Но это еще не все. Просмотр таблицы результатов остановила меня возле теста
    YES(11, HHHHH, H, H, H, H, H, H);
Блин! Так все идеально было :) Решение вот
    public boolean makeBricks(int small, int big, int goal) {
        return goal / 5 <= (big + small / 5) && goal % 5 <= small % 5;
    }
Но тест (судя по изменениям - я уже не так просматриваю таблицу, как слежу за diff)
 Напишем такой тестик
    YES(1, H, H, H, H, H);
Нате! Родил
    public boolean makeBricks(int small, int big, int goal) {
        return goal / 5 <= (big + small / 5) && goal % 5 <= ((((goal / 5 - big - small / 5) == 0) && (small / 5 != 0)) ? (small % 5) : small);
    }
Ну и задачка :) Я че сюда полез, потому что мне сказали что ее можно решить без циклов :) Я не нашел проблем в approvals тесте - обратился к codingbat.com и там тоже получил аппрув
 Теперь осталось заапрувить все в аппрувалс тесте и провести рефакторинг....
      public boolean makeBricks(int small, int big, int goal) {
        int needBig = goal / 5;
        int needSmall = goal % 5;
        int smallAsBig = small / 5;
        int smallWithoutBigGroups = small % 5;
        int stillNeedBig = needBig - big - smallAsBig;

        boolean usedSmallAsBig = stillNeedBig == 0 && smallAsBig != 0;

        boolean enoughSmall = needSmall <= (usedSmallAsBig ? smallWithoutBigGroups : small);
        boolean enoughBig = stillNeedBig <= 0;

        return enoughBig && enoughSmall;
    }
Как-то так...

Но если посмотреть на решение, которое предлагает сам автор, становится понятно, что изначально выбрали не тот путь...

Попробуем проанализировать. Если в моем способе решения задачи я цеплялся за самый простой кейс, то в подходе предложенным Автором стоило бы первым фиксом отсечь как можно большее количество вариантов, а потом повторить то же с остатком. Интересно...

Блочим Тролля

Тролля не корми - все в один голос говорят в сети. Кто-то же предлагает решения. Решил воспользоваться ими.

Итак самое интересное определение нашул тут.
Троллю совершенно безразлично, о чём идёт разговор. Ему нечего сказать по существу, он не способен сообщить ни о чём интересном. Его интересует только внимание к его персоне — и он будет делать что угодно, лишь бы обратить на себя внимание. Если вы ответите троллю, он полностью проигнорирует содержание вашего письма и напишет либо очередную глупость в ответ, либо просто вас обхамит. Если вы ему не ответите, он будет хамить ещё интенсивнее, пытаясь спровоцировать вас на грубость или необдуманное высказывание. Типичнейший приём тролля: если вы решили прекратить с ним разговор, он объявляет, что вы его испугались или что вам нечего ответить. Иногда обиженный отсутствием внимания тролль начинает систематически засорять форум мусором («флудить»). 
А вот решение, которое работает сейчас на моем блог. Идея гениальна свой простотой - надо всего лишь на фришный php хостинг разместить php файл, который будет принимать к себе всех посетителей, выкусывать их IP среди прочей информации и сравнивать с бан-списком. В случае, если юзер там найдется - php напечатает джаваскриптовый редирект, на страничку error.html. Редирект отработает в head блоке странички блога и как результат браузер отрисует эту страничку, а там будет написано в терминах blogspot - извините, но соответствующей странички нет!

Как узнать свой IP (чтобы поэкспериментировать) можно тут.

Хостинг бесплатный нашел тут.

Айпишку Тролля можно узнать, сопоставляя время коммента, когда он отправлен и время обращения к счетчику, один из которых использую на своем блоге.

Может кому-то пригодится.

Как выкачать репозиторий с историей из GoogleCode, отфильтровав его по проекту

Помогли мне в этом несколько статеек.


Спасибо Авторам за то время, которое они затратили на поиск решения и публикацию в блоге. Так же и гуглу спасибо. Я тоже немного времени инвестирую на написание этого поста заметки.

Что мне надо было сделать? Надо было выкачать из GoogleCode svn репозиторий с историей. Раньше я уже решал это, но как оно часто бывает, что-то поломалось и это решение больше не подходит. Пришлось искать другое. И оно нашлось.

Итак еще раз. Есть GoogleCode репозиторий. Я хочу получить его на локали, чтобы потом отфильтровать некоторые ревизии и потом всю историю смерджить в основной git репозиторий.

Поехали. Проект находится в https://kpi-java-training.googlecode.com/svn/trunk/BattleCity, причем корень репозитория https://kpi-java-training.googlecode.com/svn.

Нам понадобится Subversion 1.7.9 (у меня Windows 64-bit) от CollebNet.
// Создаем пустой репозиторий находясь в E:\JavaForFun\
svnadmin create all

// создаем файл в E:\JavaForFun\all\hooks\ с именем pre-revprop-change.bat и содержимым exit /b 0
cd all
cd hooks
echo exit /b 0 > pre-revprop-change.bat

// возвращемся назад
cd ..
cd ..

// синхронизируем репозиторий
svnsync init file:///E:/JavaForFun/all https://kpi-java-training.googlecode.com/svn/
svnsync sync file:///E:/JavaForFun/all 

// далее наблюдаем, как ревизия за ревизией все сливается к нам на локаль
// ...
// Copied properties for revision 753.
// Transmitting file data ...
// Committed revision 754.
// Copied properties for revision 754.
// Transmitting file data ....
// Committed revision 755.
// Copied properties for revision 755.
// Transmitting file data ...
// Committed revision 756.
// ...

// После можно сделать дамп (обрати внимание, тут путь обычный, а не file://)
svnadmin dump E:/JavaForFun/all> all.dump

// видим, как дампятся ревизии..
// ...
// * Dumped revision 726.
// * Dumped revision 727.
// * Dumped revision 728.
// * Dumped revision 729.
// * Dumped revision 730.
// ...

// фильтруем из бекапа all.dump в battlecity.dump только ревизии проекта находящегося в /trunk/BattleCity
svndumpfilter include /trunk/BattleCity < all.dump > battlecity.dump
Так случилось, что из бекапа svnadmin не хотел поднимать репозиторий. Говорил, что нет папки trunk, потому мне пришлось открыть его в текстовом файле и в конец описания ревизии 1
Revision-number: 1
Prop-content-length: 112
Content-length: 112

K 7
svn:log
V 38
This is an empty revision for padding.
K 8
svn:date
V 27
2012-02-15T12:21:42.764614Z
PROPS-END
Добавить это
Node-path: trunk
Node-kind: dir
Node-action: add
Prop-content-length: 10
Content-length: 10

PROPS-END
Кстати, в процессе фильтрации создается множество ревизий с описанием "This is an empty revision for padding." не содержащих ничего.
Revision-number: 5
Prop-content-length: 112
Content-length: 112

K 8
svn:date
V 27
2012-02-16T18:37:15.998497Z
K 7
svn:log
V 38
This is an empty revision for padding.
PROPS-END
Их можно в dump файле удалять, только при одном условии, что все порядковые номера, последующих после удаленного блока ревизий будут продолжать ряд - "без единого разрыва" :).

Возможны ошибки в процессе поднятия зачищенного бекапа, сообщающие, что такой-то ревизии N нет. Нужно найти ссылку на нее в дампе и изменить на новый номер.
Revision-number: 761
Prop-content-length: 323
Content-length: 323
...
PROPS-END

Node-kind: dir
Node-copyfrom-rev: 760 (Вот оно! - мне пришлось изменить это число на 50 потому как я удалил 710 пустых ревизий)
Node-copyfrom-path: trunk/BattleCity/test
Node-path: trunk/BattleCity/com.javatrainee.tanks.test
Node-action: add
Content-length: 0
Немного рутины, но это мне позволило избавиться от 600 пустых ревизий (тогда как мне нужно всего 53).

После я смог продолжить...
// поднимаем репозиторий из бекапа
svnadmin create battlecity
svnadmin load --ignore-uuid E:\JavaForFun\battlecity < battlecity.dump

// наблюдаем 
// ...
// ------- Committed revision 55 >>>
// <<< Started new transaction, based on original revision 56
// ------- Committed revision 56 >>>
// <<< Started new transaction, based on original revision 57
// ------- Committed revision 57 >>>
// <<< Started new transaction, based on original revision 58
// ------- Committed revision 58 >>>
// ...
После этого я имел на руках репозиторий, с которым мог уже работать с git

пятница, 19 апреля 2013 г.

Жизнь в коробке


Сегодня друг дал посмотреть это видео. И зацепил немного. На 6й минуте прервался и понесся в скайп делиться своими переживаниями.

Друг сказал:
"я часто вижу демотивированных программистов, когда закрывается проект. единственное, что я им говорю, что мы люди нанятые, наше дело копать как заключенные."
И где-то я его понимаю, поскольку был на таком месте и не раз - проект, на котором я работал, и который в последствии считал своим (иначе как бы я мог себе позволить засиживаться до раннего утра) закрывался, а команду распускали. Тут под проектом я подразумеваю не только цельный проект, но и какие-то его части - модуля. Заказчик говорит - надо это, мы запленились и пошли пилить, запилили, показали, отпраздновали успех, а потом он говорит - это уже не надо. Постойте, а как же бессонные ночи? Как же все то время, что я не провел с семьей? Ну да, я получил свои деньги, но, простите, оно (время) стоит в 1000 раз дороже. Часов в моей жизни всего (дай Бог) 700 000, и это куда меньше всех тех денег, которые я смогу заработать.

Это был первый кризис, выход из которого заставил выйти из коробки проекта. Так я стал работать на всю компанию. Если в компании есть ребята, которым я могу помочь (делать то, что скорее всего закроется), то я буду делать это для них. Так я стал делиться экспертизой между командами, а еще чинил инструмент, готовил новый.

Продлилось это не долго. Наступил второй кризис. Увольнение из компании, которую я считал своей. И хоть, причиной был я сам - так как мне представили выбор: либо так и с нами, либо как хочешь, но сам, все равно меня это выбило из привычной колеи. Этот выбор и был моим вторым переломным моментом - некогда крепкое понятие "мы" перестало иметь очертания конкретного офиса.

Сохранив установку "если есть в компании ребята, которым могу помочь - буду этим заниматься" пришлось переопределить термин "компания". Теперь это вся айтишная тусовка.

Тут же появился огромный выбор, чем именно заниматься в айти - поскольку от компании в 30 человек я вдруг попал в команду на два порядка большую. То, что я мог делать в прошлой компании всего пару часов в неделю тут я могу делать 24 часа в сутки - и мне при этом понадобится помощь. Выбрал тренинги. Ими и занимаюсь.

Так о чем это я? А вот о чем... (сам рисовал :))



Кто-то скажет, никакой коробки не существует - и будет прав. Но чтобы понять это надо из нескольких вылезти...

Но если вернуться к заключенным которых заставляют копать ямы, а потом закапывать. Вероятно им стоит найти новый смысл (вылезти из коробки) в том бессмысленном, что их заставляют делать. Например - махание лопатой - это физический труд, укрепляющий организм, и можно заняться бодибилдингом. Я уже слышу от критиков про плохое питание в тюрьме, что бодибилдинг при таких условиях не получится - и они правы... Но это еще одна коробка. Не получится это - получится что-то другое. Иначе смерть. Делать что-то бессмысленно - для меня и есть смерть, смерть при жизни.

Много людей, живучи на свободе живут еще хуже чем в тюрьме. "И вроде жить не тужить.... так откуда взялась печаль" (с) Виктор Цой вспоминается. По моему они потеряли смысл в жизни. Вот, вчера гуляли и видели девочку одну. Любой нормальный человек не стал бы с ней общаться - скажет опустившаяся, мне противно. И наверное будет прав в контексте свой коробки. Но внутри нее целый мир, в котором она сама запуталась. Входом видит конец света. Для себя. И пробовала, судя по шрамам на руках...

Так же было и старичком, алкоголиком, которого только что (по его словам) сын с кулаками выгнал из дому. Он жаловался на жизнь, говорил, что в прошлом он заслуженный майор и все для семьи всегда делал, а сейчас все от него отвернулись. Вот и пьет... Но пить-то он начал раньше, когда в семье еще было все хорошо. Нехорошо было там, у него в коробке. Он это начал чувствовать и стал глушить. Глушить химией. Это тупик. Это забиться в угол захламленной коробки и ждать когда все закончится...

Я тут позволю себе прилепить спиральную динамику. Как той молодой девочке, так и этому пожилому майору нужен следующий виток. Думаю в их случае им помогла бы какая-то религиозная секта. Вопрос другой, как потом извлечь человека из такой секты. Но это следующая коробка.


Правду говорят - одна картинка 1000 слов стоит...

Попробую подсуммировать - то, что называется черной полосой, это дурной запах в коробке, в которой мы засиделись. Проще забиться в угол и переждать, пока все проветрится. Я сам так часто делаю. Но есть и другой выход.

Ну вот, вроде как и выговорился... Стало легче... Досмотрю, что-ли видео...

вторник, 2 апреля 2013 г.

Как в VirtualDub открыть любой файл

Какая классная тулза VirtualDub, но насколько ограничена в том, какие файлы можно в ней редактировать. Но как сказал один умный человек - все ограничения у тебя в голове, Саня. И вот сегодня я поставил это знание в моей голове под сомнение. И нашлось решение.

Простое как двери. Если файл 1.xyz не хочет открываться в VirtualDub, но при этом проигрывается в обычном плеере на компьютере (т.е. кодек есть), то значит стоит создать рядом с 1.xyz текстовый файлик 1.avs с содержимым

DirectShowSource("1.zyx")

и уже его открывать в VirtualDub.



Вот и вся магия...

Так же понадобится K-Lite Codec Pack или любой другой пак кодеков...

понедельник, 1 апреля 2013 г.

Мысль не бумеранг

Шел я себе по улице, щелкал фотиком. Вижу Бабушка с лопатой управляется. Непорядок. Старенькая она. Развернулся, отобрал лопату и приобщился к решению ее проблемы. Она занималась тем, что делала проток для воды накопившейся на троуаре



И проблема как оказалось была не ее, а общая, только вот она единственная из всех прохожих решила взять дело в свои руки. Говорила, что довоенная она, еще той закалки потому и орудует лопатой... Народ нынче не тот, дети не те - говорит. Ну как не те? А мы с вами?.. Говорит не то - раньше все такими были... Ну понятно...



Задача пустить воду по желтому маршруту с такой же скоростью, с которой она истекает из дворов, а по красной пустить пеших ходов.

Разговорились. Бабушка оказалась приятным собеседником. Это все-то привыкли что бабушка это что-то, что не стоит брать во внимание. А по моему 80 лет опыта это не просто так.... В общем мне было интересно и полезно не только для души но и с точки зрения физических упражнений...



Где-то за полчасика была готова и канавка и тропинка для пеших ходов... Причем для этих самых пеших ходов приходилось оптимизировать тропинку, поскольку та, что была сделана изначально не была интуитивно им понятна - надо было сделать всего лишь два шага в сторону, а они не делали. Пришлось делать вторую.

Люди очень интересный вид. Они все спешат. Причем спешат настолько, что сильно напрягаются от того, что им приходится 10 секунд ждать пока мы с Бабушкой их пропустим. Слышали мы с Бабушкой от "Пустите, я спешу!" до "Это вам надо было делать раньше". Прохожие не знали, что мы не дворники :) Обычно они просто проходили мимо даже не обращая внимания на то, что мы были на их пути. Но кто-то все же советовал, как нам надо было делать то, что мы делаем. Кто-то критиковал... Бабушка конечно же не оставляла комментарии прохожих без своих контркомментариев :) А я молча махал лопатой, даже после того, как Бабушка решила "Та пошли они все - пусть тонут!"

"Махал" я по простой причине. Я это делаю для себя. Казалось бы, какая польза от бултыхания в весеннем компоте с собачих какашек? Тем более, что это не оценят. Все просто - то что я делал по пути с моими ценностями. Старичкам надо помагать. То что я делаю поможет кому-то еще. А я физически разомнусь. Да и выскочил на пол часа из общего потока. Ну и если честно - меня это забавляло - в детстве я очень любил весну, речушечки, кораблики...

А еще говорят, что делаешь - то и возвращается. Почти, но не совсем. Дело в том, что оно никогда и никуда не выходит за пределы моей черепной коробки - оно на всю жизнь записывается в нейронных хитросплетениях мозга - это есть мой опыт. Обидел Бабушку - и все - в моем мире Бабушек обижают. Когда-нибудь, в какой-то ситуации, этот мой опыт будет очень даже решающим. Как вот для этого морского Льва в мультфильме "Делай ноги 2".


Ничего не возвращается никакми бумерангом, все навсегда остается в моем опыте. А прошлый опыт определяет мое будущее. Настоящее нужно лишь для того, чтобы формировать этот опыт.

Радует одно, опыт - это маховик. Каждый день всего лишь чуть-чуть прибавляет ему скорости... Всегда можно начать делать что-то новое (что с ценностями по пути) или перестать делать то, что уже делаешь (что с ценностями не по пути).

Как-то так...