Если дата начала действия записи файла позднее даты окончания действия записи справочника с датой начала действия ранее даты начала действия записи файла, дата окончания действия записи файла ранее даты начала действия записи справочника, которая позднее даты начала действия записи файла, и дата окончания действия записи файла или записи справочника непустые, то контроль пересечения дат включённых и условно включённых записей КБК пройден успешно.
Меня учили дефайнить всякие непонятные числа-константы, чтобы потом в случае чего не искать по всей программе, а справиться с заменой за секунду. Так вот, при виде этой строчки я понял, что столпы мироздания могут и пошатнуться:
Как-то в бытность свою молодым самоучкой-программистом изучал я строение разделов диска и файловой системы, для чего понадобилось сдампить с винчестера первые секторы. Для этих целей я быстренько наваял программку на Си со вставкой на ассемблере с обращением к биосовскому прерыванию int 13h и вызовом соответствующей функции чтения сектора. Программа готова, работа пошла. И тут до меня медленно доходит, что вместо номера функции чтения я вроде бы вставил номер функции записи. Быстро останавливаю программу, гляжу в исходник. Так и есть: загрузочный сектор, таблица разделов и первые мегабайты винта тупо затёрты рандомными данными. Винда пока работает, но уже ясно, что повторно загрузиться не сможет.
В дверях появился заядлый друг с острым желанием поиграть в Half-Life, свежий шедевр игростроя. Мне надо было убегать, и я предупредил друга: «Играй, но комп не перезагружай ни под каким видом!» Я не успел сохранить самые нужные данные: документы и исходники (в ту пору всё, скачанное из инета, бережно хранилось на винте).
По возвращении я застал печальную картину: комп, не перезагруженный, но намертво зависший, и печальный друг напротив монитора. Исходники потеряны, доки надо собирать заново.
Писал я как-то игру — чисто для души, проект некоммерческий. Так как в программе широко использовался объектно-ориентированный подход, то классов было море. Программа писалась уже довольно давно, и вне Студии я её не запускал, пока не надумал скомпилить и протестить релизную версию. Игра загрузилась, отрисовала карту, главного героя... который стоял, как истукан, решительно отказываясь перебирать ножками и идти, куда сказали. Подивившись, я запустил Студию, открыл проект и нажал F5 — игра запустилась, и герой бодро побежал к намеченной точке! Повторная проверка показала странную закономерность: герой соглашался выполнять указы только под бдительным надзором дебаггера Студии, вне родных стен которой он просто тихо стоял на месте.
Причина привязанности героя к дебаггеру крылась, впрочем, во вполне банальной ошибке. В конструкторе класса героя флажок Idle не был инициализирован значением false, и каждый раз, когда игра запускалась в дебаге, звёзды так удачно складывались, что на область памяти, где лежала эта переменная, приходилось нулевое значение. Когда же игру запускали в «полевых условиях», адреса менялись, и на флажок Idle попадал какой-то ненулевой мусор, который герой интерпретировал как true, то есть указание ничего не делать.
Играли мы как-то с другом в одну браузерную онлайн-игрушку. Месяца через три надоело совсем. Нарыли в инете бота для неё: сам кликает по карте и собирает бонусы, разбросанные по галактике. Бонусы мелкие, но если собирать их долго, можно неплохо подняться. Бот был написан одним из админов, и как только код утёк в паблик, на карте что-то поменяли, и болванчик стал кликать всегда в одну точку, а то и вообще не двигался, хотя на бонусы исправно щёлкал.
Вспомнили, что где-то не компе валялась ранняя версия известной программы, управляющей курсором мыши. Тогда там ещё не было всяких наворотов, только самые простые функции: клик в точку экрана, перемещение, двойной клик, подождать столько-то секунд. Стали тестировать. Опытным путём забили цикл зигзагообразных перемещений по карте и запустили кликер вместе с работающим ботом. Радости не было предела: он работал! Десять минут созерцания полной автоматизации сбора бонусных коробок пробудили аппетит, и мы пошли пить чай с ништяками. По возвращении нас постигло разочарование: сервер перезагрузился, соединение оборвалось, на экране всплыло окошко с двумя кнопками: «Отмена» и «Подключиться снова». Бот кликал по серому экрану без всякого толку.
Решили предусмотреть такой вариант. Алгоритм был переписан: траектория изменена на более оптимальную, пересмотрены величины пауз между кликами, в середине и начале цикла добавлены три быстрых клика на окошки с ошибкой соединения и на кнопку переподключения. Потестировали с ручным отключением интернета — работает. Оставили всё это дело на ночь.
С утра бот продолжал летать. Остановили процесс, кликнули на ангар посмотреть, сколько насобиралось добра. Разочарование: при активности только на карте звёздного неба коннект с игрой терялся. Получалось, что кораблик летал на карте из кеша, и никаких данных на сервер не передавалось.
Была написана версия цикла 3.0. Добавлены клики на переключение окон Мозиллы, клик на меню ангара, клик на главную, переключение на вкладку с картой, продолжение сбора коробок. Все ошибки, зависящие от игры, были учтены.
Сбор коробок продолжался около трёх ночей. Богатство росло, а интерес уменьшался. Потом и вовсе перестали заходить в игру: комп ночью шумел слишком сильно.
Пришлось в студенческую бытность поработать аутсорсером. Работали совместно с парой приятелей; в итоге оттуда я ушёл на хорошо оплачиваемую работу, а вот приятели остались работать в той же сфере.
Как-то разбудил меня звонок часа в два ночи: мол, спасай. Хорошо, идти недалеко: захватил банку кофе, пару пива и отправился. Прихожу, вижу трёх человек в состоянии, близком к неадекватности: красные глаза и так далее. Три дня до дедлайна — понимаю. Писалось всё в спешке, потому часть кода была позаимствована на просторах паутины. Проблему описали быстро:
— Смотри: вот сокет. — Угу. — Вот этот отправляет, вот этот принимает. — Угу. — А теперь компилим. Запускаем — ошибка. — И? — Cтавим брейк, пошагово выполняем — работает.
Разбирались до утра. Курили матчасть, MSDN зачитали до дыр. Вроде всё правильно, но при выполнении программы неизменный error. Пошагово — как по маслу.
Ошибка нашлась, когда психическое здоровье было под угрозой. Буфер не передавал данные, пока не заполнялся полностью; чтобы передать неполный, нужно было вызвать метод flush(). При дебаге же по истечении определённого времени его вызов шёл автоматом.
Любая мистика при тщательном разборе мистикой быть перестаёт. Простите уж, верующие в духов в машине.
Летняя сессия. Внезапно в полный рост встала необходимость сдавать курсовую работу. Вообще-то на неё отводилось два месяца, но всё это время ваш покорный слуга проводил, как истинный студент, а именно пинал балду. Пояснительная записка с никому не нужной теоретической ерундой у меня была (на неё я время когда-то выделил), а вот программы не было совсем. До сдачи пять дней. Тема работы, к слову, была достаточно серьёзная: анализ данных с помощью искусственных нейронных сетей. Предполагалось, что тему эту я изучу сам (своего рода исследовательская работа в рамках курсовой). На тот момент я имел представление только о том, как работа этой самой сети выглядит со стороны — ознакомился на примере пакета Deductor.
Ну что же. За три дня ускоренно изучается загрузка данных из таблиц Экселя с помощью ADO (исходные данные для анализа, пожалованные мне преподавателем, хранились в .xls), пишется оболочка с нехитрым, но солидным интерфейсом, примерно повторяющим виденное в Дедукторе, и прикручивается пара фич для большей напыщенности. В следующие два дня с сайта BaseGroup скачивается прекрасная open-source-библиотека с компонентами, реализующими нейросети в Delphi, быстро вкуривается, прикручивается к проге...
И тут встает вопрос: а каким образом оцифровываются данные перед обработкой? Тем более, что они у меня и числовые, и строковые, и «дата-время». Помедитировав, изобрёл метод: для каждого поля считались все уникальные значения, запоминались порядковые номера этих значений и подавались на вход нейросети. То есть обучающий пример выглядел как-то так: «Если в поле_1 значение №1/5 и в поле_2 значение №2/19, то в поле_3 значение № 3/7». Очень неплохая «оцифровка» вышла! Жутко довольный собой, запускаю это дело на тестовый прогон. Что и требовалось доказать: средняя ошибка расчетов более пяти тысяч, что совсем уж некошерно. Кроме того, на выходе сеть выдаёт значения вида 9,999999 и только на седьмом знаке после запятой начинает варьировать цифры. А я-то думал, она мне сейчас такие же порядковые номера выдаст, как я ей позагружал. Наивный... Понимая, что изучить верный метод оцифровки данных за последнюю ночь я не успею, в дело пускаю что? Конечно, Великий Рандом. Конечно, спрятанный табуляцией куда подальше за экран.
В итоге программа моя честно открывала базу данных, долго и солидно загружала данные, давала настроить параметры нейросети и столь же честно, долго и старательно обучалась на той лабуде, что я ей скармливал своей гениальной «оцифровкой». Когда же доходило до проверки результатов обучения, программа принимала предложенные ей номера значений из входных полей, выполняла честный расчёт результирующего значения, которое потом успешно забывалось, а в выходные поля подставлялись значения, банально выдернутые рандомом из исходной базы. Чтобы не палиться, что на одних и тех же значениях прога выдаёт каждый раз разные результаты, кнопка «Рассчитать» отключалась после каждого клика, а включалась обратно только после смены входных значений.
Вот эту прелесть я и сдал преподавателю. На защите проверялась только работа программы, без демонстрации исходников, поэтому всё прошло отлично. Теперь сижу и молюсь, чтобы никто не додумался сверять результаты моей программы хотя бы с тем же Дедуктором, иначе ко мне могут возникнуть о-о-очень интересные вопросы. А параллельно с молитвами я изучаю оцифровку данных — всё-таки совестно, а то что ж из меня за будущий специалист?
Если девушка вам говорит: «Милый, @#$, иди спать уже!», то её нужно слушаться.
Второй час ночи. PHP-код. Цикл, в котором должны выводиться из базы категории товаров. «Должны», потому что на самом деле выводится только последний элемент. Грешил на базу — двадцать минут проверял данные. Поубирал кучу условий выборки, оставив банальное WHERE 1. Потом просто закомментил всё внутри цикла и поставил вывод счётчика. Не помогает! Сношу всё, переписываю с нуля — работает. Возвращаю код назад и вижу такой ужас:
for ($i=0; $i<20; $i++);
Проверяйте наличие пустого оператора после цикла — сэкономит кучу времени!