Tuesday, November 27, 2012

Baby steps in Clojure. Правдивый ли random в Java?

Недавно Санек скинул интересную статью про нерандомные рандомы в php http://boallen.com/random-numbers.html.
Вот решил побаловаться и проверить рандомный ли рандом в java :)

Сделаю тоже самое, что сделали ребята на пхп, только на Clojure, то есть сгенерирую (x * y) вариантов рандома (0 или 1), и, если выпадет 1, то нарисую точку на экране с координатой (x, y).

Для начала определю функцию, которая будет считать рандомы.

(defn rands [max-x max-y]
  (for [x (range max-x) y (range max-y)
        :let [rnd (cond (< (rand 1) 0.5) 0 :else 1)]
        :when (= rnd 1)
        ]
    [x y rnd]))


Что здесь:
- Входные параметры max-x и max-y
- Перебераем все сочетания (0..max-x : 0..max-y) и отбераем только те значения, рандом которых вернет 1. Выражение (cond (< (rand 1) 0.5) 0 :else 1) должно вернуть нам 1 или 0 с вероятностью 50%
- Возвращаем последовательность из векторов, состоящих из x, y, rnd. Где x, y - переменные, по которым итерируемся, rnd - рандомное значение (уже отфильтрованное ограничением :when)

Проверяю. Запускаю в REPL:

Вроде похоже на правду - возвращает значения x и y только для рандома, равному 1.

Теперь выведем на экран (по примеру, взятому из книжки Joy of Clojure). Запускаю в REPLe команды:
(def frame (java.awt.Frame.))
(.setSize frame 512 512)
(.setVisible frame true)
Что здесь:
- Определяем переменную frame, которой присвоится значение нового экземпляра java.awt.Frame. На Java это выглядело бы как Frame frame = new java.awt.Frame();
- Устанавливаем размер frame 512 x 51. Java: frame.setSize(512, 512);
- Делаем фрейм видимым. Java: frame.setVisible(true);

Крутизна в том, что не надо перекомпиливать приложение! Результат выполнения команд виден сразу же.

Вот как это выглядит из Идеевской консоли REPL. Я использую плагин La Closure для IDEA.


Появилось пустое awt-шное окошко, в котором и будем рисовать:


Теперь осталось совсем малость - нарисовать. Опять же в REPLe запускаю такие команды:

(def gfx (.getGraphics frame))
(doseq [[x y rnd] (rands 512 512)]
  (.fillRect gfx x y 1 1))
Что здесь:
-  Определили gfx, который равен graphics у frame. Java: Graphics gfx = frame.getGraphics();
- Проитерировались по списку, который нам вернет вызов функции (rands 512 512) 
-  Помним, что rands возвращает вектор из переменных [x, y и значение рандома rnd]. Значения x,y и рандома присвоятся в локальные переменные x,y,rnd соответственно. Такая форма в Clojure называется  деструктуризация (destructuring).
-  Для каждого элемента списка заполним единичный rectangle в координате x, y

Вот что получилось на экране:


Важно помнить, что изображение в awt-шном окошке "одноразовое". То есть оно исчезнет как только мы перекроем awt-шный фрейм другим окном или же свернем/развернем его.

Так что псевдорандом в Java похож на рандом. А Clojure + REPL - прикольная вещь!

Весь код целиком ниже. Тоже самое на Java наверняка потребовало бы чуть больше кода, но повторять это на Java уже не хочется :)

(defn rands [max-x max-y]
  (for [x (range max-x) y (range max-y)
        :let [rnd (cond (< (rand 1) 0.5) 0 :else 1)]
        :when (= rnd 1)
        ]
    [x y rnd]))

(def frame (java.awt.Frame.))
(.setSize frame 512 512)
(.setVisible frame true)
(def gfx (.getGraphics frame))
(doseq [[x y rnd] (rands 512 512)]
  (.fillRect gfx x y 1 1))

Thursday, November 08, 2012

Играем в тетрис на C#. Запуск на Visual Web Developer Express 2010

1. Установка Visual Wеb Developer 2010 Express.

Если подходящая версия Visual Studio 2010 уже установлена, то этот этап можно пропустить :).

Запускаем инсталлер, ставим. Я устанавливал отсюда.

Ниже картинки того, что происходило на экране во время установки.

IIS и Web Deploy еще понятно, но зачем мне SQL Server ставить :)?

Ладно, жму Install. Просит пароль sa для SQL Server.

Пустой пароль, как и 123 - не подходят :)

Качаем, ждем :)

2. Устанавливаем NuGet package manager

Открываем окно Extension Manager из меню Tools->Extension Manager...


Если NuGet Package manager не установлен, то ищем его в Online Gallery и устанавливаем


3. Стартуем

Скачиваем щаблон проекта http://codenjoy.com/files/tetris-servers.zip

После распаковки открываем проект в Visual Studio. Проект находится в <unpack folder>\tetris-servers\tetris-servers\csharp\nancy

Открываем Package manager console

и запускаем команду Install-Package Nancy.Hosting.Self

Если ошибок нет, то можно подключаться к игре.

Sunday, October 28, 2012

Красивый file upload с jQuery

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

jQuery File Upload 

Проект лежит здесь: https://github.com/blueimp/jQuery-File-Upload
Примерчики здесь: http://blueimp.github.com/jQuery-File-Upload

Пример. Ниже реализована загрузка файла с прогресом. Будет одна кнопка Upload, которая позволит выбрать файл и сразу загрузить его на сервер.

1. Скачиваем.

Скачиваю отсюда https://github.com/blueimp/jQuery-File-Upload/downloads, распаковываю архивчик.

2. Копируем javascript и css файлы в свой проект.

Я буду пользоваться минимальной установкой, поэтому в свой проект копирую только некоторые файлы. Ресурсы моего проекта находятся в папке webapp/resources, в нее копирую следующие javascript файлики из архивчика:
- js/vendor/jquery.ui.widget.js
- js/jquery.iframe-transport.js
- js/jquery.fileupload.js
- css/jquery.fileupload-ui.css

Подробнее о минимальной установке здесь: https://github.com/blueimp/jQuery-File-Upload/wiki/Basic-plugin

3. Добавляем Bootstrap и jQuery

3.1. Файлик с jQuery берем здесь http://jquery.com/download/ и добавляем в проект.
3.2. Bootstrap берем здесь http://twitter.github.com/bootstrap/index.html. Добавляем файлы:
- css/bootstrap.css
- img/glyphicons-halflings.png
- img/glyphicons-halflings-white.png

4. Создаем страничку

Красиво отобразить JSP страничку в блоге не получилось, поэтому даю ссылку на файл jsp.
Полный текст JSP странички можно посмотреть здесь.

5. Пишем сервлет загрузки

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

Wednesday, October 24, 2012

Unit тесты с embedded Jetty

Частенько хочется проверить обращение к внешнему HTTP серверу. Раньше я пользовался встроенным в JDK http сервером (см пакет com.sun.net.httpserver). В этом случае тест работает быстрее, но вытаскивать параметры из http запроса приходилось писать самому.

Я попробовал запустить embedded Jetty сервер в тесте, в котором создать сервлетик, который запоминает приходящие параметры реквеста. Вот что получилось.

Сам тест
Реализация фейкового сервера

Зависимости

Полностью проект можно скачать тут

Интересно
Если будет использоваться асинхронная отсылка http запроса из теста, то синхронизировать сам тест с обработкой запроса можно с помощью метода FakeServer.waitForResponse.
Вот интересная статья про семафоры http://www.baptiste-wicht.com/2010/09/java-concurrency-part-5-monitors-locks-and-conditions/

Friday, October 05, 2012

Динамическая конфигурация Java Security Policy в Jetty

Задача

В рамках моего веб приложения надо умудриться задеплоить еще один war, на котором будет работать какой-то сервлет. Поскольку этот war - это стороннее веб приложение, то надо запретить ему доступ к файловой системе, открытие сокетов и тем более вызывать System.exit.
Подобная задача легко решается в OSGi контейнере (пример на OSGi тут). Но у меня Jetty и необходимо очень тупое простое решение.

Предположим в этом "левом" веб-приложении какой-нибудь умник решил проверить систему на прочность и написал такой код:

Естественно, что при вызове сервлета  System.exit сделает свое дело и погасит мой сервер.

Деплоим стороннее веб приложение

Прежде всего надо убедиться, что модули jetty-webapp и jetty-server подключены к проекту. У меня версия Jetty 8.1.3.v20120416



Дальше пишем код деплоймента веб архива в Jetty

Если задеплоить этот код в любой web container, то как только мы дернем страничку из браузера, то все...

Настраиваем Java security manager

Самый тупой способ, который я нашел - это подставить свою реализацию java.security.policy:
Надо обратить внимание на, что Policy надо устанавливать ДО того, как переопределить SecurityManager, иначе не хватит прав для установки новой Policy :)

Thursday, September 20, 2012

Git: Как пофиксить detached HEAD

Если git при комите ругается, что у вас detached HEAD, то пофиксить можно 4-мя командами:

git branch temp
git checkout temp
git branch -f master temp
git checkout master

И, опционально,
git branch -d temp

Что при этом происходит
1. создаем временную ветку с текущего положения HEAD
2. переключаемся на временную ветку
3. сбросить master до позиции в temp
4. переключиться на мастер
5. удалить временную ветку

Tuesday, September 18, 2012

Tetris coding dojo. Включаем мозг. Включение #0.

О чем это

Сейчас трудно найти программиста, который не знал бы, что такое ТДД или рефакторинг. Трудно найти такого, который еще и применял бы эти практики в жизни. Мне, например, повезло и я ощутил полезность всего спектра так называемых "инженерных практик" в реальной разработке. Многие ребята не могут похвастаться таким везением. Естественно, что не попробовав применить, например, ТДД на практике, сложно сделать какой-нибудь вывод о его полезности.
Конечно же есть масса тренингов по инженерным практикам. Но проблема в том, что практические задания на  подобных мероприятиях довольно простые. На них мы можем только отработать базовые навыки. К тому же приходится давать довольно много теории, рассматривать различныые варианты решения задачи и подводить слушателей к правильным теоретическим выводам. Не хватает практического подтверждения (или опровержения :)) правильности сделанных выводов.
Решение этой проблемы пришло само собой:

Tetris Coding dojo

Вообще Coding dojo - отличное и веселое мероприятие. Мы (я и Саша Баглай) подумали, что это подходящий формат для того, чтобы попрактиковаться в применении своих мозгов навыков в инженерных практиках. Мы одолжили идею coding dojo и сделали свой фреймворк.
За основу взяли известную всем игру - тетрис. Будем учить компьютер играть в тетрис! Мало того, мы еще будем соревноваться в том, кто круче это сделает :)

Думаю, что лучше один раз увидеть, чем написать 100500 слов описания.

Пробное включение

Недавно мы с Сашей попробовали сами написать код управления фигурками. Это мероприятие выбило нас из жизни часа на 4 :). В результате пофиксили несколько багов во фреймворке. Я же научился расставлять "палочки" и "квадратики", сделал несколько небольших рефакторингов и окончательно убедился, что я тестозависим :).

Код тетриса лежит на гитхабе, написан на java. Запускается одной командой (mvn jetty:run). Чуть позже напишу подробную инструкцию (если не поленюсь:)). Велкам с коментами, пожеланиями и участием.

Saturday, September 01, 2012

Вспомнил детство : ZX Spectrum, деревянные игрушки...

Говорят, что нереализованные детские мечты нужно осуществлять, ибо они как-то там мешают во взрослой жизни. Так вот, когда деревья были больше, трава зеленее, а самая навороченная компьютерная игра требовала 48Кб памяти и 0.8 Мгц частоты ЦПУ, у меня была идея фикс - победить злостных инопланетянских роботов-захватчиков в стратегической реал-тайм (!) игрушке "Nether Earth". Я бился в нее сутками, но эти гады все равно беспощадно уничтожали мою базу. Естественно, что это сказывалось на моем эмоциональном состоянии, успеваемости в школе и вообще надо было утереть нос моему товарищу, который эту игру якобы прошел.

Настало время реванша. 

Первым делом нужен эмулятор ZX Spectrum. Их как оказалось довольно много, вот хотя бы список эмуляторов под Видновс.
Но мне не нужны легкие пути, я взял эмулятор под Java  - JSpeccy :). Не беда, что сайт разработчика на испанском, зато он регулярно выпускает обновления (последнее было в июне 2012 года!) в отличие от остальных. 

Найти саму игру тоже оказалось несложно. На сайте Bit 16 я быстро нашел Nether Eath.

Запустил как обычно из командной строки
java -jar JSpeccy.jar 

Круто - появилась строка ввода! Правда в ZX Spectrum она замаскирована под название компании - разработчика ;)

Дальше в меню File->Load... выбираю файл образа игры

Ожидал, что игрушка сразу запустится, но этого, естественно, не произошло :). В Синклере игры считывались с магнитофона, для чего нужно ввести команду LOAD "". Магическое нажатие на клавишу J выдало команду LOAD, а <Ctrl> + P вывел двойную кавычку.

Нажал на <ENTER> и пошла загрузка. Жаль, что звук с магнитофона не сэмулировали :)

Чудесная заставка, офигительный звук :). Без всяких звуковых карт и музыкальных сопроцессоров! Частота колебаний динамика программируется ручками :).


Запрограммировал клавиши, жму старт. Вот она - сила 3D графики! Никаких графических сопроцессоров и видеокарт. Почти "реал 3d" :).

На экране
1. Контрольный модуль, может летать и садиться на базу
2. База

На базе можно создавать роботов из имеющихся деталей. Количество деталей ограничено и поставляется заводами.

Создал первого супер робота

И выпустил его из завода

Роботом можно управлять непосредственно или запрограммировать его поведение.


Варианты поведения
- Пройти вперед / назад
- Найти и уничтожить вражеского робота / фабрику / вражескую базу
- Найти и захватить нейтральную  фабрику / вражескую фабрику / вражескую базу

Я задал команду захватить завод. После того, как робот постоит на заводе 10 сек, завод считается захваченным, о чем свидетельствует появившийсе вверху слева американский флаг :).

Что особенно меня убивало в этой игре - так это управление во время боя. Для того, чтобы повернуться нужно выбрать "Move robot", а дойдя до огневой позиции успеть остановить робота, выбрать оружие для стрельбы и стрельнуть. Жутко неудобно, особенно когда по тебе стреляют несколько вражеских машин.

Вот такая нехитрая игрушка. Для середины 80х это была мега крутая игра. А сейчас даже не верится, что на 48кб можно разместить саму игру с "3д" графикой и звуком.

Кстати, вчера играл 3 часа подряд, но мою базу опять захватили подлые инопланетские роботы :(

Monday, August 20, 2012

Coding dojo. Установка сервера на PHP.

Ниже инструкции для установки локального сервера coding-dojo для Apache (рекомендуемая) и для расширения sockets.

Настройка локального сервера на Apache + php.

Для того, чтобы воспользоваться этой конфигурацией необходим настроенный Apache + php. Как я настраивал можно почитать здесь

1. Скачиваем шаблон php скрипта отсюда и подкладываем его в любое место, доступное apache. В моем случае это Z:\home\calculator\www\solver.php 

2. Проверка локального сервера.
Теоретически все готово. Проверить можно, запустив скрипт с примером запроса. Например: http://www.calculator/solver.php?q=what+is+the+sum+of+8+and+27

Должны увидеть тело запроса в браузере. Примерно так:

Рядом с solver.php должен создасться файлик requests.txtс содержимым запроса:

Дальше регистрируем нового игрока. В качестве URL надо ввести адрес, по которому доджо сервер запустит скрипт solver.php. В моем случае это  http://www.calculator/solver.php.
Идем  сюда.

Установка локального сервера, работающего на расширении sockets 

1. Установка локального сервера.
Скачиваем архивчик отсюда. Это содержимое репозитория со старт-поинтами взятый отсюда
https://github.com/bodil/extreme_startup_servers.
Распаковываем (у меня в папку C:\workspace\projects\dojo-startup\extreme_startup_servers).

В папке php/sockets находится 2 файлика : server.php и solver.php

Важно!
Сервер требует расширения php_sockets. Для этого строка extension=php_sockets.dll в файле php.ini должна быть раскоментирована.

2. Запуск локального сервера.
Запускаем server.php из командной строки:
php server.php

Если при запуске не подключается расширение php_sockets, то см. ниже "что делать..."

3. Проверка локального сервера.
Наш локальный сервер запущен. Не мешает проверить как он работает. Для этого в браузере вводим такой линк http://localhost:9000/?q=what+is+the+sum+of+8+and+22.

По идее в консоли должно появится сообщение с запросом и ответом на него:

Если посмотреть содержимое файла solver.php, то понятно почему ответ такой же как и запрос :)

3.1. Немного модифицированный файл solver.php находится здесь. Он записывает все входящие запросы в файлик, что очень удобно во время соревнования.

Дальше  регистрируем наш сервер в системе. Описано здесь.

Регистрация нового пользователя на доджо сервере.

Теперь можем регистрировать наш сервер. Переходим на страничку хоста (http://localhost:3000 или в случае другого компа – IP адрес этой машины), нажимаем I want to play и вводим имя (латинскими буквами!) и URL вашего сервера. 



Если хост смог достучаться до сервера, то увидим примерно такую обнадеживающую надпись

Можем посмотреть результат работы нашей программы. Поскольку мы еще ничего не запрограммировали, то ожидаем примерно такую картинку:
В консоли локального сервера будет примерно такое (в случае с сервером на sockets extension)

В лог request.txt файле будет примерно такое:

В принципе можно уже начинать программировать solver.php так, чтобы он давал адекватные ответы :)

Что делать, если...

Что делать, если не запускается php_sockets?
Если при запуске server.php выдается подобная ошибка, то нужно скачать соовместимую версию библиотеки php_sockets.dll.

Эта ошибка у меня полечилась скачиванием и установкой расширений денвера (http://www.denwer.ru/packages/php5.html).
Второй вариант лечения - скачать zip с пакетом пхп отсюда и скопировать php_sockets.dll в папку расширений php.

Saturday, July 28, 2012

PHP для бабушек. Ставим Symfony.


Что такое Symfony? 
Клевый ответ на этот вопрос на сайте разработчиков: "Symfony - это PHP Web Development framework. Что тут неясно? А если неясно, то проще считай, что это религия!" (framework + philosophy+comunity)
Не веришь? Можешь сам перевести отсюда http://symfony.com/what-is-symfony :)

Попробую пройти "обряд крещения". Как обычно расписано по шагам для старичков с хреновой памятью типа меня :)
Вот инструкция по установке и использованию. Я просто следовал ей.

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

1. Установка

Модный способ - через композер. Как поставить композер, описано здесь.
В рутовой папке проекта (у меня это w:\home\calculator\www) запустить такое  (я запускал из гитового баша как обычно):

php composer.phar create-project symfony/framework-standard-edition Symfony/

Нифига не заработало на домашнем компе, но заработало на рабочем. Поэтому следующий вариант такой:

Скачиваю отсюда http://symfony.com/download Symfony Standart и распаковываю в рутовую папку. В руте у меня появится папка Symfony
w\
|-calculator
  |-www
    |-Symfony



Запускаю в папочке w:\calculator\www\Symfony (с баш строки как обычно)
php bin/vendors install

далее идет непериводимая игра слов выдаваемых скриптом и гитом.
Появилась папочка vendor. Сюда Symfony понапихивало массу полезностей.
Все эти полезности описаны в файлике Symfony\deps. На 11м слайде презенташки можно увидеть как он выглядит.

Проверяю. Открываю в браузере * http://www.calculator/Symfony/web/config.php. Вижу страничку конфига.
* www.calculator я добавил в файл Windows\System32\drivers\etc\hosts. Подробнее здесь.


Тут он мне предлагает поделать всякие усовершенствования типа поставить акселератор, что-то поменять в php.ini. Естественно забиваю на эти сообщения - они мне жить пока не мешают.



2. Создаю свое приложение.

Тут я перепрыгнул на слайд 32. Сначала хочу создать приложение, а потом залить его в git.

Создаю бандл
в папке Symfony запускаю php app/console generate:bundle

Ввожу имя нейпспейса (Tdd/CalculatorBundle) и имя бандла (Calculator).

Дальше куча вопросов, на которые просто жимаю <Enter>

Бандл - это директория со всем, что нужно для фичи. Вот такое мне сгенерилось:


3. Смотрим на тесты

Генератор бандлов также создал папку с тестами

В ней находится один тест на контроллер

Запустить этот тест вместе со сьютом можно из корневой папки Symfony. Запускаю команду
phpunit -c app/
 параметр -c указывает конфигурационный файл для phpunit.

Почему надо запускать тесты с опцией -c?
Тест на контроллер создает и запускает симфонийский кернел со всеми зависимостями. В файле app/phpunit.xml.dist есть ссылка на bootstrap, который делает предварительную инициализацию окружения. 


Настройки Netbeans для запуска тестов
Чтобы мои тесты запускались прямо в Netbeans я сделал следующее:
- Указал где лежат тесты (окно Project properties, пункт Sources)

- Выбрал phpunit.xml.dist в качестеве XML Configuration для тестов (окно Project properties, пункт PHPUnit)

Теперь мои тесты запускаются также из ИДЕ: