Реферати

Дипломна робота: Забезпечення всесвітньої трансляції спортивних шахових змагань із застосуванням розробленого в ході проекту закінченого програмного продукту

Наука у формуванні картини світу. Наука випробує найсильніший вплив з боку навколишньої її зовнішнього середовища, і її розвиток визначається тим, наскільки культура сприйнятлива до наукових ідей.

Фашизм: ідеологія, політика і практика. Фашизм - це ідеологія і практика, що затверджують перевагу і винятковість визначеної чи нації раси, заперечення демократії, установлення культу вождя.

Міркуючи над сторінками розповіді Андрія Платонова "Маркун". Розповідь "Маркун" був названий по імені головного героя - молодого винахідника, - який знайшов мету життя, зрозумів її зміст.

Вірша 20. Вірша Автор: Твардовский А. Т. Дробиться рваний... Дробиться рваний цоколь монумента, Взвивает сталь відбійних молотків. Крутий розчин особливого цементу

Інфляція, її сутність і прояв 2. Тема № 5: Інфляція, її сутність і форми прояву План Уведення......3 1. Природа і причини інфляції......4 2. Форми і види інфляції......15

Зміст

Уведення

1. Загальна частина

1.1 Характеристика структурного підрозділу "Шаховий клуб"

1.2 Огляд шахових систем-прототипів

1.3 Аналіз достоїнств і недоліків

1.4 Технічне завдання на створення інформаційної системи "Шаховий клуб"

2. Спеціальна частина

2.1 Вибір основних методологій розробки програмного забезпечення

2.1.1 Каскадна методологія

2.1.2 Екстремальна методологія

2.2 Вибір інструментальних засобів

2.3 Змістовна постановка задачі створення СШПО

2.4 Розробка алгоритму рішення задачі

2.5 Опис розробленого програмного комплексу

2.5.1 Транслятор шахових партій

2.5.2 Реєстратор шахових партій

2.6 Тестові іспити й аналіз результатів

3. Техніко-економічне обґрунтування проекту

3.1 Доцільність і область застосування розробки

3.2 Розрахунок витрат на розробку спеціалізованого шахового програмного забезпечення

3.3 Розрахунок експлуатаційних витрат

3.4 Оцінка економічної ефективності проекту

4. Безпека і екологичность проекту

4.1 Безпека праці

4.1.1 Аналіз умов праці на робочому місці інженера структурного підрозділу "Шаховий клуб" ГОУ ВПО "Сибгиу"

4.1.2 Заходу для безпеки праці

4.2 Надзвичайні ситуації

4.2.1 Електробезпечність

4.2.2 Пожежна безпека

4.2.3 Організаційно-штатна структура по ГО і ЧС

4.2.4 Надзвичайні ситуації, що можуть виникнути на території ГОУ ВПО "Сибгиу"

4.2.5 Способи оповіщення при ЧС

4.2.6 Дії по видах повідомлення при передачі сигналу "Увага всім!"

4.2.7 Організація захисту співробітників і студентів ГОУ ВПО "Сибгиу"

при виникненні ЧС мирного і воєнного часу

4.3 Екологічна безпека

Висновок

Список використаних джерел

Додаток А. Календарний план робіт зі створення системи

Додаток Б. Комплектність документації на систему

Додаток В. Листинг програми-транслятора шахових партій

Додаток Г. Листинг реєстратор^-програми-реєстратора шахових партій

Додаток Д. Знімки екрана

Додаток Е. Протокол DGT

Додаток Ж. Загальна структура транслятор шахових партій

Додаток З. Загальна структура реєстратора шахових партій

Додаток И. Аналіз результатів тестових іспитів

Додаток К. Листинг модуля віщання шахових партій

Уведення

В даний час в усьому світі різко зросло число спортивних шахових змагань високого і середнього рівня. Це сприяє різкому росту суспільного інтересу до даного виду спорту і накладає вимогу широкого висвітлення подібних подій у засобах масової інформації і мережі Інтернет. Для цих цілей у даний час активно використовуються інформаційні системи, оснащені електронними шахівницями й устаткуванням для відображення інформації. Однак усі подібні системи мають ряд істотних недоліків. Усі вони випливають в основному з відсутності ринку інформаційних шахових систем. По-перше, велику складність представляє закупівля устаткування для інформаційних шахових систем, тому що його постачанням у світі займається тільки 3 організації, і великий перелік вимог, які необхідно вказати при замовленні. По-друге, отсутствует вільно розповсюджуване програмне забезпечення для подібних систем.

У даному дипломному проекті приводиться приклад створення інформаційної шахової системи і робиться спроба створення для неї програмного забезпечення.

Метою дипломного проекту в першу чергу є забезпечення всесвітньої трансляції спортивних шахових змагань із застосуванням розробленого в ході проекту закінченого програмного продукту. Надалі планується комерційне використання даної розробки.

1. Загальна частина

1.1Характеристика СП "ШК"

Структурний підрозділ "Шаховий клуб" входить до складу державної освітньої установи вищого професійного утворення "Сибірський державний індустріальний університет" (ГОУ ВПО "Сибгиу"). Приміщення шахового клуба є полігоном кафедри "Фізичного виховання, здоров'я і спорту" (Фвзис) для проведення занять по дисципліні "Шахи" для студентів, по стані здоров'я не придатних до занять фізичною культурою в основній навчальній групі. В даний час у приміщенні структурного підрозділу "Шаховий клуб" (СП "ШК") займається близько 300 студентів і співробітників університету. Зміна кількості студентів, що займаються в приміщенні СП "ШК" по дисципліні "Шахи" за останні 5 років відбиває малюнок 1.

Малюнок 1 - Зміна числа студентів, що навчаються по дисципліні "Шахи"

Таким чином, число студентів, що займаються по дисципліні "Шахи" за останні 5 років стабільно не перетерплює різких змін.

Крім цього, приміщення СП "ШК" є базою для проведення змагань по шахам різного рівня: від внутріміських до міжнародних.

Навчальний процес по дисципліні "Шахи" здійснюється відповідно до навчального плану занять кафедри Фвзис. Правила шахової гри і правила проведення шахових змагань регулюються кодексом міжнародної шахової федерації ФИДЕ.

Процес проведення змагань по шахам у приміщенні СП "ШК" здійснюється відповідно до календарного плану проведення змагань на поточний рік, а також у співробітництві з міською муніципальною установою додаткового утворення дітей "Спеціалізованою детско-юношеской спортивною школою Олімпійського резерву по шахам імені Б. А. Кустова" (МУДОД "СДЮСШОР по шахам").

Корпус СП "ШК" містить у собі наступні приміщення: основний турнірний зал, суддівська, роздягальня, викладацька, малий турнірний зал, кабінет директора, підсобне приміщення, туалетні кімнати. СП "ШК" оснащено наступним інвентарем: шахові столи - 53 штуки; комплекти шахів - 40 штук; шахових годинник - 40 штук. Обслуговуючий персонал шахового клуба: директор, провідний інженер, дві технички. Заняття в приміщенні СП "ШК" проводять 3 викладача кафедри фізичної культури, здоров'я і спорту. Під час проведення спортивних змагань у випадку недостачі інвентарю й устаткування все необхідне надається в безплатне користування на період змагань міським МУДОД "СДЮСШОР по шахам". Недостача персоналу на період спортивних змагань компенсується шляхом відрядження працівників міського МУДОД "СДЮСШОР по шахам" на обслуговування і суддівство соревновательного процесу, а також шляхом залучення розрядників-студентів-розрядників на волонтерських початках. Організаційна структура СП "ШК", що включає працівників суміжних підрозділів і установ, представлена на малюнку 2.

Малюнок 2 - Організаційна структура СП "ШК"

За останнім часом різко зросло число змагань, проведених у приміщенні СП "ШК". У співробітництві з міським МУДОД "СДЮСШОР по шахам" у приміщенні СП "ШК" тільки за 2007 рік були проведені наступні міські змагання із шахів:

- перша ліга м. Новокузнецька по шахам серед чоловіків;

- перша ліга м. Новокузнецька по шахам серед жінок;

- особисто-командний студентський чемпіонат ГОУ ВПО "Сибгиу" по шахам серед факультетів;

- особисто-командний викладацький чемпіонат ГОУ ВПО "Сибгиу" по шахам серед факультетів;

- чемпіонат м. Новокузнецька по шахам серед ветеранів;

- традиційна літня міська Спартакіада;

- турнір по швидким шахам серед студентів;

- першість міста по бліці серед студентів;

внутріміські шахові змагання, присвячені до різних свят:

- традиційний новорічний бліцтурнір;

- бліц турнір до Дня Перемоги серед студентів;

- бліц турнір до Дня Перемоги серед ветеранів;

- різдвяний шаховий турнір;

- турнір, присвячений 8 березня;

- турнір, присвячений 23 лютого;

змагання від обласного до міжнародного рівня:

- чемпіонат СФО по шахам серед хлопчиків до 8 років;

- чемпіонат СФО по шахам серед дівчинок до 8 років;

- чемпіонат СФО по шахам серед хлопчиків до 10 років;

- чемпіонат СФО серед хлопчиків до 10 років по швидким шахам;

- чемпіонат СФО по шахам серед дівчинок до 10 років;

- чемпіонат СФО серед дівчинок до 10 років по швидким шахам;

- чемпіонат СФО по шахам серед хлопчиків до 12 років;

- чемпіонат СФО серед хлопчиків до 12 років по швидким шахам;

- чемпіонат СФО по шахам серед дівчинок до 12 років;

- чемпіонат СФО серед дівчинок до 12 років по швидким шахам;

- чемпіонат СФО по шахам серед чоловіків;

- чемпіонат СФО по шахам серед жінок;

- обласна спартакіада Вузов Кузбасу (студенти);

- обласна спартакіада Вузов Кузбасу (викладачі);

- обласний командний турнір ветеранів на честь Дня Перемоги;

- традиційний міжнародний турнір пам'яті Толстогузова, чоловіка;

- традиційний міжнародний турнір пам'яті Толстогузова, жінки;

- традиційний міжнародний турнір пам'яті Толстогузова, викладачі Вузов;

- першість області по шахам серед хлопчиків до 8 років;

- першість області по шахам серед дівчинок до 8 років;

- першість області по шахам серед хлопчиків до 10 років;

- першість області серед хлопчиків до 10 років по швидким шахам;

- першість області по шахам серед дівчинок до 10 років;

- першість області серед дівчинок до 10 років по швидким шахам;

- першість області по шахам серед хлопчиків до 12 років;

- першість області серед хлопчиків до 12 років по швидким шахам;

- першість області по шахам серед дівчинок до 12 років;

- першість області серед дівчинок до 12 років по швидким шахам;

За останнім часом працівниками СП "ШК" у співробітництві з міським МУДОД "СДЮСШОР по шахам" були проведені наступні найбільші міжнародні шахові форуми:

- особисто-командний чемпіонат Росії по шахам серед студентів Вузов;

- особисто-командний чемпіонат Світу із шахів серед студентів Вузов (під час написання дипломної роботи даний шаховий форум перебував у стадії підготовки).

На чемпіонаті Росії по шахам серед студентів Вузов команді ГОУ ВПО "Сибгиу" (у складі якої був і автор даної дипломної роботи; тренер команди - майстер міжнародного класу по шахам, викладач кафедри фізичного виховання, здоров'я і спорту Зайцев В. В.) удалося стати бронзовими призерами. А, небагато забігаючи вперед, на особисто-командному чемпіонаті Світу із шахів серед студентів Вузов збірна студентська команда Росії, у складі якої виступали від ГОУ ВПО "Сибгиу" два представники, виступила дуже успішно, з великим відривом обігнавши найближчих конкурентів, збірну команду Китаю, і перемігши на цьому грандіозному спортивному змаганні.

Найближчим часом у м. Новокузнецьку планується провести ще ряд найбільших шахових змагань, от тільки трохи з них:

- чемпіонат СФО по шахам серед юніорів по класичним і швидким шахам (усі вікові категорії - до 8, до 10, до 12, до 14, до 16, до 18 років; і серед юнаків і серед дівчин. У такий спосіб - 22 турніру, включаючи турніри по швидким шахам. Причому одночасно буде проводитися спочатку 12 турнірів по класичним шахам, а потім 10 турнірів по швидким шахам);

- вища ліга чемпіонату Росії серед чоловіків і жінок (один з найсильніших шахових форумів Росії і світу, що раніш традиційно проводиться в м. Сочі).

Крім усього вищесказаного, у ході роботи структурного підрозділу "Шаховий клуб" у співробітництві з міським МУДОД "СДЮСШОР по шахам" склалася гарна традиція - відправляти як заохочення кращих студентів спортсменів на міжнародні змагання за кордон. Для реалізації даної ідеї залучаються спонсорські засоби, засоби ГОУ ВПО "Сибгиу", засобу міського МУДОД "СДЮСШОР по шахам". Географія шахових турнірів, у яких брали участь спортсмени ГОУ ВПО "Сибгиу" дійсно вражає:

- Малайзия. 2003 рік. Особисто-командний чемпіонат Світу із шахів серед студентів Вузов;

- Чехія. 2005 рік. Європейський міжнародний турнір;

- Хорватія 2006 рік. Європейський міжнародний турнір;

- Албанія 2007 рік. Європейський міжнародний турнір;

- Греція 2008 рік. Європейський міжнародний турнір (планується).

Крім цього, команда ГОУ ВПО "Сибгиу" у повному складі регулярно виїжджає на великі спортивні змагання на території Росії. От тільки деякі традиційно відвідувані командою ГОУ ВПО "Сибгиу" по шахам спортивні форуми:

- обласна спартакіада Вузов Кузбасу (проводиться поперемінно в м. Новокузнецьку й у м. Кемерово);

- чемпіонат Росії по шахам серед студентів Вузов (проводиться щораз у різних містах. Кілька останніх турнірів проводилося в: м. Новокузнецьку, м. Нижньому Тагілу, м. Уфа);

- традиційний міжнародний шаховий фестиваль "Маестро", м. Берцк;

- чемпіонат СФО по шахам серед чоловіків і жінок (проводиться щораз у різних містах. Кілька останніх турнірів проводилося в: м. Новокузнецьку, м. Ангарську, м. Улан-Уде, м. Томську).

У СП "ШК" заняття по дисципліні "Шахи" ведуться дуже кваліфікованими викладачами. Двоє викладачів мають високі міжнародні звання. Це майстер міжнародного класу по шахам Сорокіна Т. Н. і майстер міжнародного класу по шахам Зайцев В. В. Викладачі СП "ШК" активно беруть участь у спортивному житті міста, області, країни і світу, показуючи наочний приклад студентам Вуза. Географія змагань, у яких брали участь і беруть участь викладачі ГОУ ВПО "Сибгиу" досить широкий і нараховує більш десятка країн.

На підставі аналізу підсумків роботи СП "ШК" ГОУ ВПО "Сибгиу" був зроблений висновок про необхідність створення спеціалізованої інформаційної шахової системи, що забезпечує нормальний процес проведення спортивних змагань, висвітлення їх для широкого кола спостерігачів, підготовки студентів-спортсменів до вищих спортивних досягнень.

1.2 Огляд шахових систем прототипів

В даний час ринок шахових інформаційних систем практично отсутствует. Тому отсутствует і масове серійне виробництво подібних систем. Електронне шахове устаткування в усьому світі можна придбати тільки в 3 організацій:

- Фірма "Шахком", генеральний директор Борис Ешан, Санкт-Петербург.

- Інформаційний шаховий центр російської шахової федерації, Москва.

- Міжнародна шахова федерація ФИДЕ.

Електронне шахове устаткування у вільному продажі практично отсутствует. Його необхідно замовляти індивідуально, указуючи необхідну комплектацію і свої побажання. Терміни постачання устаткування можуть варіюватися від декількох днів до декількох місяців, у залежності від дальності постачання. Безкоштовне сервісне обслуговування для цього устаткування не передбачено. Усі ці обставини сильно ускладнюють створення подібних систем у географічно вилучених від центральної частини Росії регіонах.

Дотепер переважна більшість створюваних інформаційних шахових систем являло собою мініатюрний варіант, що складається з невеликого числа електронних шахівниць (ЕШД), від 2 до 10 штук, з'єднаних чи несполучених між собою і підключаються до комп'ютера через стандартний сома-порт; одного чи двох проекторів, за допомогою яких власне відображалися шахові партії. Якщо це найбільші міжнародні шахові форуми, що обслуговуються міжнародною шаховою федерацією ФИДЕ чи інформаційним шаховим центром Росії, то подібні змагання висвітлюються і транслюються в мережі Інтернет на таких шахових сайтах, як:

- www.chesspro.ru;

- www.fide.com;

- www.russiachess.org;

- www.chesscenter.com;

- www.64.ru;

- www.russiachess.org.

Однак не в інтересах фахівців міжнародної шахової федерації ФИДЕ й інформаційного шахового центра Росії надавати в чи користування продавати спеціалізоване програмне забезпечення (СПО) для трансляції змагань у мережі Інтернет, тому що подібне СПО є об'єктом їхньої інтелектуальної власності і використовується ними для обслуговування турнірів у випадку запрошення співробітників цієї організації.

Як системи прототипів інформаційної системи "Шаховий клуб" (ИС "ШК") приведемо двох систем.

а) Програмно-технічний комплекс, що забезпечує трансляцію шахових змагань для присутньої аудиторії, Нижній Тагіл, 2005 рік, чемпіонат Росії по шахам серед студентів

Даний програмно-технічний комплекс (ПТК) являє собою набір з наступних технічних і програмних засобів:

- 4 ЕШД DGT;

- 4 комплекти фігур для ЕШД;

- 4 одиниці електронних шахових годин;

- персональний комп'ютер (ПК);

- 1 проектор;

- сполучні проводи і переходники;

- програмний пакет ChessAssistant9.1;

- драйвер для електронної шахівниці dgtnix.

Електронні шахівниці й електронному шаховому годинник за допомогою поставляються в комплекті з ними переходников з com інтерфейсу на стандартний мережний кабель, підключаються до магістрального проводу, що за допомогою поставляється також у комплекті переходника підключається до комп'ютера через стандартний com-порт. Як магістральний провід використовується кабель RJ45. Інформація пакетами, що надходить з електронних шахових дощок, надходить на комп'ютер у програмний продукт ChessAssistant9.1, причому процес опитування стандартного com-порту ініціюється драйвером dgtnix для електронних шахівниць, а передача даних здійснюється з використанням протоколу DGT. Інформація, що надходить, зберігається в окремій базі даних програмного продукту ChessAssistant9.1. Вона містить у собі такі дані про шахову партію, як:

- прізвище, ім'я, по батькові гравців;

- результат партії;

- класифікація дебюту шахової партії;

- дата шахової партії;

- місто, країна де гралося шахова партія;

- номер туру;

- назва, ранг, статус змагань;

- коментарі;

- міжнародні звання і рейтинги гравців;

- безпосередньо сам текст шахової партії і т.д.

Далі інформація, що надійшла в базу даних програмного продукту ChessAssistant9.1, виводиться на проектор і відображається в глядачевий залі для присутньої аудиторії.

б) Програмно-технічний комплекс, що забезпечує трансляцію шахових змагань для присутньої аудиторії й у мережі Інтернет, Москва, 2007 рік, міжнародний шаховий турнір "Аерофлот-опен 2007"

Даний ПТК створювався й обслуговувався фахівцями інформаційного шахового центра російської шахової федерації. Тому повна інформація про даний ПТК отсутствует. Як програмне забезпечення для даної системи використовувалося СПО, що є об'єктом інтелектуальної власності.

Даний ПТК являє собою набір з наступних технічних і програмних засобів:

- 16 ЕШД DGT;

- 16 комплектів фігур для ЕШД;

- 16 одиниць електронних шахових годин;

- 2 ноутбука;

- 2 проектори;

- сполучні проводи і переходники;

- СПО, що забезпечує трансляцію змагань для присутньої аудиторії й у мережі Інтернет;

- драйвер для електронної шахівниці dgtnix.

Даний ПТК відрізняється від попереднього бό льшим кількістю комплектів ЕШД і одиниць устаткування, а також можливістю трансляції спортивних змагань у мережі Інтернет.

У представленій системі використовується 2 магістральні проводи, до кожного з який підключається по 8 ЕШД. Магістральні проводи, у якості яких також використовуються кабелі RJ45, підключаються до 2 ноутбукам, що має вихід у мережу Інтернет. Трансляція в мережі інтернет здійснюється з використанням СПО, що є об'єктом інтелектуальної власності. Весь процес змагань також транслюється для присутньої аудиторії з використанням 2 проекторів. Схема підключення ЕШД подібна вже розглянутій схемі підключення, технологія передачі даних аналогічна.

У загальному виді робота розглянутого ПТК представлена на малюнку 4.

Малюнок 4 - Ілюстрація роботи ПТК, що забезпечує трансляцію змагань для присутньої аудиторії й у мережі інтернет

1.3 Аналіз достоїнств і недоліків

Розглянуті шахові системи прототипи володіють поруч достоїнств і недоліків. Деякі з них властиві тільки цьому класу систем, а деякі характерні для будь-яких подібних систем.

Достоїнствами подібних систем є:

- шахові ИС сприяють підвищенню інтересу громадськості до даного інтелектуального виду спорту, залученню молоді до спортивного життя країни і світу;

- шахові ИС сприяють залученню спонсорських засобів, що робить подібні системи економічно привабливими;

- ИС подібного класу сприяють залученню великого числа людей для участі у великих спортивних змаганнях, що є великим плюсом для економіки міста і регіону, у якому проводяться подібні форуми;

- подібні ИС сприяють підвищенню загальної культури проведення спортивних змагань, ергономіки і суддівської діяльності;

- інформаційні шахові системи (ИШС) здатні організовувати моментальний перенос партій, що граються, в електронну форму і здійснювати транслювання спортивних змагань у режимі он-лайн (on-line) по усьому світі через мережу Інтернет;

- ИШС є незамінним помічником у випадку виникнення спірних ситуацій і конфліктів, тому що позиції партій, що граються, зберігаються навіть у випадку повного порушення розміщення фігур на шахівниці;

- ИШС дозволяють перебороти обмеженість вмещаемости приміщення, у якому проводяться спортивні змагання;

- дані ИС дозволяють видавати докладні звіти про підсумки спортивних змагань практично наступного дня після закінчення турніру;

- подібні системи роблять процес, що відбувається на шахівниці, гранично зрозумілим навіть для людей, не знайомих добре з принципами гри; це досягається підключенням аналізованих ігрових і програмних модулів, що коментують, що передбачено можливостями подібних систем.

До недоліків розглянутих шахових систем прототипів, а також більшості подібних систем, відносяться:

- складність створення подібних систем, обумовлена наступними факторами:

o відсутність устаткування для подібних систем у вільному продажі;

o великий перелік вимог, які необхідно вказати при замовленні необхідного устаткування;

o складності по доставці устаткування в регіони, вилучені від центральної частини країни;

o відсутність безкоштовного сервісного обслуговування;

o складність заміни бракованого устаткування унаслідок великої далекості фірми виробника і фірми постачальника;

- дуже обмежене число експлуатованих ЕШД, що робить використання подібних систем узконаправленним на трансляцію тільки декількох перших партій змагання; подібна обставина унеможливлює проведення повномасштабних трансльованих змагань і утрудняє створення всіляких друкованих звітів про підсумки турнірів;

- тому що ринок подібних систем є монополізованим, то фірми монополісти самі установлюють вартість ліцензії на використання устаткування;

- отсутствует у вільному продажі СПО для подібних систем, тому приходиться сподіватися на працездатність СПО, що поставляється в комплекті з ЕШД.

1.4 Технічне завдання на створення ИС "ШК"

1.4.1 Загальні зведення

а) Найменування системи - інформаційна система "Шаховий клуб" ГОУ ВПО "Сибірський державний індустріальний університет".

б) Розроблювач:

Студент

Група АИС-03, ГОУ ВПО "Сибгиу"

Ширяев А. С.

Адреса: 654041, м. Новокузнецьк, вул. Ціолковського 32-22,

Телефон: (8-3843) 71-27-63

E-mail: jamert3@yandex.ru

Замовники:

ГОУ ВПО "Сибірський державний індустріальний університет"

МУДОД "СДЮСШОР по шахам ім. Б. А. Кустова"

Адреси замовників:

м. Новокузнецьк, вул. Кірова 42,

м. Новокузнецьк, вул. Орджонікідзе 23.

Телефони замовників: (8-3843) 46-33-35, (8-3843) 45-36-98.

в) Система створюється в зв'язку з необхідністю оснащення СП ГОУ ВПО "Сибгиу" устаткуванням для проведення навчального процесу і процесу проведення змагань.

г) Планові терміни початку робіт зі створення системи: 01.08.07.

Планові терміни закінчення робіт зі створення системи: 13.03.08.

д) Результати робіт зі створення системи представлені в додатку 1.

1.4.2 Призначення і мети створення системи

1.4.2.1 Призначення системи

ИС "ШК" призначена для виконання функцій, що забезпечують більш ефективне проведення навчального процесу, а також змагань, у приміщенні СП "ШК" ГОУ ВПО "Сибгиу", а саме:

- трансляція шахових партій у режимі реального часу для присутньої аудиторії й у мережі Інтернет;

- зниження трудозатрат на висвітлення турнірів у засобах масової інформації;

- надання вичерпної інформації з кожного учасника змагань по першому запиті;

- організація моментального переносу запису шахових партій в електронну форму;

- відображення шахових партій, турнірного положення, різного роду статистичної інформації на спеціалізованих екранах і електронних стендах для широкої аудиторії;

- збереження даних про кожного учасника змагань, турнірної й іншої інформації;

- оперативна обробка всієї інформації, що надходить, і видача всіх необхідних для змагань даних;

- організація видачі в оперативному режимі інформації зі спірних питань, що виникають у ході ігрового процесу;

- організація комп'ютеризованого процесу навчання грі в шахи.

1.4.2.2 Мети створення системи

Ціль складається з наступних складових:

- інформатизація процесу шахової гри;

- автоматизація:

- процесу зборки,

- відображення,

- збереження,

- обробки спеціалізованої шахової інформації;

- полегшення роботи суддівської колегії в процесі змагань;

- автоматизація процесу навчання.

1.4.3 Характеристика об'єкта інформатизації

Об'єктом інформатизації є процес шахової гри. Правила шахової гри і правила проведення шахових змагань регулюються кодексом міжнародної шахової федерації ФИДЕ.

Об'єктом інформатизації також є навчальний процес на кафедрі Фкзис ГОУ ВПО "Сибгиу" по дисципліні "Шахи". Даний навчальний процес здійснюється відповідно до навчального плану занять.

Процес проведення змагань по шахам здійснюється відповідно до календарного плану проведення змагань на поточний рік.

Навчальний процес по дисципліні "Шахи" проводиться в приміщенні СП "ШК" ГОУ ВПО "Сибгиу". Приміщення СП "ШК" ГОУ ВПО "Сибгиу" містить у собі наступні приміщення: турнірний зал, суддівський кабінет, роздягальня, приміщення для інвентарю, кімната аналізу, кабінет директора. Шаховий клуб ГОУ ВПО "Сибгиу" оснащений наступним інвентарем: шахові столи - 53 штук; комплекти шахів - 40 штук; шахових годинник - 40 штук.

1.4.4 Вимоги до системи

1.4.4.1 Вимоги до системи в цілому

а) Вимоги до структури і функціонування системи

ИС "ШК" представлена п'ятьма підсистемами:

- інтегруюча підсистема;

- підсистема збору інформації;

- підсистема обробки і збереження інформації;

- підсистема відображення інформації;

- навчальна підсистема.

Інтегруюча підсистема в загальному виді являє собою мережну структуру, що охоплює всі інші підсистеми. Тому вона є найбільш важливої з всіх інших підсистем. Конфігурація устаткування підсистеми наступна:

- 1 сервер для збереження інформації й обробки запитів;

- сполучні проводи;

- 1 комутатор D-Link DGS-1008D;

- 6 робочих комп'ютерів для роботи з інформацією, що надходить на сервер в оперативному режимі,

- периферійні пристрої:

- багатофункціональний пристрій,

- мікрофон,

- веб-камера й ін.

Підсистема збору інформації в загальному виді являє собою всі пристрої, на які надходить первинна і вторинна інформація. Ця підсистема містить у собі наступні частини:

- ЕШД у кількості 30 штук,

- інтернет і локальнаю мережа ГОУ ВПО "Сибгиу",

- фотоапаратура та інше устаткування.

ЕШД являють собою комплекти шахових фігур з дошками і шахових годинник, з'єднані за допомогою сполучних проводів і переходников з комп'ютером. Передача даних, що надходять із шахівниць, здійснюється за допомогою протоколу DGT. Процес, що відбувається під час гри за шахівницею, цілком переноситься в електронну форму за допомогою СПО. Кількість що підключаються ЕШД визначається потребами соревновательного процесу, але загальне їхнє число 30 штук. Інтернет і локальна мережа ГОУ ВПО "Сибгиу" - необхідні джерела інформації. Звідси буде надходити інформації всілякого роду: відкликання, коментарі, пропозиції, аматорська фото і відео.

Підсистема обробки і збереження інформації містить у собі:

- обробку і збереження шахової інформації;

- обробку і збереження іншої інформації.

Підсистема обробки і збереження шахової інформації являє собою набір СПО для проведення турнірів, збереження і классифицирования шахової інформації, СПО для обслуговування електронних дощок. У якості СПО для проведення турнірів використовується набір з наступних програмних продуктів:

- суддівська програма SwissMaster 5.5 у кількості 2 ліцензійних версій;

- багатофункціональний пакет ChessAssistant9.1 у кількості 6 ліцензійних версій

- багатофункціональний пакет ChessBase9 у кількості 3 ліцензійних версій.

Для обслуговування ЕШД використовується програмне забезпечення, що поставляється з ними в комплекті.

Підсистема обробки і збереження іншої інформації являє собою пакет стандартних програм для роботи з графікою.

Підсистема відображення інформації містить у собі:

- трансляцію змагань у мережі Інтернет;

- трансляцію змагань для присутньої аудиторії.

Тому що використовується СПО для ЕШД, що поставляється з ними в комплекті, то не виникає необхідності в додатковому СПО для трансляції змагань у мережі Інтернет з тієї причини, що зазначене СПО вже містить усі для цього необхідне.

Як технічні засоби, що забезпечують трансляцію змагань для присутньої аудиторії, використовується існуюче устаткування, а саме - плазменние монітори, установлені по університеті, електронні стенди і проектори: 1 електронний стенд і проектор у турнірному залі і 1 електронний стенд і проектор на території ГОУ ВПО "Сибгиу".

Підсистема відображення інформації, крім виконання своєї головної функції - трансляції змагань для присутньої аудиторії й у мережі Інтернет - може бути використана в рекламних цілях.

Навчальна підсистема являє собою набір програмних засобів для навчання шаховій грі, тренування, гри в шахи через мережу Інтернет і по локальній мережі ГОУ ВПО "Сибгиу". Як програмне забезпечення використовується:

- програмний пакет ChessAssistant9.1 ( щомається в наявності);

- програмний пакет ChessBase9 ( щомається в наявності);

- навчальна програма Studies2.0 (6 ліцензійних версій);

- навчальна програма "Шахові комбінації" (6 ліцензійних версій);

- навчальна програма "Шахова Стратегія" (6 ліцензійних версій);

- навчальна програма "Шахова школа" (6 ліцензійних версій);

- програма для гри в шахи по мережі Інтернет "ChessPlanet".

Більш наочно загальна структура ИС "ШК" представлена в графічній частині дипломного проекту, на листі 3.

Структура ИС "Шаховий клуб" може бути доповнена новими підсистемами, модулями й устаткуванням, якщо на то виникне необхідність. Чисельність одиниць техніки і програмне забезпечення може мінятися в залежності від обсягів фінансування.

б) Вимоги до чисельності і кваліфікації персоналу системи і режиму його роботи

До експлуатації допускається персонал, що вивчив інструкцію з експлуатації.

Кваліфікація персоналу повинна забезпечувати ефективне функціонування системи у всіх заданих режимах. Чисельність персоналу повинна бути достатньої для забезпечення виконання усіх функцій системи.

Персонал повинний бути підготовлений до виконання своїх обов'язків відповідно до інструкцій організаційного забезпечення.

Кожне обличчя, що входить до складу персоналу, повинне вміти застосовувати відповідні інформаційні моделі і працювати з використовуваними їм технічними засобами і документацією, що визначає порядок його діяльності.

в) Показники призначення

Час реалізації системи на ініціативи користувача по запитах на видачу інформації, введення інформації, відновлення не повинне перевищувати 3 секунд.

Час запізнювання системи при перекладі шахової партії в електронну форму і відображенні її для широкого кола спостерігачів у процесі змагань не повинне перевищувати 0,5 секунд, якщо заздалегідь не передбачена регламентована затримка.

Структура комплексу технічних засобів, функціональні можливості і програмне забезпечення повинні бути реалізовані з урахуванням можливості подальшого розвитку.

г) Вимоги до надійності

Технічні засоби системи повинні працювати в умовах реального часу в процесі проведення змагань у плині усього робочого дня з періодичним технічним обслуговуванням.

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

Середній час відновлення функцій системи в процесі проведення змагань не повинне перевищувати 10 хвилин.

Середній час відновлення функцій системи в ході навчального процесу не повинне перевищувати 1 доби.

Час наробітку на відмовлення технічних і програмних засобів не повинне перевищувати 5 років.

Вимоги по надійності функціонування повинні уточнюватися на наступних етапах проектування.

д) Вимоги безпеки

Вимоги по безпеці при монтажі, налагодженні й експлуатації устаткування повинні відповідати наступним документам:

- ДСТ 12.1.004-85 "ССБТ. Пожежна безпека. Загальні правила".

- Санпин 2.2.2.542-96 "Гігієнічні вимоги до відеодисплейних терміналів обчислювальних машин".

- Норми освітленості повинні бути забезпечені відповідно до Снип 11-4-79.

е) Вимоги до ергономіки і технічної естетики

Розміщення технічних засобів, а також форми представлення оперативної інформації повинні відповідати Дст 22.269-76.

Загальні ергономические вимоги до мікроклімату робочих приміщень персоналу повинні відповідати Дст 12.1.005-76.

Устаткування системи повинне бути скомпоноване з технічних засобів, що випускаються серійно.

Спосіб і форма представлення інформації оперативному персоналу повинна відповідати вимогам ергономіки ДСТ 22.269-76.

ж) Вимоги по експлуатації, технічному обслуговуванню, ремонту і збереженню

При розробці ИС "ШК" необхідно передбачити проведення технічного обслуговування використовуваного устаткування на місці його експлуатації. Технічне обслуговування проводиться з метою попередження відмовлень у роботі системи.

Періодичність проведення технічного обслуговування залежить від виду і призначення пристроїв і установлюється відповідно до технічного опису й інструкції з експлуатації для кожного елемента. Для швидкої заміни пристроїв, що вийшли з ладу, і блоків необхідно передбачити запасні блоки, резервні канали даних.

з) Вимоги по схоронності інформації при аваріях

Для забезпечення схоронності інформації при різких змінах і зникненнях напруги в живильній мережі, відмовленнях сервера, влученнях у систему вірусу, відмовленнях комп'ютерів і інших технічних засобів необхідно передбачити:

- автоматичне архивирование;

- використання засобів захисту інформації;

- аналіз відмовлень і відновлення даних.

и) Вимоги до захисту від впливу зовнішніх впливів

Захист технічних засобів ИС "ШК" від впливу зовнішніх електричних і магнітних полів, а також перешкод по ланцюгах харчування повинна бути достатньої для надійного функціонування системи. У ИС "ШК" повинна бути передбачена антивірусний захист і захист від несанкціонованого доступу, достатня для надійного, безперебійного функціонування системи.

к) Вимоги до патентної чистоти

Розроблювальна система не призначена для експорту, тому перевірка використовуваних технічних рішень на патентну чистоту не потрібно.

1.4.4.2 Вимоги до функцій системи

ИС "ШК" відповідно до ДСТ 24.104-85 повинна виконувати:

- збір, обробку й аналіз інформації (сигналів, повідомлень, документів і т.п.) про стан об'єкта керування;

- вироблення керуючих впливів (програм, планів і т.п.);

- передачу керуючих впливів на виконання і їхній контроль;

- реалізацію і контроль виконання керуючих впливів;

- обмін інформацією (документами, повідомленнями і т.п.) із взаємозалежними автоматизованими системами.

Склад автоматизованих функцій і функцій по представленню інформації ИС "ШК" повинний забезпечувати можливість керування відповідним об'єктом і представленням інформації.

Склад автоматизованих функцій, функцій по представленню інформації ИС "ШК" і ступінь інформативності відображуваних даних повинні бути економічно і соціально обґрунтовані з урахуванням необхідності звільнення персоналу від виконання повторюваних дій і створення умов для використання його творчих здібностей у процесі роботи.

1.4.4.3 Вимоги до видів забезпечення

а) Вимоги до інформаційного забезпечення

Інформаційне забезпечення ИС "ШК" повинне бути достатнім для виконання всіх автоматизованих і інформативних функцій даної системи.

Інформаційне забезпечення ИС "ШК" повинне бути сумісне з інформаційним забезпеченням систем, взаємодіючих з нею, по змісту, системі кодування, методам адресування, форматам даних і формі представлення інформації, одержуваної і видаваної ИС "ШК".

б) Вимоги до програмного забезпечення

Програмне забезпечення ИС "ШК" повинне бути достатнім для виконання усіх функцій цієї системи, реалізованих із застосуванням засобів обчислювальної техніки, а також мати засобу організації всіх необхідних процесів обробки і представлення даних, що дозволяють вчасно виконувати всі автоматизовані й інформативні функції у всіх регламентованих режимах функціонування ИС "ШК".

в) Вимоги до технічного забезпечення

Комплекс технічних засобів ИС "ШК" повинний бути достатнім для виконання всіх автоматизованих функцій і функцій по представленню інформації.

У комплексі технічних засобів ИС "ШК" повинні використовуватися технічні засоби серійного виробництва. При необхідності допускається застосування технічних засобів одиничного виробництва.

Технічні засоби ИС "ШК" повинні бути розміщені з дотриманням вимог, що містяться в технічної, у тому числі експлуатаційної, документації на них, і так, щоб було зручно використовувати їх при функціонуванні ИС "ШК" і виконувати технічне обслуговування.

Технічні засоби ИС "ШК", використовувані при її взаємодії з іншими системами, повинні бути сумісні по інтерфейсах з відповідними технічними засобами цих систем і використовуваних систем зв'язку.

У ИС "ШК" повинні бути використані технічні засоби з терміном служби не менш п'яти років.

У ИС "ШК" повинні бути використані засоби обчислювальної техніки, що задовольняють загальним технічним вимогам за Дст 22552-84.

г) Вимоги до лінгвістичного забезпечення

Лінгвістичне забезпечення системи повинне бути достатнім для спілкування різних категорій користувачів у зручній для них формі з засобами ИС "ШК" і для здійснення процедур перетворення і машинного представлення оброблюваної інформації.

У лінгвістичному забезпеченні ИС повинні бути:

- передбачені мовні засоби для опису будь-якої використовуваної інформації;

- уніфіковані використовувані мовні засоби;

- стандартизовані описи однотипних елементів інформації і записи синтаксичних конструкцій;

- забезпечені зручність, однозначність і стійкість спілкування користувачів із засобами автоматизації і представлення інформації;

- передбачені засоби виправлення помилок, що виникають при спілкуванні користувачів з технічними засобами ИС.

Лінгвістичне забезпечення ИС "ШК" повинне бути відбите в документації організаційного забезпечення системи у виді правил спілкування користувачів з технічними засобами ИС "ШК" у всіх режимах функціонування системи.

д) Вимоги до організаційного забезпечення

Організаційне забезпечення ИС "ШК" повинне бути достатнім для ефективного виконання персоналом покладених на нього обов'язків при здійсненні автоматизованих і зв'язаних з ними неавтоматизованих функцій системи, а також функцій по представленню інформації.

Організаційна структура ИС "ШК" повинна дозволяти виконувати усі функції з урахуванням їх розподілу по рівнях керування.

Інструкції організаційного забезпечення ИС "ШК" повинні визначати дії, необхідні для виконання кожної автоматизованої чи функції функції по представленню інформації, у всіх режимах функціонування ИС "ШК", з урахуванням заданих вимог по безпомилковості і швидкодії реалізації персоналом своїх функціональних обов'язків, а також містити конкретні вказівки про дії у випадку виникнення аварійних чи ситуацій порушення нормальних умов функціонування ИС "ШК".

1.4.5 Склад і зміст робіт зі створення системи

Склад і зміст робіт зі створення системи представлені в додатку 1.

1.4.6 Порядок контролю і приймання системи

1.4.6.1 Попередні іспити системи

Попередні іспити системи проводять для визначення її працездатності і рішення питання про можливість приймання ИС "ШК" у досвідчену експлуатацію.

Попередні іспити системи організує замовник і проводить розроблювач і замовник спільно. Зміст програми іспитів повинний відповідати Дст 24.208-80.

У "Протоколі іспитів", складеному за результатами попередніх іспитів системи, приводять висновок про можливість приймання системи в досвідчену експлуатацію, а також перелік необхідних доробок.

1.4.6.2 Досвідчена експлуатація

Результати приймання ИС "ШК" у досвідчену експлуатацію оформляють "Актом приймання в досвідчену експлуатацію", складеним на підставі "Протоколу іспитів" комісією, що проводила попередні іспити системи.

Тривалість досвідченої експлуатації системи визначають по термінах, необхідним для перевірки правильності функціонування системи при виконанні кожної автоматизованої функції, функції по представленню інформації і готовності персоналу до участі у виконанні всіх автоматизованих функцій і функцій по представленню інформації ИС "ШК".

Під час досвідченої експлуатації системи ведеться робочий журнал, у який заносяться зведення: про тривалість функціонування системи, про результати спостереження за правильністю функціонування системи, про відмовлення, збої, аварійних ситуаціях, проведених коректуваннях технічної документації.

За результатами досвідченої експлуатації системи складають акт про завершення робіт з перевірки системи в режимі досвідченої експлуатації.

1.4.6.3 Приймальні іспити системи

Приймальні іспити системи проводять для визначення її відповідності технічному завданню, вимогам стандарту і визначення можливості введення ИС "ШК" у дію.

Приймальної комісії замовник і розроблювач пред'являють наступну документацію:

- технічне завдання на систему;

- проект програми приймальних іспитів;

- протокол попередніх іспитів;

- акт приймання системи в досвідчену експлуатацію;

- робочі журнали досвідченої експлуатації системи;

- акт про завершення робіт з перевірки системи в режимі досвідченої експлуатації;

- технічна документація на систему.

За результатами приймальних іспитів приймальна комісія складає протокол іспитів і акт про введення системи в дію.

1.4.7 Вимоги до складу і змісту робіт з підготовки об'єкта інформатизації до введення системи в дію

Одночасно з розробкою системи повинне бути забезпечене проведення наступних заходів:

- визначити конкретних облич, відповідальних від СП "ШК" ГОУ ВПО "Сибгиу" за підготовку системи до експлуатації;

- позначити місця установки технічних засобів і забезпечити їхня схоронність;

- організувати підготовку персоналу для роботи із системою.

1.4.8 Вимоги до документування

Експлуатаційна документація на розроблювальну систему повинна бути достатньої для введення комплексу в дію ефективної роботи при його експлуатації.

Документація повинна містити зведення, необхідні для швидкого і якісного освоєння і правильної експлуатації засобів автоматизації і представлення інформації системи, містити вказівки по діях персоналу в аварійних чи ситуаціях при порушеннях нормальних умов функціонування комплексу, не містити зведень, що допускають неоднозначне тлумачення.

Комплект документації по системі приведений у додатку 2.

1.4.9 Висновок

У ході розробки ИС "ШК" було встановлено, що в комплекті з ЕШД було поставлено непрацездатне програмне забезпечення. Але тому що необхідно було в терміновому порядку закінчити роботи зі створення системи, а на з'ясування причин і додаткове постачання пішов б значний час унаслідок того, що устаткування поставлявся з Нідерландів, було прийняте рішення в терміновому порядку запросити фахівців з інформаційного шахового центра російської шахової федерації, що володіють власним програмним забезпеченням для ЕШД, на час проведення змагань, що спричинило за собою великі витрати.

Після розробки ИС "ШК", її приймання і проведення досвідченої експлуатації керівництвом ГОУ ВПО "Сибгиу" у тісному співробітництві з адміністрацією м. Новокузнецька й адміністрацією Кемеровської області було прийняте рішення перенести ИС "ШК" у приміщення культурного центра "Західносибірського металургійного комбінату" ("ЗСМК") на час проведення Всесвітньої шахової універсіади, що проходила в м. Новокузнецьку з 3 березня по 11 березня 2008 року. Перенесення ИС "ШК" у приміщення культурного центра "ЗСМК" не склало великих труднощів, тому що всі блоки системи легко отсоединяеми і транспортируеми.

Унаслідок тієї обставини, що працездатне програмне забезпечення для ЕШД так і не було поставлено, а фахівці з інформаційного шахового центра відмовилися від комерційного продажу СПО, що є їхньою інтелектуальною власністю, було прийняте рішення про самостійну розробку подібного СПО. Даний напрямок є пріоритетним для написання дипломної роботи студентом Ширяев А. С.

2. Спеціальна частина

2.1 Вибір основних методологій розробки програмного забезпечення

Проект - це унікальний процес, у ході виконання якого одержують унікальний продукт. Таким чином, для розробки продукту в проекті, швидше за все, повинний застосовуватися унікальний процес. Замість створення кожного проекту "з нуля", керівник проекту може скористатися узагальненої, перевіреної на практиці методикою, адаптувавши її для конкретного проекту. Як правило, завжди є можливість вибору серед декількох "початкових" життєвих циклів.

Вибір і адаптація життєвого циклу розробки проекту впливає на методики розробки продукту, навички менеджменту проектів і навички менеджменту персоналу. Що стосується методів розробки продукту, керівник проекту повинний, насамперед, мати представлення про стандарти процесу, вміти оцінити їхню застосовність стосовно даного проекту, оцінити альтернативні процеси і при необхідності адаптувати процес життєвого циклу до поточного потребам. На вибір методів і інструментальних засобів також може впливати вибір життєвого циклу.

Модель життєвого циклу розробки програмного забезпечення (ПО) є єдиним видом процесу, у якому представлений порядок його здійснення. Модель життєвого циклу розробки ПО (SoftwareLifeCycleModel, SLCM) схематично пояснює, яким образом будуть виконуватися дії по розробці програмного продукту, за допомогою опису "послідовності" цих дій. Така послідовність може чи бути не бути лінійної, оскільки фази можуть випливати друг за другом, чи повторюватися відбуватися одночасно. На малюнку 5 представлена проста узагальнена схема процесу.

Життєвий цикл

Процес

Малюнок 5 - Узагальнена схема процесу

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

Життєвий цикл - це свого роду "карта-путівник" для всіх учасників проекту, що допомагає їм зрозуміти, чи не виходять вони за визначені для них границі. Для керування програмним проектом виникає необхідність у деякому роді карти для планування дій і хронологий їхнього виконання.

У стандарт були включені описи причин, що пояснюють необхідність виконання стандартизованого процесу. Цей стандарт допомагає досягти наступних цілей.

- Поліпшення і забезпечення якості:

- за допомогою стандартизованої процедури можна щонайкраще гарантувати завершенность результатів, які необхідно надати;

- визначення проміжних результатів забезпечує можливість прискорити виконання оцінних процедур;

- контекст однорідних продуктів полегшує їхнє сприйняття, а також роботу з процедурами оцінки.

- Можливість перевірки витрат на виконання повного життєвого циклу:

- спрощує процес створення стандартів розробки для визначеного проекту і його оцінка;

- стандартизовані процедури підвищують ступінь "прозорості" операцій по визначенню витрат і дозволяють більш ефективно розпізнавати можливі ризики, зв'язані з витратами;

- однакові стандарти зменшують ризик виникнення розбіжностей між клієнтом і розроблювачем, а також між головним розроблювачем і субпідрядником;

- у випадку застосування стандартизованої процедури стають "прозорими" універсальні підходи до методів рішення, а отже, їхній можна використовувати повторно;

- небажаний хід процесу розробки, можливо, виявити на ранній стадії;

- зменшуються витрати на підготовку персоналу.

- Поліпшується обмін інформацією між різними сторонами, що беруть участь у процесі розробки; відбувається зниження залежності клієнта від підрядчика:

- використання визначених термінів зменшує розбіжності, що виникають між усіма задіяними в проекті сторонами;

- користувач, покупець і розроблювач одержують підтримку при формулюванні своїх вимог, а також при описі своїх чи ролей отриманих результатів;

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

"Каркасом" процесу розробки ПО служить модель зрілості функціональних можливостей (CapabilityMaturityModel, CMM). Вона заснована на практичних діях, відображає кращі результати і визначає потреби індивідів, що працюють над удосконаленням процесу розробки ПО і виконуючих оцінний аналіз цього процесу. Модель СММ являє собою схему, по якій етапи розробки відповідають п'ятьом рівням розвитку функціональних можливостей, на основі яких здійснюється безупинне удосконалення процесу розробки.

Вихідний. Процес розробки ПО можна охарактеризувати як спеціальний, підібраний для визначеного випадку процес, а іноді і як хаотичний. Визначити можна лише невелика кількість процесів, і успіх залежить від прикладених зусиль і рішучих дій, що починаються.

Повторюваний. Основні процеси керування проектом створюються для того, щоб відслідковувати витрати, графік роботи і функціональні можливості. Тут дотримується необхідний порядок виконання процесу, призначений для повторення досягнень, отриманих раніше при виконанні подібних проектів.

Визначений. В усіх проектах використовується випробувана, адаптована версія стандартного процесу розробки ПО даній організації.

Керований. Збираються детальні показники процесу розробки ПО і якісні характеристики продукту. Керування процесом розробки програмних продуктів здійснюється на кількісному рівні.

Рівень оптимізації. Безупинне удосконалення процесу розробки досягається за допомогою кількісного зворотного зв'язку, що досягається при здійсненні самого процесу, а також на базі новаторських ідей і технологій.

Визначення процесу містить у собі розробку і супровід стандартного процесу розробки визначеної організації, а також стосовні до нього коштовні властивості процесу, такі як описові характеристики життєвих циклів розробки ПО, що керують принципи адаптації процесу і його критерії.

Ціль визначення організаційної структури процесу полягає в розробці і супроводі стандартного процесу розробки ПО для даної організації.

Дії, що формулюють процес побудови організаційної структури, включають документування і супровід описових характеристик життєвих циклів розробки ПО, що схвалені для використання в проектах. Керівні принципи і критерії адаптації описують вибір і адаптацію життєвого циклу розробки ПО і характеристик даного проекту.

Найбільш відомими і широко використовуваними життєвими циклами розробки ПО можна назвати наступні: каскадна модель і екстремальна модель. Є і ряд інших методологій, але в ході реалізації даного дипломного проекту вони не досліджувалися. Розглянемо зазначені моделі докладніше.

2.1.1 Каскадна методологія

Класична каскадна модель, незважаючи на отриману останнім часом негативну оцінку, справно служила фахівцям з програмному інжинірингу багато років. Розуміння її сильних сторін і недоліків поліпшує оцінний аналіз інших, найчастіше більш ефективних моделей життєвого циклу, заснованих на даній моделі.

В перші роки практики програмування спочатку записувався програмний код, а потім відбувалося його налагодження. Загальноприйнятим вважалося правило починати роботу не з розробки плану, а з загального ознайомлення з продуктом. Без зайвих формальностей можна було спроектувати, закодувати, налагодити і протестувати ПО ще до того, як воно буде готово до випуску. Це нагадувало процес, зображений на малюнку 6.

Малюнок 6 - Модель процесу "робити, поки, не буде зроблене"

У структурі такого процесу є трохи "неправильностей" (чи недоліків). По-перше, оскільки споконвічно не існувало офіційного чи проекту аналізу, неможливо було довідатися про момент завершення процесу. Також був відсутній спосіб визначення відповідності вимогам щодо досягнення якості.

У 1970 році каскадна модель була уперше визначена як альтернативний варіант методу розробки ПО за принципом кодування-усунення помилок, що був широко розповсюджений у той час. Це була перша модель, що формалізувала структуру етапів розробки ПО, додаючи особливе значення вихідним вимогам і проектуванню, а також створенню документації на ранніх етапах процесу розробки.

Початковий етап виконання каскадної моделі показаний у лівій верхній частині малюнка 7. Продовження процесу виконання реалізується за допомогою упорядкованої послідовності кроків. У моделі передбачено, що кожна наступна фаза починається лише тоді, коли цілком довершене виконання попередньої фази. Кожна фаза має визначені критерії входу і виходу: вхідні і вихідні дані.

Малюнок 7 - Класична каскадна модель зі зворотним зв'язком

У результаті виконання генеруються внутрішні чи зовнішні дані проекту, включай документацію і ПО. Документи по аналізі вимог згодом передаються системним фахівцям, що у свою чергу передають їх розроблювачам програмних систем більш високого рівня. Програмісти передають детальні технічні характеристики програмістам, що вже представляють готовий код тестерам.

Перехід від однієї фази до іншої здійснюється за допомогою формального огляду. Таким чином, клієнт одержує загальне представлення про процес розробки, крім того відбувається перевірка якості програмного продукту. Як правило, проходження стадії огляду вказує на домовленість між командою розроблювачів і клієнтом про те, що поточна фаза довершена і можна перейти до виконання наступної фази. Закінчення фази зручно приймати за стадію в процесі виконання проекту.

У результаті завершення визначених фаз формується базова лінія, що у даній крапці "заморожує" продукти розробки. Якщо виникає потреба в їхній зміні, тоді для внесення змін використовується формальний процес змін.

У критичних крапках каскадної моделі формуються базові лінії, остання з який є базовою лінією продукту. Після формування заключної базової лінії виробляється огляд приймання.

Спроби оптимізації каскадної моделі привели до виникнення інших циклів розробки ПО. Прототипирование програм дозволяє забезпечити повне розуміння вимог, у той час як инкрементние і спіральні моделі дозволяють повторно повертатися до фаз, співвіднесеним із класичною каскадною моделлю, перш ніж отриманий продукт буде визнаний остаточним.

Відмітною властивістю каскадної моделі можна назвати те, що вона являє собою формальний метод, різновид розробки "зверху вниз", він складається з незалежних фаз, виконуваних послідовно, і піддана частому огляду.

а) Короткий опис фаз каскадної моделі

Приведена нижче характеристика являє собою короткий опис кожної фази каскадної моделі (включаючи фази інтеграції):

- дослідження концепції - відбувається дослідження вимог на системному рівні з метою визначення можливості реалізації концепції;

- процес системного розподілу - може бути пропущений для систем по розробці винятково ПО. Для систем, у яких необхідна розробка як апаратного, так і програмного забезпечення, необхідні функції застосовуються до ПО й устаткуванню відповідно до загальної архітектури системи;

- процес визначення вимог - визначаються програмні вимоги для інформаційної предметної області системи, призначення, лінії поводження, продуктивність і інтерфейси. (У разі потреби в процес також включений функціональний розподіл системних вимог до апаратного і програмного забезпечення.);

- процес розробки проекту- розробляється і формулюється логічно послідовна технічна характеристика програмної системи, включаючи структури даних, архітектуру ПО, интерфейсние представлення і процесуальну (алгоритмічну) деталізацію;

- процес реалізації - у результаті його виконання ескізний опис ПО перетворюється в повноцінний програмний продукт. При цьому створюється вихідний код, база даних і документація, що лежать в основі фізичного перетворення проекту. Якщо програмний продукт являє собою придбаний пакет прикладних програм, основними діями по його реалізації будуть установка і тестування пакета програм. Якщо програмний продукт розробляється на замовлення, основними діями є програмування і код-тестування;

- процес установки - включає установку ПО, його перевірку й офіційне приймання замовником для операційного середовища;

- процес експлуатації і підтримки - має на увазі запуск користувачем системи і поточне забезпечення, включаючи надання технічної допомоги, обговорення виниклих питань з користувачем, реєстрацію запитів користувача на модернізацію і внесення змін, а також чи коректування усунення помилок;

- процес супроводу- зв'язаний з дозволом програмних помилок, несправностей, збоїв, модернізацією і внесенням змін, генерируемих процесом підтримки. Складається з ітерацій розробки і припускає зворотний зв'язок по наданню інформації про аномалії;

- процес висновку з експлуатації - висновок існуючої системи з її активного використання або шляхом припинення її роботи, або завдяки її заміні новою чи системою модернізованою версією існуючої системи;

- інтегральні задачі - включають початок роботи над проектом, моніторинг проекту і його керування, керування якістю, верифікацію й атестацію, менеджмент конфігурації, розробку документації і професійну підготовку протягом усього життєвого циклу.

б) Переваги каскадної моделі

Неважко помітити, що каскадна модель має безліч переваг, якщо неї використовувати в проекті, для якого вона досить прийнятна. Нижче перераховані ці переваги:

- модель добре відома споживачам, що не мають відносини до розробки й експлуатації програм, і кінцевим користувачам (вона часто використовується іншими організаціями для відстеження проектів, не зв'язаних з розробкою ПО);

- вона упорядоченее справляється зі складностями і добре спрацьовує для тих проектів, що досить зрозумілі, але усе-таки важко розв'язні;

- вона дуже доступна для розуміння, тому що переслідується проста мета - виконати необхідні дії;

- вона проста і зручна в застосуванні, тому що процес розробки виконується поетапно;

- її структурою може керуватися навіть слабко підготовлений у технічному чи плані недосвідчений персонал;

- вона відрізняється стабільністю вимог;

- вона являє собою шаблон, у який можна помістити методи для виконання аналізу, проектування, кодування, тестування і забезпечення;

- вона добре спрацьовує тоді, коли вимоги до якості домінують над вимогами до витрат і графіка виконання проекту;

- вона сприяє здійсненню строгого контролю менеджменту проекту;

- при правильному використанні моделі дефекти можна знайти на більш ранніх етапах, коли їхнє усунення ще не вимагає щодо великих витрат;

- вона полегшує роботу керівнику проекту по складанню плану і Комплектації команди розроблювачів;

- вона дозволяє учасникам проекту, що завершили дії на виконуваній ними фазі, взяти участь у реалізації інших проектів;

- вона визначає процедури по контролі за якістю. Кожні отримані дані піддаються огляду. Така процедура використовується командою розроблювачів для визначення якості системи;

- стадії моделі досить добре визначені і зрозумілі;

- хід виконання проекту легко простежити за допомогою використання тимчасової шкали (чи діаграми Ганта), оскільки момент завершення кожної фази використовується як стадію.

в) Недоліки каскадної моделі

Але при використанні каскадної моделі для проекту, що важко назвати придатним для неї, виявляються наступними недоліки:

- в основі моделі лежить послідовна лінійна структура, у результаті чого кожна спроба повернутися на одну чи двох фаз назад, щоб виправити яку-небудь чи проблему недолік, приведе до значного збільшення витрат і збою в графіку;

- вона не може запобігти виникненню ітерацій між фазами, що так часто зустрічаються при розробці ПО, оскільки сама модель створюється відповідно до стандартного циклу апаратного інжиніринга;

- вона не відображає основну властивість розробки ПО, спрямоване на дозвіл задач. Окремі фази строго зв'язані з визначеними діями, що відрізняється від реальної роботи чи персоналу колективів;

- вона може створити помилкове враження про роботу над проектом. Вираження типу "35 відсотків виконане" - не несе ніякого змісту і не є показником для руководительа проекту;

- інтеграція всіх отриманих результатів відбувається раптово в завершальній стадії роботи моделі. У результаті такого одиничного проходу через весь процес, зв'язані з інтегруванням проблеми, як правило, дають про себе знати занадто пізно. Отже, проявляться не виявлені раніше чи помилки конструктивні недоліки, підвищити ступінь ризику при невеликому задачі часу на відновлення продукту;

- у клієнта навряд чи їсти можливість ознайомитися із системою заздалегідь, це відбувається лише в самому кінці життєвого циклу. Клієнт не має можливості скористатися доступними проміжними результатами, і відкликання користувачів не можна передати назад розроблювачам. Оскільки готовий продукт не доступний аж до закінчення процесу, користувач бере участь у процесі розробки тільки на самому початку - при зборі вимог, і наприкінці - під час приймальних іспитів;

- користувачі не можуть переконатися як розроблений продукт до закінчення всього процесу розробки. Вони не мають можливості оцінити якість, якщо не можна побачити готовий продукт розробки;

- у користувача немає можливості поступово звикнути до системи. Процес навчання відбувається наприкінці життєвого циклу, коли ПО вже запущено в експлуатацію;

- проект можна виконати, застосувавши упорядковану каскадну модель, і привести його у відповідність з письмовими вимогами, що, однак, не гарантує його запуску в експлуатацію;

- кожна фаза є передумовою для виконання наступних дій, що перетворює такий метод у ризикований вибір для систем, що не мають аналогів, тому що він не піддається гнучкому моделюванню;

- для кожної фази створюються результативні дані, що по його завершенню вважаються замороженими. Це означає, що вони не повинні змінюватися на наступних етапах життєвого циклу продукту. Якщо елемент результативних даних якого-небудь етапу змінюється (що зустрічається дуже часто), на проект уплине зміну графіка, оскільки ні модель, ні план не були розраховані на внесення і дозвіл зміни на більш пізніх етапах життєвого циклу;

- усі вимоги повинні бути відомі на початку життєвого циклу, але клієнти рідко можуть сформулювати всі чітко задані вимоги на цей момент розробки. Модель не розрахована на динамічні зміни у вимогах протягом усього життєвого циклу, тому що одержувані дані "заморожуються". Використання моделі може викликати значні витрати, якщо вимоги в недостатній мері відомі чи піддані динамічним змінам під час протікання життєвого циклу;

- виникає необхідність у твердому керуванні і контролі, оскільки в моделі не передбачена можливість модифікації вимог;

- модель заснована на документації, а виходить, кількість документів може бути надлишковим;

- весь програмний продукт розробляється за один раз. Ні можливості розбити систему на частині. У результаті узятих розроблювачами зобов'язань розробити целую систему за один раз можуть виникнути проблеми з фінансуванням проекту. Відбувається розподіл великих коштів, а сама модель навряд чи дозволяє повторно розподілити засобу, не зруйнувавши при цьому проект у процесі його виконання;

- отсутствует можливість врахувати переробку й ітерації за рамками проекту.

г) Область застосування каскадної моделі

Через недоліки каскадної моделі її застосування необхідно обмежити ситуаціями, у яких вимоги і їхня реалізація максимально чітко визначені і зрозумілі.

Каскадна модель добре функціонує при її застосуванні в циклах розробки програмного продукту, у яких використовується незмінне визначення продукту і цілком зрозумілі технічні методики.

Якщо компанія має досвід побудови визначеного роду системи - автоматизованого бухгалтерського обліку, нарахування зарплати, ревізії, компіляції, виробництва, - тоді в проекті, орієнтованому на побудову ще одного продукту такого ж типу, можливо, навіть заснованого на існуючих розробках, можна ефективно використовувати каскадну модель. Іншим прикладом належного застосування моделі може служити створення і випуск нової версії вже існуючого продукту, якщо внесені зміни цілком визначені і керовані. Перенос вже існуючого продукту на нову платформу часто наводять як ідеальний приклад використання каскадної моделі в проекті.

При всій справедливості критики цієї моделі усе-таки варто визнати, що модифікована версія каскадної моделі є в значній мірі менш твердої, чим її первісна форма. Тут включаються ітерації між фазами, рівнобіжні фази і менеджмент змін. Зворотні стрілки припускають можливість існування ітерацій між діями в рамках фаз. Щоб відобразити погодженість між етапами, їх поєднують чи прямокутниками під прямокутниками перелічують виконувані на даних етапах дії, щоб продемонструвати погодженість між ними. Незважаючи на те, що модифікована каскадна модель є значно більш гнучкої, чим класична модель, вона все-таки не є найкращим вибором для виконання проектів по прискореній розробці.

Каскадні моделі протягом усього часу їхнього існування використовуються при виконанні великих проектів, у яких задіяно кілька великих команд розроблювачів.

2.1.2 Екстремальна методологія

Батьком-ідеологом екстремального програмування (XP) вважають Кента Бека (Kent Beck). XP є досить молодою методологією, оцінки якої дуже суперечливі - від захоплених до різко негативних. Основними принципами є:

- Простота рішень (simplicity).

- Інтенсивна розробка малими групами (не більше 10 чоловік), активне спілкування в групі і між групами (communication).

- Зворотний зв'язок із клієнтом (feedback), що фактично вовлечен у процес розробки.

- Достатній ступінь сміливості (courage) і бажання йти на ризик.

Перший фактор прискорення розробки - итеративность: розробка ведеться короткими ітераціями при наявності активного взаємозв'язку з замовником. XP - це ітеративний процес розробки, що сам по собі не є революційним. Ітерації як такі пропонується робити короткими, що рекомендується тривалість - 2-3 тижня і не більш 1 місяця. За одну ітерацію група програмістів зобов'язана реалізувати кілька властивостей системи, кожне з який описується в користувальницькій історії (user story). Користувальницькі історії в даному випадку є початковою інформацією, на підставі якої створюється модуль. Користувальницькі історії відрізняються від прецедентів (use case): користувальницька історія коротка - 1-2 абзацу, тоді як прецеденти звичайно пишуть досить докладними, з основним і альтернативним потоками - таким чином, виходить приблизно сторінка плюс схема (найбільш розповсюджена формалізація в даний час запропонована в UML); історії користувачів пишуться самими користувачами (які в XP є частиною команди) на відміну від прецедентів, що звичайно пише системний аналітик. Відсутність формалізації опису вхідних даних проекту в XP прагнуть компенсувати за допомогою активного включення в процес розробки замовника як повноправного члена команди і за рахунок наявності постійного контакту з замовником (активне спілкування і безупинна підтримка зворотного зв'язку). У даному випадку extreme - це ступінь залучення замовника до програмістської кухні, що обумовлено прагненням зжати терміни розробки за рахунок комунікації і зворотного зв'язку.

Другий фактор прискорення розробки продукту - наявність малих груп і парне програмування (коли два програмісти разом створюють код на одному загальному робочому місці). Усе це націлено на досягнення високого рівня спілкування в групі, а також на як можна більш раннє виявлення проблем (як помилок, так і зриву термінів). Парне програмування має на меті стабілізації проекту, тому що при даній методології високий ризик утрати коду через відхід програміста, що не витримав інтенсивного графіка роботи. У цьому випадку другий програміст із пари відіграє роль "спадкоємця" коду (що в класичних методиках реалізується в технічній документації). Немаловажно і те, як саме розподілені групи в робочому просторі - у XP використовується відкритий робочий простір, що припускає швидкий і вільний доступ усіх до усім; як правило, робочий простір будується на основі кола.

Третій фактор прискорення розробки процесу - прийняття першого найпростішого робочого рішення. У даному випадку екстремальність методу зв'язана з високим ступенем ризику рішення, обумовленого поверховістю аналізу і твердим тимчасовим графіком. Реалізується мінімальний набір головних функцій системи на першій і кожній наступній ітерації; функціональність розширюється на кожній ітерації.

а) Практики екстремальної методології

Звичайно XP характеризують набором з 12 дій (практик), які необхідно виконувати для досягнення гарного результату. Практики XP не визначають сам процес XP, але XP визначає ці практики - тобто виконання практик не гарантує результату. Жодна з практик не є принципово нової, але в XP вони зібрані разом.

- Планування процесу (planning game). Уся команда збирається разом, приймається колективне рішення про те, які властивості системи будуть реалізовані в найближчій ітерації. Набір властивостей визначається користувальницькими історіями. XP-трудомісткість кожної властивості визначається самими програмістами.

- Тісна взаємодія з замовником (feed-back, on-site customer). Замовник повинний бути членом XP-команди (on-site customer). Він пише користувальницькі історії, вибирає історії, що будуть реалізовані в конкретній ітерації, і відповідає на питання, що стосуються бізнесу. Замовник повинний бути експертом в автоматизируемой предметної області. Необхідно постійна наявність зворотного зв'язку з замовником (feed-back).

- Метафора системи (system metaphor). Гарна метафора системи означає простоту іменування класів і перемінних. У реальному житті пошук метафори - украй складне заняття; знайти гарну метафору непросто. У будь-якому випадку команда повинна мати єдині правила іменування.

- Проста архітектура (simple design). Будь-яка властивість системи повинна бути реалізована як можна простіше. Програмісти в XP-команді працюють під девізом: "Нічого зайвого!". Приймається перше найпростіше працююче рішення, реалізується необхідний рівень функціональності на даний момент. Тим самим заощаджується час програміста.

- Стандарти кодування (coding conventions). Стандарти кодування потрібні для забезпечення інших практик: колективного володіння кодом, парного програмування і рефакторинга. Без єдиного стандарту виконувати ці практики як мінімум складніше, а в реальності взагалі неможливо: група буде працювати в режимі постійної недостачі часу. Детальні стандарти не вимагаються, необхідно стандартизувати тільки важливі речі. Визначення найбільш важливих об'єктів стандартизації в XP суб'єктивно.

- Рефакторинг (refactoring). Рефакторинг - це оптимізація існуючого коду убік спрощення, що передбачає постійну роботу зі спрощення коду. Зберігаючи код прозорим і визначаючи його елементи всего один раз, програмісти скорочують число помилок, що згодом прийдеться усувати. При реалізації кожної нової властивості системи програміст повинний подумати над тим, чи можна спростити існуючий код і як це допоможе реалізувати нову властивість. Крім того, не можна сполучати рефакторинг із дизайном: якщо створюється новий код, рефакторинг треба відкласти.

- Парне програмування (pair programming) - одна з найвідоміший XP-практик. Усі програмісти повинні працювати в парах: один пише код, іншої дивиться. Таким чином, необхідно розміщати групу програмістів в одному місці, що легше всего зробити на території замовника (усі необхідні члени команди географічно знаходяться в одному місці); XP найбільше успішно працює в нерозподілених колективах програмістів і користувачів.

- 40-годинний робочий тиждень. Програміст не повинний працювати більш 8 годин на день. Необхідність понаднормової роботи (overtime) - це чіткий індикатор проблеми на даному конкретному напрямку розробки; до того ж замовник не платить за понаднормову роботу в XP. Пошук причин понаднормової роботи і їхнє якнайшвидше усунення - одне з основних правил.

- Колективне володіння кодом (collective code ownership). Кожен програміст у колективі XP повинний мати доступ до коду будь-якої частини системи і вносити зміни в будь-який код. Обов'язкове правило: якщо програміст уніс зміни і система після цього працює некоректно, те саме цей програміст повинний виправити помилки. У противному випадку робота системи уподібниться тотальному хаосу.

- Часта зміна версій (small releases). Мінімальна ітерація - один день, максимальна - місяць; чим частіше здійснюються релизи, тим більше недоліків системи буде виявлено. Перші релизи допомагають виявити недоліки на самих ранніх стадіях, далі функціональність системи розширюється (на підставі тих же користувальницьких історій). Оскільки користувач включається в процес розробки починаючи з першого релиза, те він оцінює систему і видає користувальницьку історію плюс feedback. На підставі цього визначається наступна ітерація: яким буде новий релиз. У XP усе спрямовано на забезпечення безупинного зворотного зв'язку з користувачами.

- Безупинна інтеграція (continuous integration). Інтеграція нових частин системи повинна відбуватися якнайчастіше, як мінімум раз у кілька годин. Основне правило інтеграції наступне: інтеграцію можна робити, якщо всі тести проходять успішно. Якщо тести не проходять, то програміст повинний або внести виправлення і тоді інтегрувати складові частини системи, або взагалі не інтегрувати їх. Правило це тверде й однозначне - якщо в створеній частині системи мається хоча б одна помилка, то інтеграцію робити не можна. Часта інтеграція дозволяє швидше одержати готову систему, замість того щоб витрачати на зборку тиждень.

- Тестування (testing). На відміну від більшості інших методологій тестування в XP - одне з найважливіших складових. Екстремальний підхід полягає в тім, що тести пишуться до написання коду. Кожен модуль зобов'язаний мати unit test - тест даного модуля; таким чином, у XP здійснюється regression testing (поворотне тестування, "непогіршення якості" при додаванні функціональності). Більшість помилок виправляються на стадії кодування. Тести пишуть самі програмісти; будь-який програміст має право написати тест для будь-якого модуля. Ще один важливий принцип: тест визначає код, а не навпаки (такий підхід зветься test-driven development), тобто шматок коду кладеться в сховище тоді і тільки тоді, коли всі тести пройшли успішно, у противному випадку дана зміна коду відкидається.

Отже, XP украй зневажливо відноситься до всіх артефактів процесу розробки, крім вихідного коду. Процес XP є найвищою мірою неформальним, але вимагає високого рівня самодисципліни. Якщо це правило не виконується, то XP миттєво перетворюється в хаотичний і неконтрольований процес. XP не жадає від програмістів написання безлічі звітів і побудови маси моделей. У XP кожен програміст вважається кваліфікованим працівником, що професійно і з великою відповідальністю відноситься до своїх обов'язків. Якщо в команді цього ні, то впроваджувати XP абсолютно безглуздо - краще для початку зайнятися перебудовою команди. Ризик розробки знижується тільки в команді, який XP підходить ідеально, у всіх інших випадках XP - це процес розробки з найбільш високим ступенем ризику, оскільки інші методи зниження комерційних ризиків, крім банального людського фактора, у XP просто відсутні.

б) Існуючі ризики застосування методології

Варто виділити ризики XP, здатні завалити проект, якщо не враховувати і не запобігати їх.

- Етап планування (planning game). Програмісти реалізують тільки ті функції, що необхідні для можливостей, обраних на даній ітерації замовником. У результаті такого рішення за кадром залишається розвиток системи, унаслідок чого при розробці виникає необхідність будувати "заглушки" і переписувати код.

- Постійна участь замовника (on-site customer). Представник замовника в період роботи над системою знаходиться в команді розроблювачів, причому вимоги до кваліфікації цієї чи людини команди дуже високі. Якщо замовник не погодився надати персонал рівня експертів, то проект попадає в групу найбільш високого ризику.

- Метафора (metaphor). Загальний вид системи визначається за допомогою чи метафори набору метафор, над якими спільно працюють замовник і програмісти. Якщо не ведеться журнал даного процесу і структура найменувань не стандартизована, то такий процес може виявитися нескінченно ітераційним.

- Проста архітектура (simple design). У кожен момент часу розроблювальна система виконує всі тести і підтримує усі взаємозв'язки, обумовлені програмістом, не має дублікатів коду і містить мінімально можлива кількість класів і методів. Це правило коротке можна виразити так: "Кожну думку формулюй один і тільки один раз". Даний принцип вступає в протиріччя зі швидкістю написання коду. Без наявності високої самодисципліни і твердих стандартів коду система негайно попадає в групу ризику.

- Часта зміна версій (small releases). Систему запускають в експлуатацію вже через кілька місяців після початку реалізації, не чекаючи остаточного дозволу всіх поставлених проблем. Періодичність випуску нових версій може варіюватися від щоденної до щомісячної. Протестувати за такий термін більш-менш складний компонент неможливо; замовник фактично виступає в ролі бета-тестера. Системи, до яких пред'являється вимога безупинної надійної роботи (так називана вимога 24Ѕ7), входять у групу ризику.

- Переробка системи (refactoring). Архітектура системи постійно еволюціонує. Поточний проект трансформується, при цьому гарантується правильне виконання всіх тестів. Екстремальне програмування виходить з того, що переробити частину системи завжди можна, причому без особливих витрат. Однак практика досить часто свідчить про зворотний.

- Безупинна інтеграція (continuous integration). Новий код інтегрується в існуючу систему не пізніше чим через кілька годин. Після цього система знову збирається в єдине ціле і прогоняются всі тести. Якщо хоча б один з них не виконується коректно, внесені зміни скасовуються. У даному випадку не завжди зрозуміло, хто саме буде виправляти помилки, причому не тільки локальні, але і наведені неправильним кодом. Проведення комплексних тестів на даному етапі не передбачається; крім того, зміни зберігаються навіть у тому випадку, коли помилка виявлена.

- Програмування в парі (pair programming). Весь код проекту пишуть групи по двох людини, що використовують одне робоче місце. Людський фактор у даному випадку відіграє визначальну роль: чи пари чи працює ні, третього не дано.

- годинников-40-годинний тиждень (40-hour weeks). Обсяг понаднормових робіт не може перевищувати по тривалості один робочий тиждень. Навіть окремі випадки понаднормових робіт, що повторюються занадто часто, служать ознакою серйозних проблем, що вимагають невідкладного рішення. Як показує практика застосування екстремального програмування (незважаючи на цілий ряд позитивних прикладів, що приводяться прихильниками даного методу), понаднормова робота при такому підході - це правило, а не виключення, і боротьба з проблемами в даному випадку - явище постійне. Підсилюється вона в період заміни поточної сирої версії продукту черговий - менш сирої. Якщо замовник не одержує постійних доказів поліпшення системи, виходить, у вас виникли серйозні проблеми.

- Колективне володіння (collective ownership). Кожен програміст має можливість при необхідності в будь-який час удосконалити будь-яку частину коду в системі. Без стандарту контролю вихідного коду процес розробки здобуває абсолютно неконтрольований характер.

- Відкритий робочий простір (open workspace). Команда розроблювачів розташовується у великому приміщенні, оточеному кімнатами меншої площі. У центрі робочого простору встановлюються комп'ютери, на яких працюють пари програмістів (причому відповідно до вищевикладених принципів, усе це повиннео розташовуватися на території замовника, оскільки він дуже активно залучається до процесу розробки). При наявності територіально розподіленої групи розроблювачів і замовників проект вимагає стандартизації протоколу взаємодії (швидко, надійно, безвідмовно) чи попадає в групу ризику.

- Тести (tests). Програмісти постійно пишуть тести для модулів (unit tests). Зібрані разом, ці тести повинні працювати коректно. Для етапів ітерації замовники пишуть функціональні тести (functional tests), від яких також потрібно правильна робота. Однак на практиці це не завжди досяжно. Щоб прийняти вірне рішення, необхідно зрозуміти, у що обійдеться здача системи з заздалегідь відомим дефектом, і порівняти це з ціною затримки на його усунення. Тести, написані самими програмістами (особливо в умовах понаднормових робіт), не є полнофункциональними і вуж тим більше не враховують особливостей многопользовательской роботи. На більш просунуті тести в розроблювачів звичайно бракує часу. Зважується дана проблема шляхом залучення на певний строк контакторів, що зв'язано з великою роллю людського фактора: оскільки технічна документація споконвічно отсутствует, те інформація передається за допомогою спілкування програмістів. Хоча, звичайно, можна побудувати систему розробки таким чином, що від початку до кінця усім будуть займатися ті самі люди. До сказаного необхідно додати, що тестування системи зовсім не вичерпується тестами компонентів (units); не менш важливі тести взаємодії між ними, це ж відноситься і до тестів надійності роботи. І проте метод екстремального програмування не передбачає створення тестів даного класу. Це порозумівається тим, що самі подібні тести можуть представляти досить складний код (особливо це стосується тестів - імітаторів реальної роботи системи). У даній технології також ніяк не враховується ще один важливий клас тестів - тести поводження системи при росту обсягів оброблюваної інформації. При високій частоті зміни версій виконати такий тест технологічно неможливо, оскільки його проведення вимагає стабільного і незмінного коду проекту, наприклад протягом тижня. У такому випадку чи прийдеться припиняти розробку компонентів, чи створювати на час проведення тесту рівнобіжну версію проекту, що буде зберігатися незмінної, тоді як інша при цьому буде змінюватися. Потім потрібно буде виконати процес злиття коду. Але в цьому випадку тест прийдеться створювати заново, тому що методи екстремального програмування просто не передбачають розробку засобів, що дозволяють прогнозувати поводження системи при тих чи інших змінах. Вирішувати дані проблеми в XP пропонується за допомогою усі того ж людського фактора і самодисципліни.

- Не більш ніж правила (just rules). Члени колективу, що працює за технологією екстремального програмування, зобов'язуються виконувати викладені правила. Однак це не більш ніж правила, і команда може в будь-який момент змінити їх, якщо її члени досягнуть принципової угоди з приводу внесених змін. Даний принцип серйозно залежить від людського фактора; порушення дисципліни розробки спричиняє зриви термінів і в результаті веде до краху проекту.

У підсумку ми одержуємо метод, що потенційно володіє високою адаптацією до серйозно і часто змінюються вимогам до проекту, але в той же час не вільний від ряду принципових недоліків і в дуже високому ступені залежний від людського фактора.

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

2.2 Вибір інструментальних засобів

Як єдине середовище розробки, як для транслятора партій так і для реєстратора було обране середовище NetBeansIDE. NetBeans IDE - вільне інтегроване середовище розробки додатків (IDE) мовою програмування Java, Ruby, C++ і ряді інших. Середовище розробки NetBeans за замовчуванням підтримують розробку для платформ J2SE і J2EE. Для розробки програм у середовищі NetBeans і для успішної інсталяції і роботи самого середовища NetBeans повинний бути попередньо встановлений Sun JDK чи J2EE SDK придатної версії. Для підтримки розробки в середовищі NetBeans для мобільних платформ (J2ME) необхідно установити окремо розповсюджуваний (і також безкоштовний) NetBeans Mobility Pack (доступний тільки для Linux і Windows). Проект NetBeans IDE підтримується і спонсируется фірмою Sun Microsystems, однак розробка NetBeans ведеться незалежно співтовариством розроблювачів-ентузіастів (NetBeans Community) і компанією NetBeans Org. По якості і можливостям останні версії NetBeans IDE не уступають кращим комерційної (платним) інтегрованим середовищам розробки для мови Java, таким, як Intelli IDEA, підтримуючи рефакторинг, профілювання, виділення синтаксичних конструкцій кольором, автодополнение конструкцій, що набираються, на лету, безліч визначених шаблонів коду й ін. У версії NetBeans IDE 6.0 декларується підтримка UML, SOA, мови програмування Ruby (включаючи підтримку Ruby on Rails), а також засобу для створення додатків на J2ME для мобільних телефонів (Linux, Windows). NetBeans IDE підтримує плагини, дозволяючи розроблювачам розширювати можливості середовища. На ідеях, технологіях і в значній частині на вихідному коді NetBeans IDE базуються пропоновані фірмою Sun комерційні інтегровані середовища розробки для Java - Sun Java Studio Creator, Sun Java Studio Enterprise і Sun Studio (для ведення розробки на C, C++ чи Фортран). Порівняно недавно Sun стала пропонувати ці середовища розробки безкоштовно для зареєструвалися в Sun Developer Network (SDN) розроблювачів, сама ж реєстрація на сайте безкоштовна і не вимагає ніяких попередніх умов, крім згоди з ліцензією CDDL. NetBeans IDE доступна у виді готових дистрибутивів (прекомпилированних бинарников) для платформ Microsoft Windows, GNU/Linux, FreeBSD, Mac OS X і Solaris (як для SPARC, так і для x86 - Intel і AMD). Для всіх інших платформ доступна можливість зібрати NetBeans самостійно з вихідних текстів.

Корпорація Sun Microsystems додала підтримку Ruby до свого інтегрованого середовища розробки NetBeans і розширила платформу JRuby. Перша версія NetBeans Ruby Pack містить модуль, що підключається, для вільно розповсюджуваного середовища розробки NetBeans, що підтримує Ruby і JRuby. Останній являє собою Java-реалізацію Ruby, що працює з віртуальною машиною Java. Платформа NetBeans у першу чергу орієнтована на Java, але може бути розширена і до Ruby. Як правило, розроблювачі, що пишуть програми на цій мові, не використовують інтегровані середовища розробки. Однак, як підкреслив Тор Норби, старший інженер Sun, "запропоноване корпорацією рішення являє собою значно більш продуктивне середовище, чим усе, що існувало для Ruby раніше".

2.3 Змістовна постановка задачі створення СШПО

Предметна область

Спеціалізоване шахове програмне забезпечення (СШПО) призначено для переносу шахових партій, що граються, в електронну форму, трансляції ігор для присутньої на змаганнях аудиторії й у мережі Інтернет. Користувачами СШПО буде персонал структурного підрозділу "Шаховий клуб" ГОУ ВПО "Сибгиу" і персонал МУДОД "СДЮСШОР по шахам".

Дано:

Діюча ИС "Шаховий клуб".

Прототипи інформаційної системи.

Безліч моделей життєвого циклу (МЖЦ) розробки програмного забезпечення.

Інструментальні засоби розробки ПО.

Загальні вимоги до СШПО:

- працездатність у всіх сучасних операційних системах (ОС),

- безперервність роботи в ході усього соревновательного процесу,

- можливість одержання коректної й оперативної інформації про змагання за межами турнірного залу і з будь-якої крапки земної кулі по мережі Інтернет,

- нагромадження і збереження інформації із соревновательному процесу,

- економія часу і засобів на перенос партій в електронну форму,

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

- облік можливості виправлення неправильного плину ігрового процесу.

Обмеження:

При виборі МЖЦ обмежитися каскадної й екстремальний МЖЦ розробки програмного забезпечення.

1. При виборі інструментальних засобів розробки СШПО обмежитися наступними програмними продуктами: NetBeans IDE 6.0, MySQLAdministrator.

2. У ході функціонування СШПО під час соревновательного процесу повинні виконуватися наступні умови:

- СШПО повинно функціонувати без простоїв у плині всього ігрового дня.

- Відображуваний хід повинний цілком відповідати ходу, зробленому на електронній шахівниці.

- Тимчасова затримка трансляції, якщо вона заздалегідь не передбачена, не повинна перевищувати 0,5 секунди.

- Тимчасова затримка переносу ігрового процесу в електронну форму не повинна перевищувати 0,5 секунди.

Потрібно

Реалізувати СШПО з урахуванням усіх вимог і обмежень

2.4 Розробка алгоритму рішення задачі

Реєстратор шахових партій (РШП) реалізується мовою Java (j2se). РШП реалізує протокол обміну даних DGT шахових електронних дощок, що у свою чергу базується на прокотоле обміну через послідовний порт RS-232. Як компонент для роботи з послідовним портом у Java була обрана бібліотека rxtx версії 1.72. Протокол DGT приведений у додатку 6 у виді заголовного C файлу (header). Задача РШП здійснювати трансляцію партій, при цьому зміни позиції партій зберігаються в базу даних, відкіля ці дані одержує Транслятор шахових партій (ТШП). Формат запису, у якому записуються шахові ходи в базу даних, наступний:

[фігура{K(король),Q(ферзь),N(кінь),B(слон),R(тура),' '(пішак)}][вертикаль вихідного полючи][горизонталь вихідного полючи]-[вертикаль полючи призначення][горизонталь полючи призначення].

Наприклад:

Kg8-g7

Ng1-f3

e2-e4

Дані, одержувані РШП від електронної дошки, інтерпретуються відповідно до опису в протоколі DGT. Наприклад, дамп дошки виходить у виді 64 ASCII символів (інформативна частина повідомлення) - 'rnbqkbnrppppppppPPPPPPPPRNBQKBNR' перетвориться у вид:

Малюнок 8 - Результат перетворення інформативної частини повідомлення від ЕШД

ТШП реалізований на технології RubyonRails. Rails - це повноцінний, багаторівневий фреймворк для побудови веб-приложений, що використовують бази даних, що заснований на архітектурі Модель-Представлення-Контролер (Model-View-Controller, MVC). Динамічний AJAX-інтерфейс, обробка запитів і видача даних у контролерах, предметна область, відбита в базі даних, - для всього цього Rails надає однорідне середовище розробки на Ruby. Усе, що необхідно для початку - база даних і веб-сервер. Rails відмінно працює з багатьма веб-серверами і СУБД. Як веб-сервера можна використовувати Apache чи lighttpd як з FastCGI, так і з SCGI. У якості СУБД можна використовувати MySQL, PostgreSQL, SQLite, Oracle, SQL Server, DB2 чи Firebird. Використовувати Rails можна на практично будь-якій операційній системі.

Задача ТШП створювати трансляції і віщати шахові партії. У ТШП передбачена система авторизації, що дозволяє гнучко набудовувати права користувачів зареєстрованих у системі, за замовчуванням існують три профілі користувачів: Адміністратор (права на усіх), Керівник (йому належать права на створення/редагування online трансляций, турнірів, коментування партій і т.д.) і Гість (тільки перегляд партій).

Модуль віщання партій реалізований за допомогою скриптов JavaScript, при цьому відновлення позиції запитується із сервера через AJAX запити, без відновлення всієї сторінки.

Листинг модуля віщання партій представлений у додатку 10.

2.5 Опис розробленого програмного комплексу

2.5.1 Транслятор шахових партій

У загальному виді транслятор шахових партій (ТШП) являє собою наступні структури:

- моделі даних (models);

- представлення (views);

- контролери (controllers);

- помічники (helpers).

Моделі даних містять об'єктні представлення, задачі у виді класів бізнеси-логіки. Тут описуються класи, до яких будуть віднесені реальні дані. Бізнесу-логіка керується однойменним контролером, наприклад, клас Cities (міста) керується однойменним контролером cities_controller.rb. Модель може мати одне чи кілька представлень, що відповідають за те, у якому виді будуть відображатися дані. Крім контролерів усіх класів існує головний контролер main_controller.rb (у якості головного може бути призначений будь-який контролер). Він виконує усі функції по обслуговуванню шахового інтернет-порталу:

- відображення головної веб-страници;

- повернення до попереднього веб-странице;

- показ партій у режимі реального часу (online) і архіву турнірних партій (offline);

- авторизація користувачів;

- вхід в особистий кабінет користувача;

- нагадування при втраті чи пароля логина;

- показ трансляції;

- вивантаження шахових партій у форматі pgn (portablegamenotation);

- вихід користувача;

- інтерфейс реєстрації і т.д.

Знімки екрана (Screenshots) головної сторінки rDGT-сервера, сторінки авторизації користувача, сторінки перегляду поточних online трансляций і сторінки перегляду шахових партій представлені в додатку 5.

Скрипт трансляції шахової партії реалізований мовою Javascript. Відновлення позиції здійснюється через асинхронні javascript-запити до rDGT-сервера при використанні технології Ajax без відновлення всієї сторінки.

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

Веб-интерфейс реалізований на платформі RubyonRails, відповідно до ідеології викладеної в розділі 2.4. Портал можна розділити на кілька вузлових розділів:

- Роздягнув трансляций партій (online режим).

- Роздягнув перегляду партій, збережених на сервері (offline режим).

- Роздягнув редагування даних порталу, має на увазі авторизацію користувача, якому доступні:

- додавання, видалення, зміна турнірів;

- додавання, видалення, зміна гравців;

- додавання, видалення, зміна трансляций;

- додавання, видалення, зміна даних різних довідників (регламент проведення турніру, годинні регламенти, країни, міста).

Загальна структура транслятора шахових партій, всі атрибути і методи його структурних елементів представлені в додатку 7

2.5.2 Реєстратор шахових партій

Алгоритм роботи:

Користувач у веб-интерфейсе формує трансляцію партій, при цьому він указує наступні параметри:

- Назва послідовного порту (serialport), до якого підключені дошки, з яких буде відбуватися трансляція шахових партій ("COM1", "COM2" і т.п. для операційної системи Windows і "/dev/tty0", "/dev/tty1" для операційної системи Linux).

- Час початку трансляції.

- Для кожної дошки вказується гравець, що грає білим кольором, і гравець, що грає чорним кольором.

- Асоціює дану трансляцію з заздалегідь заданим турніром.

Веб-сервер після складання заявки на трансляцію партій, запускає додаток jgdtnix, параметризуя його введеними параметрами. Jgdtnix до призначеного часу переходить у "сплячий" режим, а за кілька хвилин до початку трансляції jgdtnix починає опитувати порт на наявність доступних дощок і реєструє їх. Під час трансляції jgdtnix з визначеною періодичністю опитує порт, одержує відновлення позиції і дані із шахових годин, і заносить ходи в базу даних.

Загальна структура реєстратора шахових партій, всі атрибути і методи його структурних елементів представлені в додатку 8.

2.6 Тестові іспити й аналіз результатів

Тестові іспити проводилися в приміщенні СП "ШК" у терміни з 5 червня по 11 червня 2008 року на Чемпіонаті області по шахам серед юнаків до 12 років. Кількість використовуваних в іспитах ЕШД і електронних шахових годин - 5 штук,. Трансляція соревновательного процесу здійснювалася протягом усього зазначеного терміну з 11:00 до 15:00, що відповідає тривалості ігрового дня. Схема підключення ЕШД і електронних шахових годин аналогічна малюнку 3 пункти "Огляд шахових систем-прототипів" з тією лише різницею, що трансляція шахових партій здійснювалася не тільки для присутньої аудиторії, але й у мережі Інтернет.

Аналіз результатів тестових іспитів представлений у додатку 9.

Як порівняльний показник використовується загальне число шахових ходів, зроблених на всіх дошках протягом усього соревновательного процесу. Тому що число ігрових днів - 7, число дощок, що враховуються - 5, а середнє число ходів у шаховій партії 30, те загальне число шахових ходів дорівнює дорівнює 1050.

http://www.compress.ru/Archive/CP%5C2003%5C10%5C65/http:/www.cpress.ru/

3 Техніко-економічне обґрунтування проекту

3.1 Доцільність і область застосування розробки

У даному техніко-економічному обґрунтуванні розглядається спеціалізоване шахове програмне забезпечення, розроблене для автоматизації діяльності інформаційної системи структурного підрозділу "Шаховий клуб" у рамках упровадження комплексної інформаційної системи структурного підрозділу "Шаховий клуб" ГОУ ВПО "Сибірський державний індустріальний університет".

3.1.1 Ефект від впровадження інформаційних систем

Інформатизація заради інформатизації не має змісту. Інформаційна система - це економічний товар, і як будь-який товар вона має ціну. Одним з перших критеріїв при впровадженні такої системи є зіставлення вигод, принесених нею, з витратами на її впровадження, супровід і підтримку, тобто мета повинна виправдувати засобу.

Вигоду від впровадження інформаційної системи можна розділити на дві складові - організаційну й економічну. Перша зв'язана з загальними змінами навчального і соревновательного процесів, упровадженням більш прогресивних методів проведення спортивних змагань, підвищенням загальної культури керування, зниженням паперового документообігу, використанням нових, більш оптимальних схем побудови навчального і соревновательного процесів. Це, так сказати, якісні поліпшення, і вони є скоріше наслідком, чим метою інформатизації. Поліпшення з ними зв'язані, представляють набір управлінських рішень, що дозволяє успешнее досягати цілей, поставлених керівництвом.

Крім підвищення загальної культури керування, інформатизація допомагає установі в побудові взаємин з потенційними партнерами й інвесторами. Не секрет, що спонсори зацікавлені в економічно привабливих інформаційних системах, що можуть бути використані не тільки по безпосередньому призначенню, але й у рекламних цілях.

Під економічними вигодами від упровадження мається на увазі одержання реальної економічної віддачі від використання всього пакета чи додатків окремих функціональних блоків. Відповідно до статистики впровадження інформаційних систем і систем інформаційного супроводу може забезпечити наступну віддачу:

- усунення ручної підготовки і супроводу документів;

- зменшення витрат на адміністративно-управлінський апарат;

- більш точний облік витрат;

- більш повне інформаційне забезпечення кінцевих користувачів і споживачів;

- зменшення термінів інформування кінцевих користувачів і споживачів.

Навіть найкраща у світі комп'ютерна система не в змозі виконати роль "чарівної палички", як по помаху всі накопившиеся проблеми, що знімає. Впровадження інформаційної системи - це спільна праця, як постачальника, так і замовника. Така система покликана в першу чергу підтримувати регулярний менеджмент. Якщо ж в установі такого чи не існує ні хоча б спроб його налагодити, інформаційна система споконвічно приречена бути "стороннім тілом". Тому реальну віддачу від інформаційної системи можна одержати тільки при правильній організації проекту впровадження і при бажанні перших облич організації створити прибуткову, ефективно працюючу структуру інформаційного супроводу.

3.1.2 Інформатизація діяльності СП "ШК"

В даний час на ринку програмних продуктів існують різні прикладні інформаційні рішення для інформаційного забезпечення діяльності структурного підрозділу "Шаховий клуб". Однак в усіх у них один загальний і дуже істотний недолік - відсутність підтримки трансляций соревновательного процесу в мережі Інтернет і локальні мережі. Програмне забезпечення подібного роду найчастіше є об'єктом інтелектуальної власності і поширюється за рішенням власників. Програмне забезпечення, що поставляється в комплекті з електронними шахівницями, не відповідає необхідним вимогам і в багатьох випадках є неробочим.

З цієї ситуації є 3 виходи: запрошувати фахівців з міжнародних шахових організацій на обслуговування процесу змагань, що спричиняє дуже значні витрати; намагатися знайти якісне програмне забезпечення на ринку, що дуже проблематично, тому що власники інтелектуальної власності не хочуть з ним розставатися, а воліють користатися їм самостійно, заробляючи гроші на обслуговуванні змагань; розробляти власне програмне забезпечення.

Перші два шляхи були уже випробувані. На обслуговування Всесвітньої студентської універсіади, що проводилася з 3 по 11 березня 2008 року були запрошені фахівці з інформаційного центра російської шахової федерації. У результаті ці послуги обійшлися організаторам приблизно в 100000 карбованців, що дуже накладно. Після проведення цього великого спортивного форуму організаторами була почата спроба налагодити комерційні зв'язки з обслуговуючими турнір фахівцями з метою покупки програмного забезпечення для особистого використання, однак ця пропозиція була зігнорована. У зв'язку з цими обставинами автором дипломного проекту за узгодженням з керівництвом структурного підрозділу "Шаховий клуб" ГОУ ВПО "Сибгиу" і керівництвом МУДОД "СДЮСШОР по шахам імені Б. А. Кустова" було прийняте рішення про самостійну розробку спеціалізованого шахового програмного забезпечення з метою особистого і комерційного використання.

3.2 Розрахунок витрат на розробку спеціалізованого шахового програмного забезпечення

Прорахуємо економічну ефективність розробки спеціалізованого програмного забезпечення в грошовому еквіваленті.

Витрати на розробку спеціалізованого програмного забезпечення складаються з заробітної плати розроблювачам, витрат на придбання, монтаж і експлуатацію устаткування, матеріалів, витрат на придбання ліцензійних програмних продуктів, необхідних для розробки.

Розроблювачами спеціалізованого програмного забезпечення є: керівник проекту - адміністратор МУДОД "СДЮСШОР по шахам ім. Б. А. Кустова" і інженер структурного підрозділу "Шаховий клуб".

У таблиці 1 представлені основні етапи проведення роботи.

Таблиця 1 - Оцінка завантаження виконавців

етапу

Найменування робіт

Длитель-ность, дні

Виконавець

Коефіцієнт завантаження, відсотки

1

Постановка задачі

3

керівник

50%

інженер

50%

2

Збір вихідних матеріалів

3

керівник

75%

інженер

25%

3

Визначення вимог до програми

3

керівник

50%

інженер

50%

4

Узгодження і твердження ТЗ

2

керівник

50%

інженер

50%

5

Вивчення літератури по темі завдання

7

інженер

100%

6

Уточнення структури і форми представлення даних.

Розробка структури програми

7

інженер

100%

7

Розробка плану заходів щодо впровадження програми,

пояснювальної записки.

3

інженер

100%

8

Програмування

20

інженер

100%

9

Тестування програми

7

інженер

100%

10

Написання програмної документації

7

інженер

100%

11

Підготовка і передача програми і програмної документації для супроводу і твердження.

7

інженер

25%

керівник

75%

Разом

69

3.2.1 Витрати на оплату праці розроблювачів програми

Розмір місячного окладу для інженера структурного підрозділу "Шаховий клуб" складає 3000 карбованців.

Розмір місячного окладу для керівника складає 4000 карбованців.

Думаючи, що в місяці 21 робітник день, розрахуємо вартість одного робочого дня. Розрахунок окладу розроблювачів програми за один робітник день приведений у таблиці 2.

Розрахунок основної заробітної плати приведений у таблиці 3.

Таблиця 2 - Розрахунок окладу співробітників за один робітник день

Посада

Оклад на місяць, руб.

Вартість одного робочого дня, руб.

Керівник

4 000,00

190,48

Програміст

3 000,00

142,86

Таблиця 3 - Розрахунок основної заробітної плати співробітників за період розробки програми

Виконавець

Трудомісткість, днів

Вартість одного робочого дня, руб.

Сума, руб.

Керівник

11,5

190,48

2190,52

Програміст

57,5

142,86

8214,45

Разом

69

333,34

10404,97

3.2.2 Витрати на відрахування єдиного соціального податку

Відрахування по єдиному соціальному податку (ЕСН), що складає 26 % від заробітної плати, рівні:

ЗЕСН=10404,97*0.26=2705,29 руб.

3.2.3 Витрати на придбання устаткування для розробки спеціалізованого програмного забезпечення

Витрати на придбання устаткування визначаються по формулі:

(1)

де - вартість устаткування;

- витрати на транспортування (8% від );

- витрати на монтаж (10% від ).

Перелік придбаного устаткування і витрати на нього приведені в таблиці 4.

Таблиця 4 - Перелік придбаного устаткування і витрати на нього

Найменування устаткування

Кількість

, руб.

, руб.

, руб.

, руб.

Принтер (HP LaserJet 1010)

1

5200

416

520

6136

Маніпулятор Logitech

2

1200

96

120

1416

Разом:

6 200

496

620

7552

3.2.4 Витрати на придбання матеріалів

На цю статтю відноситься вартість матеріалів, покупних виробів, напівфабрикатів і інших матеріальних цінностей, що витрачаються безпосередньо в процесі виконання проекту. Ціна матеріальних ресурсів визначається по відповідним цінниках. У вартість матеріальних витрат включаються транспортні витрати (5% від прейскурантної ціни). Розрахунок статті "Матеріали" приводиться в таблиці 5.

Таблиця 5 - Матеріали і покупні вироби і послуги

Найменування

Одиниця виміру

Кількість

Ціна за одиницю, руб

Вартість, руб.

Папір для принтера

пачка

1

120

120

Чорнило

мл

100

0,8

80

Лазерні диски

шт

5

15

75

Оплата за інтернет

година

15

30

450

Разом:

725

3.2.5 Витрати на придбання ліцензійних програмних продуктів

Для розробки спеціалізованого шахового програмного забезпечення вимагаються наступні ліцензійні програмні продукти:

- середовище розробки NetBeans IDE 6.0;

- програмний пакет для створення і розробки баз даних MySQLAdministrator;

- програмний пакет Ruby-186-26;

- драйвер опитування електронних шахівниць dgtnix.

Усі перераховані програмні продукти є абсолютно безкоштовними. Перший, другий і третій з них поширюються по ліцензії з відкритим вихідним кодом LGPL, останній з них також поширюється безкоштовно, але по ліцензії з відкритим вихідним кодом GPL.

3.2.6 Витрати на споживану електроенергію

До цієї статті відноситься вартість споживаної електроенергії комп'ютером за час розробки програми.

Вартість електроенергії, споживаної при розробці спеціалізованого програмного забезпечення, визначається по формулі (2):

(2)

де - сумарна потужність ЕОМ, квт;

- час роботи комп'ютера, година;

- вартість 1 квт*год електроенергії, руб.

Оскільки стандартний робітник день дорівнює 8 годинник, те

,

де - час експлуатації комп'ютера при створенні спеціалізованого програмного забезпечення, днів.

Отже, вартість електроенергії за період роботи комп'ютера під час створення спеціалізованого шахового програмного забезпечення буде обчислюватися по формулі (5):

,(3)

Відповідно до технічного паспорта ЕОМ Ревм=0,25 квт, а вартість 1 квт/год електроенергії по місту =0,96 руб.

Тоді розрахункове значення витрат на електроенергію:

3.2.7 Накладні витрати

Накладні витрати включаються в суму витрат на розробку спеціалізованого програмного забезпечення і приймаються 10% від витрат на заробітну плату й ЕСН.

3.2.8 Кошторис витрат на розробку системи

Кошторис витрат на розробку системи приведений у таблиці 6.

Таблиця 6 - Кошторис витрат на розробку системи

Найменування витрат

Сума, руб.

Витрати на заробітну плату розроблювачам

10404,97

Витрати на ЕСН

2705,29

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

7552

Витрати на придбання матеріалів

725

Витрати на придбання ліцензійних програмних продуктів

-

Витрати на електроенергію

178,56

Накладні витрати

1311,03

Разом:

22876,85

3.3 Розрахунок експлуатаційних витрат

Експлуатаційні витрати визначаються по формулі:

(4)

де - витрати на заробітну плату;

- витрати на амортизаційні відрахування;

- витрати на електроенергію;

- витрати на матеріали;

- витрати на поточний ремонт устаткування і пристроїв системи;

- накладні витрати.

3.3.1 Витрати на заробітну плату

За працездатністю спеціалізованого шаховий програмного забезпечення буде стежити інженер структурного підрозділу "Шаховий клуб", частка заробітної плати якого складає 500 карбованців на місяць.

Відрахування ЕСН (26%) складуть: 500*0,26 = 130 карбованців/місяць

3.3.2 Витрати на амортизаційні відрахування

Амортизаційні відрахування розраховуються по формулі:

(5)

де - вартість устаткування, руб.;

- норма амортизації.

Розрахунок витрат на амортизацію приведений у таблиці 7.

Таблиця 7 - Витрати на амортизаційні відрахування

Найменування

Кіл.

Загальна вартість, руб.

Норма амортизації, %.

Сума, руб.

Принтер (НР LaserJet 1010)

1

6 136

12,5

767

Маніпулятор Logitech

2

1416

12,5

177

Разом:

944

3.3.3 Затратинаелектроенергию

Витрати на електроенергію розраховуються по формулі:

(6)

де - потужність i-го устаткування;

n - кількість струмоприймачів;

- час роботи i-того устаткування, година.

(7)

де - кількість робочих днів у році;

- норматив середньодобового завантаження, ч.;

- коефіцієнт використання i-того устаткування;

- вартість 1 квт/год електроенергії.

Розрахунок витрати на електроенергію приведені в таблиці 8.

Таблиця 8 - Розрахунок витрат на електроенергію

Найменування пристрою

Кіл.

Р, Ут

Дг, днів

ч.

Т, ч.

ДО

Сел (квт/ч), руб.

Зел, руб.

ПК (Celeron 1.7 GHz)

1

250

366

8

2920

0,5

0,96

350,4

Монітор (Samsung 17")

1

80

366

8

2920

0,5

0,96

112,13

Принтер (НР LaserJet 1010)

1

200

366

6

2190

0,1

0,96

42,05

Разом:

504,58

3.3.4 Витрати на матеріали

Перелік видаткових матеріалів і витрати на них приведений у таблиці 9.

Таблиця 9 - Перелік видаткових матеріалів і витрати на них

Найменування матеріалу

Кількість

Вартість за 1 ед., руб.

Доставка (8%),

руб.

Сума, руб.

Папір офісна (формат А4)

4

120

9,6

518,4

Тонер для принтера

3

180

14,4

583,2

Разом:

1 101,6

3.3.5 Витрати на поточний ремонт устаткування і пристроїв системи

Витрати на поточний ремонт устаткування складають 5% у рік від його вартості (таблиця 10).

Таблиця 10 - Розрахунок витрат на поточний ремонт устаткування

Найменування устаткування

Кіл.

Загальна вартість, руб.

Норматив витрат на ремонт, %

Сума, руб.

Принтер (НР LaserJet 1010)

1

5 200

0,05

260

Маніпулятор Logitech

2

1 200

0,05

60

Разом:

320

3.3.6 Кошторис експлуатаційних витрат

Кошторис експлуатаційних витрат приведений у таблиці 11.

Таблиця 11 - Кошторис експлуатаційних витрат

Найменування витрат

Сума, руб.

Витрати на заробітну плату

6000

Витрати на ЕСН

1560

Витрати на амортизаційні відрахування

944

Витрати на електроенергію

504,58

Витрати на матеріали

1 101,6

Витрати на поточний ремонт устаткування і пристроїв системи

320

Разом:

10430,18

3.4 Оцінка економічної ефективності проекту

Для з'ясування економічної вигоди від розробки спеціалізованого шахового програмного забезпечення необхідно проаналізувати й оцінити його переваги.

Дана розробка призначена для інформаційного забезпечення навчального процесу і спортивних змагань, проведених у структурному підрозділі "Шаховий клуб" ГОУ ВПО "Сибгиу", а також спортивних змагань по шахам будь-якого рівня, проведених з використанням електронних шахівниць DGT. Вона забезпечить ефективний інформаційний супровід проведених у приміщенні структурного підрозділу "Шаховий клуб" спортивних змагань, висвітлення соревновательного процесу в мережі Інтернет і локальної мережі ГОУ ВПО "Сибгиу", дозволить цілком відмовитися від періодичних послуг найманих робітників. Крім того, дана розробка буде приносити прибуток при комерційному використанні.

Річна економія від упровадження системи визначається по формулі:

(8)

де Е1, Е2, Е3- економія в рік по факторах;

Секс- експлуатаційні витрати в рік.

3.4.1 Виключення витрат на послуги складачів

Щороку в приміщенні структурного підрозділу "Шаховий клуб" проводиться в середньому 10 великих спортивних змагань, на період проведення яких наймається 2 складача, в обов'язку яких входить переклад запису шахових партій з паперової форми в електронну. Величина оплати послуг одного складача за один турнір складає 2000р. Таким чином, загальні витрати на послуги складачів складають 40000р. у рік.

Дане спеціалізоване програмне забезпечення дозволяє цілком автоматизувати переклад запису шахових партій в електронну форму.

Е1=40 000 руб.

3.4.2 Виключення витрат на висвітлення змагань у мережі Інтернет

Усі значні змагання, що проводяться в приміщенні структурного підрозділу "Шаховий клуб" відповідно до регламенту повинні бути освітлені в мережі Інтернет. Висвітлення соревновательного процесу в мережі Інтернет входить в обов'язку головного арбітра змагань. Головний арбітр відряджається міським МУДОД "СДЮСШОР по шахам ім. Б. А. Кустова" у шаховий клуб ГОУ ВПО "Сибгиу" на проведення турніру. Витрати по оплаті роботи головного судді по проведенню спортивних змагань бере на себе міське МУДОД "СДЮСШОР по шахам ім. Б. А. Кустова". У тих випадках, коли необхідне висвітлення спортивного форуму в мережі Інтернет, дана послуга оплачується окремо шаховим клубом ГОУ ВПО "Сибгиу". З 10 великих турнірів, що проводяться за рік у приміщенні структурного підрозділу "Шаховий клуб" мінімум 5 висвітлюються в мережі Інтернет.

Витрати на висвітлення змагань у мережі Інтернет представлені в таблиці 12.

Таблиця 12. Витрати на висвітлення змагань у мережі Інтернет

Найменування витрат

Витрати за

1 турнір (руб)

Річний обсяг витрат (руб)

Викладення всієї інформації про змагання в мережі інтернет

2 000

10 000

Додаткові витрати за користування Інтернетом (руб/година)

300

1 500

Разом

11 500

Розроблене спеціалізоване шахове програмне забезпечення вже містить у собі web-сайт, на якому в режимі реального часу ведеться трансляція змагань, що проводяться в приміщенні структурного підрозділу "Шаховий клуб". На даному сайте відображається вся інформація про змагання, зберігаються всі поточні і попередні партії. Таким чином, відпадає необхідність оплати додаткових послуг головного арбітра змагань по викладенню інформації в мережі Інтернет, а також відпадає необхідність у додаткових витратах за користування Інтернетом, тому що трансляція ведеться в режимі реального часу й отсутствует необхідність у додаткових тимчасових витратах.

Е2=11 500 руб.

3.4.3 Прибуток від комерційного використання розробки

В даний час у Сибірському федеральному окрузі проводиться щорічно біля сотні великих шахам форумів. Кожен такий турнір має потребу в інформаційному супроводі і послугах складачів шахових партій. У середньому на інформаційний супровід і набір партій одного великого шахового турніру витрачається від 10000 до 100000 карбованців (у залежності від масштабів змагань), включаючи послуги складачів, висвітлення змагань у мережі Інтернет і засобах масової інформації. Використання розробленого спеціалізованого програмного забезпечення в сполученні з електронними шахівницями DGT дозволить чи цілком частково відмовитися від послуг складачів, автоматизувати процес трансляції змагань у мережі Інтернет і локальні мережі, спростити процес висвітлення спортивних змагань у засобах масової інформації. Таким чином, у сфері проведення спортивних шахових змагань дана розробка буде затребуваною.

Повна оцінка розмірів прибутку від комерційного використання даної розробки дуже проблематична, тому що повинна містити в собі детальні маркетингові дослідження, облік витрат на оформлення авторських прав, рекламу, сервісне обслуговування, хостинг і т.д. Дану оцінку ще тільки має бути зробити, що є одним із пріоритетних напрямків подальшої діяльності. Але вже зараз ясно, що дана розробка буде приносити прибуток, тому що нею зацікавилися фахівці з інформаційного центра російської шахової федерації.

Фактори річної економії при впровадженні системи (без обліку прибутку від комерційного використання розробки) приведені в таблиці 13.

Таблиця 13 - Фактори річної економії при впровадженні системи

Е і

Фактор економії

Сума, руб.

Е 1

Виключення витрат на послуги складачів

40 000

Е 2

Виключення витрат на висвітлення змагань у мережі Інтернет

11 500

Разом:

51 500

Таким чином, річна економія може скласти:

Е=51 500 - 10 430,18 = 41 069,82 руб.

Економічна ефективність одноразових витрат на створення системи визначається показниками Тр і Ер, де Тр - розрахунковий строк окупності одноразових витрат на створення системи в літах, Ер - розрахунковий коефіцієнт ефективності одноразових витрат на створення системи:

Зіставляючи розрахунковий коефіцієнт і строк окупності системи з нормативними, знаходимо, що і . Отже, дана розробка економічно ефективна і доцільна.

3.5 Техніко-економічні показники проекту

Техніко-економічні показники проекту представлені в таблиці 14.

Таблиця 14. Техніко-економічні показники проекту

№ п/п

Найменування показника

Ед. изм.

Значення показника

1

Проектні витрати

Руб.

22 876,85

1.1

Витрати на устаткування

Руб.

7552

1.2

Витрати на придбання матеріалів

Руб.

725

1.3

Витрати на заробітну плату розроблювачам

Руб.

10 404,97

1.4

Витрати на відрахування ЕСН

Руб.

2 705,29

1.5

Витрати на електроенергію

Руб.

132,48

1.6

Накладні витрати

Руб.

1 311,03

2

Експлуатаційні витрати

Руб.

10 430,18

2.1

Витрати на амортизаційні відрахування

Руб.

944

2.2

Витрати на поточний ремонт устаткування і пристроїв системи

Руб.

320

2.3

Витрати на ЕСН

Руб.

1 560

2.4

Витрати на заробітну плату

Руб.

6 000

2.5

Витрати на електроенергію

Руб.

504,58

2.6

Витрати на матеріали

Руб.

1 101,6

3

Річна економія

Руб.

51 500

3.1

Виключення витрат на послуги складачів

Руб.

40 000

3.2

Виключення витрат на висвітлення змагань у мережі Інтернет

Руб.

11 500

4

Економія при впровадженні розробленого проекту

Руб.

41 069,82

5

Строк окупності проекту

Мес.

0,56

4 . Безпека і екологичность проекту

4.1 Безпека праці

4.1.1 Аналіз умов праці на робочому місці інженера структурного підрозділу "Шаховий клуб" ГОУ ВПО "Сибгиу"

Об'єктом аналізу є умови праці на робочому місці інженера структурного підрозділу "Шаховий клуб" ГОУ ВПО "Сибгиу", розташованому за адресою вул. Кірова, 42.

Аналіз умов праці виконаний для робочого кабінету інженера структурного підрозділу "Шаховий клуб" ГОУ ВПО "Сибгиу", що розташовується в прибудові до головного корпуса Сибгиу на третьому поверсі над приміщенням їдальні. Параметри робочого кабінету інженера: площа - 12 м2, периметр - 14 м. У робочому кабінеті інженера розташовується 3 комп'ютери. Приміщення обладнане системою опалення і приточно-витяжной вентиляцією, що відповідає [1].

Для внутрішньої обробки інтер'єра робочого кабінету інженера з ВДТ і ПЕВМ використані матеріали з коефіцієнтом відображення для стелі - 0,7; для стін - 0,5; для підлоги - 0,3, що відповідають [2].

Поверхня підлоги в робочому кабінеті інженера рівна, без вибоїв, неслизька, зручна для очищення і вологого збирання, має антистатичні властивості.

Пил, що осідає на екрані, знижує його освітленість, погіршує видимість зображення і сприяє нагромадженню статичної електрики.

У приміщенні з ПЕВМ щодня проводитися вологе збирання, що відповідає [2].

При роботі з комп'ютером користувач піддається впливу ряду небезпечних і шкідливих виробничих факторів, що по природі дії підрозділяються на наступні групи [3]:

- поразка електричним струмом;

- механічні ушкодження;

- електромагнітне випромінювання;

- інфрачервоне випромінювання;

- небезпека пожежі;

- підвищений рівень шуму і вібрації.

Нормативні документи [1] - [7] передбачають створення на робочому місці умов праці, при яких вплив небезпечних і шкідливих факторів на працюючих або припустимо, або знаходиться в припустимих межах.

Проведемо оцінку умов праці на робочому місці (таблиця 15).

Таблиця 15 - Оцінка умов праці на робочому місці

Фактор

Оцінка умов праці

Фактич. умови

Норматив. значення

Посилання на норматив

Величина соотв./несоотв.

Мікроклімат

Температура, 0 С

холодний період року

теплий період року

20-22

22-25

20-24

21-28

[4]

відповідає

Відносна

вологість повітря,%

50-60

60

відповідає

Швидкість руху повітря, м/с

0,1

0,1-0,2

відповідає

Висвітлення

Природне, %

1,6

> 1,5

[5]

відповідає

Штучне, лк

300

300-500

відповідає

Шумовий вплив

Рівень шуму, дб

60

61

[6]

відповідає

Електромагнітне

Напруженість електричного полючи

[7]

5 Гц-2 кгц

24 В/м

25 В/м

відповідає

2кгц-400 кгц

2.3 У/м

2.5 У/м

відповідає

Щільність магнітного потоку

5 Гц-2 кгц

238 нтл

250 нтл

відповідає

2кгц-400 кгц

22 нтл

25 нтл

відповідає

Робота інженера структурного підрозділу "Шаховий клуб" ГОУ ВПО "Сибгиу" відноситься до категорії 1б, тобто це робота, вироблена сидячи, чи коштуючи зв'язана з ходьбою і супроводжується деякою фізичною напругою, при яких витрата енергії складає від 140 до 232 Дж/з [2].

Аналіз цієї таблиці дозволяє охарактеризувати умови роботи як оптимальні. З метою оптимізації умов праці проектом розроблені заходи щодо безпеки праці.

4.1.2 Заходу щодо безпеки праці

Розроблені проектом заходу відповідають вимогам, пропонованим при роботі за комп'ютером [2].

Таблиця 16 - Фактори впливу на робочому місці і використовувані засоби захисту

Шкідливі фактори

Використовувані засоби захисту

Електромагнітне випромінювання

Дотримання відстані від очей оператора до монітора не менш 70 див

Статична електрика

Заземлення комп'ютерів і електроустаткування, вологе збирання

Перенапруженість зорових аналізаторів

Правильна орієнтація комп'ютера, щоб світло падало ліворуч.

Наявність жалюзі.

Монотония

При 8-ми вартовому робітнику дні робота за комп'ютером не більш 6 годин.

Швидкість набору не більш 120 знаків у хвилину.

4.1.2.1 Організація робочих місць

Висота робочого столу складає 720 мм. Розміри стільниці складають 1400 х 800 мм, що відповідає оптимальному розміру. Під стільницею робочого столу є вільний простір для ніг з розмірами по висоті не менш 600 мм, по ширині не менш 500 мм, по глибині - 650 мм, що відповідає [2].

Конструкція одномісного столу для роботи з ПЕВМ і ВДТ повинна передбачає дві роздільні поверхні: одна - горизонтальна для розміщення ПЕВМ чи ВДТ і друга - для клавіатури. Відсутні шухляди.

Корпус ВДТ і ПЕВМ, клавіатура й інші блоки і пристрої ПЕВМ мають матову поверхню одного кольору, не має блискучих деталей, здатних створювати відблиски. У конструкції ВДТ передбачені кнопки регулювання яскравості і контрасту. Вони забезпечують можливість регулювання цих параметрів від мінімальних до максимальних значень.

Розмір екрана повинний бути не менш 17 дюймів по діагоналі, при цьому відстань від очей до екрана повинне бути в межах 40 - 80 див.

Клавіатура виконана у виді окремого пристрою з можливістю вільного переміщення. Конструкція клавіатури передбачає опорне пристосування, що дозволяє змінювати кут нахилу поверхні клавіатури в межах від 5 до 15 градусів. Висоту середнього ряду клавіш не більш 30 мм.

При захисті від електромагнітних і електростатичних полів допускається застосування приекранних фільтрів, спеціальних екранів і інших засобів індивідуального захисту, що пройшла іспити в акредитованих лабораторіях, і що мають відповідний гігієнічний сертифікат.

Всі описані параметри і характеристики відповідають [2].

4.1.2.2 Освітленість робочого місця

У робочому кабінеті інженера структурного підрозділу "Шаховий клуб" ГОУ ВПО "Сибгиу" передбачене природне і штучне висвітлення. Природне висвітлення відповідно до вимог [5] здійснюється через светопроеми, орієнтовані на північ і північний схід. Освітленість на поверхні столу і клавіатурі повинна бути не менш 300 люкс, а вертикальна освітленість екрана - всего 100-250 люкс.

Як джерела світла при штучному висвітленні застосовуються люмінесцентні лампи типу ЛБ - 40 у кількості 3 штук. Світильники розташовуються локалізовано над робочим столом ближче до його переднього краю, зверненому до оператора.

4.1.2.3 Розрахунок освітленості робочого кабінету інженера структурного підрозділу "Шаховий клуб" ГОУ ВПО "Сибгиу".

Висота - 4 м, довжина - 4 м, ширина - 3 м

Стеля і стіни робочого кабінету інженера структурного підрозділу "Шаховий клуб" ГОУ ВПО "Сибгиу" побілені. Використовуються лампи ЛБ-40.

Розрахуємо кількість світильників, необхідне в робочому кабінеті інженера структурного підрозділу "Шаховий клуб" ГОУ ВПО "Сибгиу", по методу коефіцієнта використання світлового потоку [5].

Ен = 300 лк

S = 4* 3 = 12

Z = 1.1

k = 1.3

F = 3000 лм

n = 2

I = (4*3)/(2.78*(4+3))= 0,62

h = 4 - 0.5 - 0.72 = 2.78 м

hc = 0.5 м (висота світильника)

hр = 0.72 м (висота робочого столу)

η = 0,29

(шт)

Для висвітлення робочого кабінету інженера структурного підрозділу "Шаховий клуб" ГОУ ВПО "Сибгиу" розмірами 4м х 3м х 4 м буде потрібно 3 світильники з люмінесцентними лампами типу ЛБ - 40. У робочому кабінеті інженера встановлено 3 світильники, що відповідає [5].

4.2 Надзвичайні ситуації

4.2.1 Електробезпечність

При користуванні засобами обчислювальної техніки і периферійним устаткуванням кожен користувач повинний уважно й обережно звертатися з електропроводкою, приладами й апаратами і завжди пам'ятати, що зневага правилами безпеки загрожує і здоров'ю, і життя людини.

Щоб уникнути поразки електричним струмом необхідно твердо знати і виконувати наступні правила безпечного користування електроенергією.

Необхідно постійно стежити на своєму робочому місці за справним станом електропроводки, вимикачів, штепсельних розеток, за допомогою яких устаткування включається в мережу, і заземлення. При виявленні несправності негайно знеструмити електроустаткування, сповістити адміністрацію. Продовження роботи можливо тільки після усунення несправності.

Щоб уникнути ушкодження ізоляції проводів і виникнення коротких замикань не дозволяється:

- вішати що-небудь на проводи;

- зафарбовувати і білити шнури і проводи;

- закладати проводи і шнури за газові і водопровідні труби, за батареї опалювальної системи;

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

Для виключення поразки електричним струмом забороняється:

- часто включати і виключати комп'ютер без необхідності;

- доторкатися до екрана і до тильної сторони блоків комп'ютера;

- працювати на засобах обчислювальної техніки і периферійному устаткуванні мокрими руками;

- працювати на засобах обчислювальної техніки і периферійному устаткуванні, що має порушення цілісності корпуса, порушення ізоляції проводів, несправну індикацію включення харчування, з ознаками електричної напруги на корпусі;

- класти на засоби обчислювальної техніки і периферійне устаткування сторонні предмети.

Забороняється очищати від пилу і забруднення електроустаткування, що знаходиться під напругою.

Забороняється перевіряти працездатність електроустаткування в непристосованих для експлуатації приміщеннях зі струмопровідними, сирими підлогами, що не дозволяють заземлити доступні металеві частини.

Ремонт електроапаратури виробляється тільки фахівцями-техніками з дотриманням необхідних технічних вимог.

Неприпустимо під напругою проводити ремонт засобів обчислювальної техніки і периферійного устаткування.

Щоб уникнути поразки електричним струмом, при користуванні електроприладами не можна стосуватися одночасно яких-небудь трубопроводів, батарей опалення, металевих конструкцій , з'єднаних із землею.

При користуванні електроенергією в сирих приміщеннях дотримувати особливої обережності.

При виявленні проводу, що обірвався, необхідно негайно повідомити про це адміністрації, ужити заходів по виключенню контакту з ним людей. Дотик до проводу небезпечно для життя.

Порятунок потерпілого при поразці електричним струмом головним чином залежить від швидкості звільнення його від дії струмом.

В усіх випадках поразки людини електричним струмом негайно викликають лікаря. До прибуття лікаря потрібно, не втрачаючи часу, приступити до надання першої допомоги потерпіл.

Необхідно негайно почати робити штучне дихання, найбільш ефективним з який є метод "рот у рот", а також зовнішній масаж серця.

Штучне дихання ураженому електричним струмом виробляється аж до прибуття лікаря.

4.2.2 Пожежна безпека

Відповідно до [8] кабінети з ВДТ по пожежній небезпеці відносяться до категорії "У", тому що в приміщенні знаходяться електронна апаратура, офісна техніка і папір.

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

- перевантаження електричних мереж;

- несправність електропроводки, електроустаткування і недотепне їхнє використання;

- самозаймистість деяких речовин;

- недотримання правил техніки безпеки;

- паління і застосування відкритого вогню в неналежному місці;

- коротке замикання в електроустаткуванні;

- диверсійно-терористичні акції.

Порядок і послідовність дій:

- повідомлення про пожежу;

- евакуація студентів з палаючих приміщень;

- звірення облікового складу з фактичною наявністю евакуйованих;

- гасіння виниклого пожежі.

Необхідно знати, що:

- при виявленні пожежі, чи загорянні задимленні негайно телефонувати 01;

- при виникненні пожежі евакуація виробляється через запасні виходи корпуса, їдальні і будинку головного корпуса "Сибгиу";

- при виникненні пожежі в частині будинку, що має вихід на вулицю, евакуацію робити через запасні виходи їдальні, головного корпуса і потокових аудиторій;

- всі евакуйовані перераховуються і звіряються за списком;

- гасіння загоряння виробляється негайно з моменту його виявлення.

Виконавці:

- перший дим, що помітив, і черговий по корпусі;

- черговий приміщень і викладачі, що проводили заняття;

- викладачі і старости груп;

- члени ДПД.

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

Протипожежна служба складається зі штатних працівників відділу забезпечення порядку, що самотужки здатні гасити пожежу будь-якого ступеня складності. Чисельність працівників відділу забезпечення порядку 30 чоловік. Головне у їхній роботі - запобігтиЖ пожеж. Якщо загоряння відбулося, то основна задача - зупинити його, не дати перерости в пожежу. Основною причиною загоряння в будинку університету є незагашена сигарета. Ушкодження електропроводки також може привести до загоряння, а потім і до пожежі.

До засобів пожежегасіння відносяться засоби колективного й індивідуального захисту.

Засобу колективного захисту:

- вогнегасники порошкові ОП-3;

- гідранти;

- пожежні рукави.

Засобу індивідуального захисту:

- протигази ГП5;

- респіратори.

Усі види засобів захисту в достатній кількості маються на посадах служби забезпечення порядку.

У головному корпусі Сибгиу розташовується пожежна посада №1, де знаходяться первинні засоби пожежегасіння (на початковій стадії розвитку пожежі): вогнегасники, пісок, повсть, повстина, азбестова полотнина, цебра, лопати й ін. Там же знаходиться і форма.

Джерела водопостачання:

- пожежні гідранти;

- пожежні крани - 58 шт.

Пожежні крани розміщені в шафках, на дверцята яких нанесений буквений індекс "ПК" і порядковий номер крана. Кожен пожежний кран обладнаний рукавом довжиною 20 м і пожежним стовбуром зі сприском. Пожежні рукави бувають усмоктувальні і напірні. За допомогою усмоктувальних рукавів забирають воду з водоисточников пожежним насосом. Напірні рукави застосовують для подачі води до місця пожежі від водоисточника чи водопровідного крана.

Пожежна сигналізація в головному корпусі знаходиться тільки в комп'ютерних класах, у виді:

- димових датчиків;

- термічних датчиків.

Основним заходом щодо захисту людей при пожежі є повна екстрена евакуація. Плани евакуації висять на всіх поверхах у всіх корпусах університету.

4.2.3 Організаційно-штатна структура по ГО і ЧС.

У керівний склад входять начальник ГОЧС (Кулагин Микола Михайлович), начальник штабу ГОЧС (Герасимова Ганна Олексіївна), голова евакуаційної комісії (Галевский Геннадій Владиславович) і начальник СЕП (Рябцев Вадим Олегович).

Сили ГОЧС складають рятувальна команда (105 чоловік), групи оповіщення і зв'язку (30 чоловік), команда охорони суспільного порядку (45 чоловік), санітарні дружини (72 чоловік) і ланки пожежегасіння (20 чоловік).

4.2.4 Надзвичайні ситуації, що можуть виникнути на території ГОУ ВПО "Сибгиу".

Надзвичайні ситуації, що можуть виникнути на території ГОУ ВПО "Сибгиу", зв'язані з небезпекою для здоров'я, загибеллю і каліцтвом студентів і персоналу:

- пожаро-взривоопасная ситуація;

- витік хлору в плавальному басейні спорткомплексу університету;

- виробничі аварії на Лівобережному водозаборі, на його технологічних лініях і емкостях із хлором, при несприятливих метеоусловиях і напрямку вітру від місця аварії убік університету;

- аварії на залізниці, що пролягає в безпосередній близькості до ГОУ ВПО "Сибгиу" з розливом АХОВ чи вибухом особливо небезпечного вантажу;

- неблагополучна обстановка в місті, у центральному районі, зв'язана з виникненням вогнищ особливо небезпечних інфекційних захворювань;

- ураганний вітер, землетруси, повені й інші стихійні лиха.

4.2.5 Способи оповіщення при ЧС

Звучання сирен, переривчасті гудки підприємств і транспортних засобів означає подачу попереджувального сигналу "Увага всім!".

Почувши його, варто негайно включити гучномовець, радіо і телеприймач (у будь-який час доби), прослухайте екстрене повідомлення керування по справах ГО і ЧС.

Після сигналу "Увага всім!" може піти й інша інформація, наприклад, про погрозу виникнення ЧС, про небезпеку радіоактивного чи, що насувається, хімічного зараження, виникнення "Повітряної небезпеки". У цих випадках буде передане коротке повідомлення про порядок дій і правила поводження при даної ЧС.

У робочий час можна одержати інформацію про передачу сигналу "Увага всім!" від керівників університету (ГО і ЧС). Діяти необхідно відповідно до їхніх указівок.

Слід дотримуватися спокою і порядок. Необхідно бути уважним до повідомлень працівників цивільної оборони.

4.2.6 Дії по видах повідомлення при передачі сигналу "Увага всім! "

При аварії з викидом АХОВ і несприятливих метеоусловиях необхідно:

- провести герметизацію приміщень;

- відключити вентиляційні пристрої, електронагрівальні прилади, перекрити воду, газ;

- підготувати і перевірити засобу індивідуального захисту органів подиху і шкіри, при їхній відсутності виготовити найпростіші засоби індивідуального захисту;

- узяти із собою документи, гроші, продукти;

- залишити своє місцезнаходження і вийти по найкоротшому шляху в напрямку, зазначеному ГОЧС.

Усі повинні вийти в безпечне місце в кротчайшее час до підходу зараженого хлором повітряної хмари.

Якщо при аварії на кожнім з хімічно небезпечних об'єктів чи району на залізниці і напрямку вітру убік чи об'єкта житлових будинків отримана інформація про небезпеку влучення, що грозить, у зону зараження АХОВ, то необхідно негайно залишити приміщення університету, вийти з вогнища зараження і рухатися в напрямку перпендикулярному руху вітру.

Час виходу з вогнища зараження дуже обмежене і не повинно перевищувати 15-20 хвилин з моменту аварії, відстань виходу близько 200 - 300 метрів. Вихід здійснювати, дихаючи через змочену у воді матер'яну пов'язку.

При виникненні "Повітряної небезпеки" (при воєнному стані) необхідно:

- відключити світло, газ, воду;

- узяти засобу індивідуального захисту, документи, запас харчування і води;

- допомогти хвор вийти на вулицю;

- якнайшвидше дійти до захисного чи спорудження укритися в складках місцевості.

При відбої дії по сигналах ГО за вказівкою ГОЧС чи представника охорони суспільного порядку вийти з укриттів і повернутися до місця роботи. Знімати засобу індивідуального захисту - за особливим наказом. Надалі діяти за вказівкою керування ГОЧС чи старшого на робочому місці.

При інших ЧС діяти стосовно до случившейся ЧС.

4.2.7 Організація захисту співробітників і студентів Сибгиу при виникненні ЧС мирного і воєнного часу

Інженерний захист: студенти і персонал університету вкриваються в захисних спорудженнях - підвальних приміщеннях корпусів, спорткомплексі, їдальні.

Забезпечення засобами індивідуального захисту:

- в екстрених випадках (при аваріях з АХОВ) виготовляються найпростіші засоби захисту органів подиху (матер'яні пов'язки) з підручного матеріалу, можуть бути використані промислові чи респіратори ватно-марлеві пов'язки, що маються на робочому місці;

- при надходженні розпорядження керування ГО і ЧС на одержання засобів індивідуального захисту (СИЗИЙ) із запасів об'єкта (чи централізованого) у приміщеннях головного корпуса, блоку потокових аудиторій, гірничо-технологічного корпуса розвертаються "Пункти видачі СИЗІ".

Видача СИЗА здійснюється по черзі для всіх структурних підрозділів за графіком, складеному штабом ГОЧС університету.

Організація евакуації університету:

- у мирний час (екстрена евакуація):

o при аваріях на підприємствах міста (району) чи ж/д з викидом АХОВ - у місця, зазначені при одержанні сигналу "Увага всім!" у напрямку, перпендикулярному руху зараженої хмари (з урахуванням особливостей АХОВ);

o при підвищенні радіаційного тла понад 60 мкр/година - за розпорядженням керування ГОЧС чи району керівника об'єктів у місця, визначені адміністрацією області;

- у воєнний час (планова евакуація):

o з одержанням розпорядження керування ГОЧС евакуацію здійснює евакуаційна комісія університету. Евакуація працівників і студентів Сибгиу і членів їхніх родин здійснюється по залізниці в населений пункт м. Гур'євськ Кемеровської області в тому числі: залізничним транспортом, через СЕП №20, що розвертається в приміщенні блоку потокових аудиторій;

o у заміських зонах розміщення відбувається в приміщеннях 3-х автогосподарств і житлових будинків (подселением) відповідно до плану керування ГОЧС.

4.3 Екологичность проекти

З погляду енергопостачання монітори, використовувані в робочому процесі, мають убудовану систему економії електроенергії - PowerSaver. Ця система зберігає електроенергію за допомогою переключення монітора в режим з низьким споживанням енергії, коли він не використовується протягом визначеного періоду часу.

Можливі режими роботи - робітник, Stand-by, Suspend, виключений. Дана система успішно працює з VESADPMS - сумісною відеокартою, встановленої в комп'ютері. Більш детальна інформація зведена в таблиці 3.

Таблиця 17 - Характеристики режимів збереження електроенергії [10].

Стан

Робоче

Режим збереження електроенергії EPA/NUTEK

Режим Stand-by

Режим Suspend

Режим Power-off

Горизонтальна синхр.

Активний

Неактивний

Активний

Неактивний

Вертикальна синхр.

Активний

Активний

Неактивний

Неактивний

Відео

Активний

Темний екран

Темний екран

Темний екран

Споживана потужність

73 Ут (макс)

55 Ут (номин)

50 Ут (номин)

Менш 15 Ут

Менш 5 Ут

Монітор автоматично повертається до режиму нормального функціонування при відновленні горизонтального і вертикального розгорнення.

Висновок

У результаті виконання дипломного проекту головна задача, поставлена в розділі "Постановка задачі" - реалізувати спеціалізоване шахове програмне забезпечення, що відповідає всім критеріям і обмеженням - була виконана цілком.

Для рішення поставленої задачі були використані методології розробки програмного забезпечення, детально розглянуті в дипломному проекті, а також стандартні засобу програмних продуктів, представлених у дійсній роботі. У зв'язку з неможливістю використання прототипів спеціалізованого шахового програмного забезпечення в ході розробки були застосовані прийоми екстремальної методології розробки ПО.

За даними аналізу результатів тестових іспитів, представлених у додатку 8, була виявлена повна відповідність реалізованого спеціалізованого шахового програмного забезпечення всім критеріям і обмеженням.

Список використаних джерел

1. Санітарні норми і правила: Снип 41.01-03. Опалення, вентиляція і кондиціонування. - Уведений 01.01 2004. Технорматив: інформаційна система. - 58 с.

2. Санітарні правила і норми: Санпин 2.2.2/2.4.1340-03. Гігієнічні вимоги до персональних електронно-обчислювальних машин і організація роботи. - Уведений 30.06.2003. Технорматив: інформаційна система - 26 с.

3. Система стандартів безпеки праці: ДСТ 12.0.003-74. Небезпечні і шкідливі фактори. - Уведений 18.11.1974. М.: - Держстандарт СРСР, 1974р., - 55с.

4. Система стандартів безпеки праці: ДСТ 12.005-88. Загальні санітарно-гігієнічні вимоги до повітря робочої зони. - Уведений 29.09.1988. М.: - Державний комітет СРСР по стандартах, 1988р. - 28з

5. Санітарні правила і норми: Санпин 2.2.1/2.2.2.1278-03. Гігієнічні вимоги до природного, штучного і сполученого висвітлення житлових і суспільних будинків. - Уведений 15.06.2003. Технорматив: інформаційна система. - 27 с.

6. Санітарні норми: СН 2.2.4/2.1.8.562-96. Шум на робочих місцях, у приміщеннях житлових, суспільних будинків і на території житлової забудови. - Уведений 31.10.1996. М.: - Держкомсанепіднадзора Росії , 1996р. - 34с.

7. Санітарні правила і норми: Санпин 2.2.4.1191-03 Електромагнітні полючи у виробничих умовах - Уведений 01.05.2003. Спб.: Мінздрав РФ, 2003р. - 17 с.

8. Норми пожежної безпеки: НПБ 105-2003. Визначення категорій приміщень, будинків і зовнішніх установок по взривопожарной і пожежної небезпеки. - Уведений 18.06.2003. М.: МЧС РФ, 2003р. - 26с.

9. Санітарні норми і правила: Снип 21.01-97. Пожежна безпека будинків і споруджень. - Уведений 01.01.1998. Технорматив: інформаційна система. - 23 с.

10. Система стандартів безпеки праці: ДСТ Р50949-96. Засобу відображення інформації індивідуального користування. Методи вимірів і оцінки ергономических параметрів і параметрів безпеки. - Уведений 01.07.1997. М: Держстандарт Росії, 1996 - 27 с.

11. Фултон Х. Програмування мовою Ruby. Идеалогия мови, теорія і практика приминения. / Х. Фултон - М.: Дмк-пресс, 2007. - 688 с.

12. Томас Д. Гнучка розробка веб-приложений у середовищі Rails. / Томас Д., Хенссон Д. Х. - Спб.: Питер, 2008. - 716 с.

13. Ченців В. В. Мова програмування Java і середовище NetBeans. / Ченців В. В. - Спб.: Бхв-петербург, 2008. - 640 с.

14. Шильдт Х. Java. Методики програмування Шилдта. / Шильдт Х. - М.: Вільямс, 2008. - 512 с.

15. Гудман Д. JavaScript. Біблія користувача. Видання 5-і. / Гудман Д., Моррисон М. - М.: Вільямс, 2006. - 1184 с.

16. Фленаган Д. JavaScript. Докладне руководтство. Видання 4-і. / Фленаган Д. - М.: Символ-плюс, 2004. - 960 с.

17. Муссиано Ч. HTML і XHTML. Докладне керівництво. Видання 6-і. / Муссиано Ч., Кеннеді Б. - М.: Символ-плюс, 2008. - 752 с.

18. Лазаро И. К. Повний довідник по HTML, CSS і JavaScript. Довідник професіонала. / Лазаро И. К. - М.: Третій Рим, 2007. - 1168 с.

19. Бобко Т. В. Методичні вказівки до виконання економічної частини дипломних проектів. / Бобко Т. В. - Новокузнецьк: Сибгиу, 2007. - 47 с.

20. Бек К. Екстремальне програмування. / Бек К. - Спб.: Питер, 2002. -224с.

21. Избачков Ю. С. Інформаційні системи: Підручник для вузів. 2-і видання. / Избачков Ю. С., Петров В. Н. - Спб.: Питер, 2005. - 656 с.

Додаток А

Календарний план робіт зі створення системи

Найменування етапу

Терміни виконання

Виконавець

1

Розробка ТЗ на ИС "Шаховий клуб" по пунктах 1,2

01.08.2007 -

01.09.2007

Ширяев А. С.

2

Розробка ТЗ на ИС "Шаховий клуб" по пунктах 3-5

01.09.2007 -

01.11.2007

Ширяев А. С.

3

Розробка ТЗ на ИС "Шаховий клуб" по пунктах 6-9

01.11.2007 -

01.12.2007

Ширяев А. С.

4

Закупівля устаткування, створення системи, розробка необхідної документації на систему

01.12.2007 -

01.02.2008

Персонал шахового клуба ГОУ ВПО "Сибгиу", персонал МУДОД "СДЮСШОР по шахам ім. Б. А. Кустова"

5

Попередні іспити системи

02.02.2008 -

03.02.2008

Персонал шахового клуба ГОУ ВПО "Сибгиу", персонал МУДОД "СДЮСШОР по шахам ім. Б. А. Кустова",

Ширяев А. С.

6

Досвідчена експлуатація

03.02.2008 -

03.03.2008

Персонал шахового клуба ГОУ ВПО "Сибгиу", персонал МУДОД "СДЮСШОР по шахам ім. Б. А. Кустова"

Додаток Б

Комплектність документації на систему

Найменування документації

Документація по загальносистемних рішеннях:

Схема функціональної структури

Опис автоматизируемих функцій і функцій по представленню інформації

Загальний опис системи

Документація по організаційному забезпеченню:

Опис організаційної структури

Організаційно-технічна інструкція

Документація по технічному забезпеченню:

Опис комплексу технічних засобів

Структурна схема комплексу технічних засобів

Документація на технічні засоби

Документація по інформаційному забезпеченню:

Перелік вхідних сигналів і даних

Перелік вихідних сигналів і даних

Опис інформаційного забезпечення системи

Опис організації інформаційної бази

Документація по програмному забезпеченню:

Опис програмного забезпечення

Документація на програмне забезпечення

Додаток У

Листинг програми-транслятора шахових партій

Контролери (controller)

main_controller.rb

- -

# Основний контролер порталу

class MainController < ApplicationController

# Редиректнаглавнуюстраницу

def index

render :action = > 'logo'

end

# Головна сторінка

def logo

end

# Стара сторінка

def main

render :action = > 'logo'

end

# Показ партій в онлайн режимі (трансляції)

def online

@online_games = CurrentGame.find :all

end

# Показ партій в оффлайн режимі (уже закінчилися)

def offline

end

# Нагадування при втраті чи пароля логина

def remind

end

# Вхід в особистий кабінет користувача

def enter

unless session[:user_id].nil?

redirect_to "/users/room/#{session[:user_id]}"

end

end

# Показтрансляции

def game

unless params[:id].nil?

@game = Game.find params[:id]

else

render :action = > 'logo'

end

end

# Повертає текст партії в домовленому форматі

def game_moves

@game = Game.find(params[:id])

render_text @game.moves

end

# Авторизація

def login

session[:user_id] = nil

user = User.authenticate(params[:login], params[:password])

if user.nil?

redirect_to :action = > 'enter'

else

session[:user_id] = user.id

redirect_to "/users/room/#{user.id}"

end

end

# Вихід користувача

defunlogin

session[:user_id] = nil

redirect_to :action = > 'logo'

end

# Перехід до реєстрації

defregister

redirect_to '/users/new'

end

end

cities_controller.rb

- -

class CitiesController < ApplicationController

layout 'main'

scaffold :cities

end

clock_reglaments_controller.rb

- -

class ClockReglamentsController < ApplicationController

layout 'main'

scaffold :clock_reglament

end

countries_controller.rb

- -

class CountriesController < ApplicationController

layout 'main'

scaffold :countries

end

game_infos_controller.rb

- -

class GameInfosController < ApplicationController

layout 'main'

scaffold :game_info

end

games_controller.rb

- -

class GamesController < ApplicationController

layout 'main'

scaffold :game

end

moves_controller.rb

- -

class MovesController < ApplicationController

layout 'main'

scaffold :move

end

players_controller.rb

- -

class PlayersController < ApplicationController

layout 'main'

scaffold :player

end

tournament_views_controller.rb

- -

class TournamentViewsController < ApplicationController

layout 'main'

scaffold :tournament_view

end

tournaments_controller.rb

- -

class TournamentsController < ApplicationController

layout 'main'

scaffold :tournament

def index

render :action = > 'list'

end

end

users_controller.rb

- -

class UsersController < ApplicationController

layout 'main'

scaffold :users

def index

render :action = > 'room'

end

def room

end

end

Помічники (helper)

main_helper.rb

- -

module MainHelper

def print_current_tournament

html = ""

Tournament.find_all_by_status('open').each do |tournament|

city = tournament.city_id.nil? ? nil : City.find(tournament.city_id)

html < < " < tr > "

html < < " < td > < /td > "

html < < " < td > " + tournament.name + " < /td > "

html < < " < td > " + (city.nil? ? "" : city.name) + " < /td > "

html < < " < /tr > "

end

html

end

def render_game_info

"Тестова партія з тестового турніру"

end

def render_moves

moves = " < div id=\"moves\" > < /div > "

moves = " < table width='100%' align='center' > "

moves += " < tr > < th width='2%' > < /th > < th width='45%' > < /th > < th > < /th > < th width='45%' > < /th > < th width='2%' > < /th > < /tr > "

moves += " < tr > < td > 1. < /td > < td > b < /td > < td > c < /td > < td > d < /td > < td > e < /td > < /tr > "

moves += " < tr > < td > 2. < /td > < td > b < /td > < td > c < /td > < td > d < /td > < td > e < /td > < /tr > "

moves += " < tr > < td > 3. < /td > < td > b < /td > < td > c < /td > < td > d < /td > < td > e < /td > < /tr > "

moves += " < tr > < td > 4. < /td > < td > b < /td > < td > c < /td > < td > d < /td > < td > e < /td > < /tr > "

moves += " < tr > < td > 5. < /td > < td > b < /td > < td > c < /td > < td > d < /td > < td > e < /td > < /tr > "

moves += " < tr > < td > 6. < /td > < td > b < /td > < td > c < /td > < td > d < /td > < td > e < /td > < /tr > "

moves += " < tr > < td > 7. < /td > < td > b < /td > < td > c < /td > < td > d < /td > < td > e < /td > < /tr > "

moves += " < tr > < td > 8. < /td > < td > b < /td > < td > c < /td > < td > d < /td > < td > e < /td > < /tr > "

moves += " < tr > < td > 9. < /td > < td > b < /td > < td > c < /td > < td > d < /td > < td > e < /td > < /tr > "

moves += " < tr > < td > 10. < /td > < td > b < /td > < td > c < /td > < td > d < /td > < td > e < /td > < /tr > "

moves += " < tr > < td > 11. < /td > < td > b < /td > < td > c < /td > < td > d < /td > < td > e < /td > < /tr > "

moves += " < tr > < td > 12. < /td > < td > b < /td > < td > c < /td > < td > d < /td > < td > e < /td > < /tr > "

moves += " < tr > < td > 13. < /td > < td > b < /td > < td > c < /td > < td > d < /td > < td > e < /td > < /tr > "

moves += " < tr > < td > 14. < /td > < td > b < /td > < td > c < /td > < td > d < /td > < td > e < /td > < /tr > "

moves += " < tr > < td > 15. < /td > < td > b < /td > < td > c < /td > < td > d < /td > < td > e < /td > < /tr > "

moves += " < tr > < td > 16. < /td > < td > b < /td > < td > c < /td > < td > d < /td > < td > e < /td > < /tr > "

moves += " < tr > < td > 17. < /td > < td > b < /td > < td > c < /td > < td > d < /td > < td > e < /td > < /tr > "

moves += " < tr > < td > 18. < /td > < td > b < /td > < td > c < /td > < td > d < /td > < td > e < /td > < /tr > "

moves += " < tr > < td > 19. < /td > < td > b < /td > < td > c < /td > < td > d < /td > < td > e < /td > < /tr > "

moves += " < tr > < td > 20. < /td > < td > b < /td > < td > c < /td > < td > d < /td > < td > e < /td > < /tr > "

moves += " < tr > < td colspan='5' align='center' > "

moves += image_tag('go_begin.jpg', :id = > 'go_begin', :onclick = > 'goBegin();'), :onmouseover = > 'new Effect.Scale("go_begin", 110)'), :onmouseout = > 'new Effect.Scale("go_begin", 90)') + ' '

moves += image_tag('go_prev.jpg', :id = > 'go_prev', :onclick = > 'goPrev();') :onmouseover = > 'new Effect.Scale("go_prev", 110)', :onmouseout = > 'new Effect.Scale("go_prev", 90)') + ' '

moves += image_tag('go_refresh.jpg', :id = > 'go_refresh', :onclick = > 'goRefresh();') :onmouseover = > 'new Effect.Scale("go_refresh", 110)', :onmouseout = > 'new Effect.Scale("go_refresh", 90)') + ' '

moves += image_tag('go_next.jpg', :id = > 'go_next', :onclick = > 'goNext();'):onmouseover = > 'new Effect.Scale("go_next", 110)', :onmouseout = > 'new Effect.Scale("go_next", 90)') + ' '

moves += image_tag('go_end.jpg', :id = > 'go_end', :onclick = > 'goEnd();')#:onmouseover = > 'new Effect.Scale("go_end", 110)', :onmouseout = > 'new Effect.Scale("go_end", 90)') + ' '

moves += " < /td > < /tr > "

moves += " < /table > ";

moves

end

def render_board

return " < table class=\"board\" id=\"board\" >

< tr >

< td class=\"board_label_digit\" > 8 < /td >

< td class=\"board_white_field\" id=\"fieldA8\" > < /td >

< td class=\"board_black_field\" id=\"fieldB8\" > < /td >

< td class=\"board_white_field\" id=\"fieldC8\" > < /td >

< td class=\"board_black_field\" id=\"fieldD8\" > < /td >

< td class=\"board_white_field\" id=\"fieldE8\" > < /td >

< td class=\"board_black_field\" id=\"fieldF8\" > < /td >

< td class=\"board_white_field\" id=\"fieldG8\" > < /td >

< td class=\"board_black_field\" id=\"fieldH8\" > < /td >

< /tr >

< tr >

< td class=\"board_label_digit\" > 7 < /td >

< td class=\"board_black_field\" id=\"fieldA7\" > < /td >

< td class=\"board_white_field\" id=\"fieldB7\" > < /td >

< td class=\"board_black_field\" id=\"fieldC7\" > < /td >

< td class=\"board_white_field\" id=\"fieldD7\" > < /td >

< td class=\"board_black_field\" id=\"fieldE7\" > < /td >

< td class=\"board_white_field\" id=\"fieldF7\" > < /td >

< td class=\"board_black_field\" id=\"fieldG7\" > < /td >

< td class=\"board_white_field\" id=\"fieldH7\" > < /td >

< /tr >

< tr >

< td class=\"board_label_digit\" > 6 < /td >

< td class=\"board_white_field\" id=\"fieldA6\" > < /td >

< td class=\"board_black_field\" id=\"fieldB6\" > < /td >

< td class=\"board_white_field\" id=\"fieldC6\" > < /td >

< td class=\"board_black_field\" id=\"fieldD6\" > < /td >

< td class=\"board_white_field\" id=\"fieldE6\" > < /td >

< td class=\"board_black_field\" id=\"fieldF6\" > < /td >

< td class=\"board_white_field\" id=\"fieldG6\" > < /td >

< td class=\"board_black_field\" id=\"fieldH6\" > < /td >

< /tr >

< tr >

< td class=\"board_label_digit\" > 5 < /td >

< td nowrap class=\"board_black_field\" id=\"fieldA5\" > < /td >

< td nowrap class=\"board_white_field\" id=\"fieldB5\" > < /td >

< td nowrap class=\"board_black_field\" id=\"fieldC5\" > < /td >

< td nowrap class=\"board_white_field\" id=\"fieldD5\" > < /td >

< td nowrap class=\"board_black_field\" id=\"fieldE5\" > < /td >

< td nowrap class=\"board_white_field\" id=\"fieldF5\" > < /td >

< td nowrap class=\"board_black_field\" id=\"fieldG5\" > < /td >

< td nowrap class=\"board_white_field\" id=\"fieldH5\" > < /td >

< /tr >

< tr >

< td class=\"board_label_digit\" > 4 < /td >

< td class=\"board_white_field\" id=\"fieldA4\" > < /td >

< td class=\"board_black_field\" id=\"fieldB4\" > < /td >

< td class=\"board_white_field\" id=\"fieldC4\" > < /td >

< td class=\"board_black_field\" id=\"fieldD4\" > < /td >

< td class=\"board_white_field\" id=\"fieldE4\" > < /td >

< td class=\"board_black_field\" id=\"fieldF4\" > < /td >

< td class=\"board_white_field\" id=\"fieldG4\" > < /td >

< td class=\"board_black_field\" id=\"fieldH4\" > < /td >

< /tr >

< tr >

< td class=\"board_label_digit\" > 3 < /td >

< td class=\"board_black_field\" id=\"fieldA3\" > < /td >

< td class=\"board_white_field\" id=\"fieldB3\" > < /td >

< td class=\"board_black_field\" id=\"fieldC3\" > < /td >

< td class=\"board_white_field\" id=\"fieldD3\" > < /td >

< td class=\"board_black_field\" id=\"fieldE3\" > < /td >

< td class=\"board_white_field\" id=\"fieldF3\" > < /td >

< td class=\"board_black_field\" id=\"fieldG3\" > < /td >

< td class=\"board_white_field\" id=\"fieldH3\" > < /td >

< /tr >

< tr >

< td class=\"board_label_digit\" > 2 < /td >

< td class=\"board_white_field\" id=\"fieldA2\" > < /td >

< td class=\"board_black_field\" id=\"fieldB2\" > < /td >

< td class=\"board_white_field\" id=\"fieldC2\" > < /td >

< td class=\"board_black_field\" id=\"fieldD2\" > < /td >

< td class=\"board_white_field\" id=\"fieldE2\" > < /td >

< td class=\"board_black_field\" id=\"fieldF2\" > < /td >

< td class=\"board_white_field\" id=\"fieldG2\" > < /td >

< td class=\"board_black_field\" id=\"fieldH2\" > < /td >

< /tr >

< tr >

< td class=\"board_label_digit\" > 1 < /td >

< td class=\"board_black_field\" id=\"fieldA1\" > < /td >

< td class=\"board_white_field\" id=\"fieldB1\" > < /td >

< td class=\"board_black_field\" id=\"fieldC1\" > < /td >

< td class=\"board_white_field\" id=\"fieldD1\" > < /td >

< td class=\"board_black_field\" id=\"fieldE1\" > < /td >

< td class=\"board_white_field\" id=\"fieldF1\" > < /td >

< td class=\"board_black_field\" id=\"fieldG1\" > < /td >

< td class=\"board_white_field\" id=\"fieldH1\" > < /td >

< /tr >

< tr >

< td class=\"board_lebel_letter\" >   < /td >

< td class=\"board_lebel_letter\" > A < /td >

< td class=\"board_lebel_letter\" > B < /td >

< td class=\"board_lebel_letter\" > C < /td >

< td class=\"board_lebel_letter\" > D < /td >

< td class=\"board_lebel_letter\" > E < /td >

< td class=\"board_lebel_letter\" > F < /td >

< td class=\"board_lebel_letter\" > G < /td >

< td class=\"board_lebel_letter\" > H < /td >

< /tr >

< /table > "

end

def render_result

"1/2 - 1/2"

end

def render_black_time

"-:-:-"

end

def render_white_time

"-:-:-"

end

end

Представлення (view)

layout/main.rhtml

- -

< !DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"

"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd" >

< html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en" >

< head >

< meta http-equiv="content-type" content="text/html;charset=UTF-8" / >

< title > Стартова сторінка: < %= controller.action_name % > < /title >

< %= stylesheet_link_tag 'scaffold' % >

< %= stylesheet_link_tag 'main' % >

< %= stylesheet_link_tag 'game' % >

< %= javascript_include_tag :defaults % >

< %= javascript_include_tag 'game' % >

< /head >

< body >

< table bgcolor="#f4f4f4" border="0" width="80%" align="center" cellpadding="0" cellspacing="0" >

< tr >

< td width='3%' > < /td >

< td >

< h1 > < %= link_to(image_tag('dgt.gif', :size = > '42x25', :border = > 0, :alt = > 'http://dgtprojects.com'), 'http://dgtprojects.com') % >    

Сервер трансляції шахових партій < %= link_to 'rDGT', 'http://rdgt.org' % >    

< %= link_to(image_tag('home.gif', :size = > '12x12', :border = > 0), '/main/index') % >

< %= link_to(image_tag('email.gif', :size = > '12x12', :border = > 0), '') % >

< %= link_to(image_tag('search.gif', :size = > '12x12', :border = > 0), '')% >

< /h1 > < hr / >

< /td >

< td width='3%' > < /td >

< /tr >

< tr >

< td > < /td >

< td >

< p style="color: green" > < %= flash[:notice] % > < /p >

< %= yield % >

< /td >

< td > < /td >

< /tr >

< tr >

< td > < /td >

< td align="right" > < br / > < hr / >

< %= mail_to 'zarstudio@gmail.com', '[ Розроблювачі ]' % > < br / >  

< /td >

< td > < /td >

< /tr >

< /table >

< /body >

< /html >

main/enter.rhtml

- -

< % form_tag '/main/login' do % >

< table align='center' width='100%' >

< tr >

< td width='41%' align="right" > < strong > Ім'я:  < strong > < /td >

< td align="left" > < %= text_field_tag :login, params[:login] % > < /td >

< /tr >

< tr >

< td align="right" > < strong > Пароль:  < /strong > < /td >

< td align="left" > < %= password_field_tag :password, params[:password] % > < /td >

< /tr >

< tr >

< td align="center" colspan="2" > < %= submit_tag 'Увійти' % > < /td >

< /tr >

< tr >

< td align="center" colspan="2" > < %= link_to '[ Реєстрація ]', { :action = > 'register' }% > < /td >

< /tr >

< tr >

< td align="center" colspan="2" > < %= link_to '[ Забули логин чи пароль? ]', { :action = > 'remind' }% > < /td >

< /tr >

< /table >

< % end % >

< br / >

main/game.rhtml

- -

< %= render_game_info % >

< br / >

< br / >

< table width='100%' cellspacing="0" cellpadding="0" border="0" >

< tr align="center" >

< td width='1%' > < /td >

< td width='50%' align="left" > < %= image_tag 'seek_black.png', :size = > '16x16' % > < /td >

< td > < /td >

< td width='45%' > < %= link_to @game.black_player.to_s, { :controller = > 'players', :action = > 'show', :id = > @game.black_player.id } % > < /td >

< td width='1%' > < /td >

< /tr >

< tr align="center" >

< td > < /td >

< td > < /td >

< td > < /td >

< td > < %= render_black_time % > < /td >

< td > < /td >

< /tr >

< tr >

< td > < /td >

< td > < %= render_board % > < /td >

< td > < /td >

< td style="background-color: #dadada" > < %= render_moves % > < /td >

< td > < /td >

< /tr >

< tr align="center" >

< td > < /td >

< td > < /td >

< td > < /td >

< td > < %= render_white_time% > < /td >

< td > < /td >

< /tr >

< tr align="center" >

< td > < /td >

< td align="left" > < %= image_tag 'seek_white.png', :size = > '16x16' % > < /td >

< td > < /td >

< td > < %= link_to @game.white_player.to_s, { :controller = > 'players', :action = > 'show', :id = > @game.white_player.id} % > < /td >

< td > < /td >

< /tr >

< tr align="center" >

< td > < /td >

< td > < /td >

< td > < /td >

< td > < %= render_result % > < /td >

< td > < /td >

< /tr >

< tr >

< td colspan="5" > < /td >

< /tr >

< /table >

< %= link_to_remote 'Обновити', :update = > 'moves', :url = > { :action = > 'game_moves', :id = > @game.id } % >

< div > < /div >

main/logo.rhtml

- -

< table align='center' > < tr > < td align='center' >

< %= image_tag 'logo.jpg', :alt = > 'Шаховий портал rDGT', :width = > '400px', :height = > '280px' % >

< br / >

< br / > < %= link_to '[ Трансляції ]', { :action = > 'online' }% >

< br / > < %= link_to '[ Турніри ]' , { :action = > 'offline' }% >

< br / > < %= link_to '[ Кабінет ]', { :action = > 'enter' } % >

< /td > < /tr > < /table >

main/online.rhtml

- -

< !- < %= link_to '[ Перегляд ]', { :action = > 'game' }% > - >

< table width='80%' align='center' >

< tr >

< th > < /th >

< th width='10%' > Початок < /th >

< th width='25%' > Турнір < /th >

< th width='30%' > Білі < /th >

< th width='30%' > Чорні < /th >

< /tr >

< % @online_games.each do |game| % >

< tr align='center' >

< td > < %= link_to(image_tag('eye.gif', :size = > '16x16', :onclick = > '', :alt = > 'Перегляд трансляції'), { :action = > 'game', :id = > game.id }) % > < /td >

< td > < %= game.begin.to_s % > < /td >

< td > < %= link_to game.tournament.to_s, { :controller = > 'tournaments', :action = > 'show', :id = > game.tournament.id } % > < /td >

< td > < %= link_to game.white.to_s, { :controller = > 'players', :action = > 'show', :id = > game.white.id } % > < /td >

< td > < %= link_to game.black.to_s, { :controller = > 'players', :action = > 'show', :id = > game.black.id } % > < /td >

< /tr >

< % end % >

< /table >

Модель (model)

- -

class Cities < ActiveRecord::Base

end

class City < ActiveRecord::Base

end

class ClockReglament < ActiveRecord::Base

end

class Country < ActiveRecord::Base

end

class CurrentGame < ActiveRecord::Base

def init

@game = Game.find(self.game_id) if @game.nil?

end

def tournament

init

@game.tournament

end

def white

init

@game.white_player

end

def black

init

@game.black_player

end

end

class Game < ActiveRecord::Base

def moves

result = ""

@moves = Move.find_all_by_game_id self.id

@moves.sort { |movea, moveb| movea.number < = > moveb.number }.each do |move|

result += move.to_s + "|"

end

result

end

def tournament

info = GameInfo.find self.game_info_id unless self.game_info_id.nil?

t = Tournament.find info.tournament_id

end

def white_player

player = Player.new

player.id= 1

player.first_name = "Іван"

player.second_name = "Риків"

player

end

def black_player

player = Player.new

player.id= 1

player.first_name = "Сергій"

player.second_name = "Бедарев"

player

end

end

class GameInfo < ActiveRecord::Base

end

class LastMove < ActiveRecord::Base

end

class Move < ActiveRecord::Base

def to_s

((self.white_move.nil? or self.white_move == "") ? "******" : self.white_move) +

((self.black_move.nil? or self.black_move == "") ? "******" : self.black_move) + ":" +

(self.white_clock.nil? ? "" : self.white_clock) + "-" + (self.black_clock.nil? ? "" : self.black_clock)

end

end

class Player < ActiveRecord::Base

def full_name

return self.second_name + " " + self.first_name

end

def to_s

full_name

end

end

class Tournament < ActiveRecord::Base

def to_s

self.name

end

end

class TournamentView < ActiveRecord::Base

end

require 'digest/md5'

class User < ActiveRecord::Base

validates_presence_of :login

validates_uniqueness_of :login

def self.authenticate(login, password)

user = User.find_by_name(login)

if user

expected_password = encrypted_password(password)

if user.password != expected_password

user = nil

end

end

user

end

def self.encrypted_password(password)

Digest::MD5.hexdigest("sdjkvkjeho2ijij2o3d2kn3dl2kn3dn23dkn2ld3n" + password)

end

end

Міграція (db migration)

- -

ActiveRecord::Schema.define(:version = > 12) do

create_table "cities", :force = > true do |t|

t.column "name", :string, :limit = > 30

t.column "country_id", :integer

t.column "description", :text

t.column "image", :binary

end

create_table "clock_reglaments", :force = > true do |t|

t.column "title", :string, :limit = > 30

t.column "total_time", :integer

t.column "add", :boolean, :limit = > nil, :default = > false

t.column "add_time", :integer, :default = > 0

t.column "desciprion", :text

end

create_table "countries", :force = > true do |t|

t.column "name", :string, :limit = > 30

t.column "code", :string, :limit = > 30

t.column "image", :binary

t.column "description", :text

end

create_table "current_games", :force = > true do |t|

t.column "game_id", :integer

t.column "begin", :datetime

t.column "end", :datetime

t.column "description", :text

end

create_table "game_infos", :force = > true do |t|

t.column "game_id", :integer

t.column "white_id", :integer

t.column "black_id", :integer

t.column "tournament_id", :integer

t.column "result", :integer

t.column "clock_reglament_id", :integer

t.column "round", :integer

t.column "debut_code", :string, :limit = > 30

t.column "description", :text

t.column "status", :string, :limit = > 30

end

create_table "games", :force = > true do |t|

t.column "game_info_id", :integer

t.column "begin", :datetime

t.column "end", :datetime

t.column "desciption", :text

end

create_table "last_moves", :force = > true do |t|

t.column "move_id", :integer

t.column "move_time", :datetime

end

create_table "moves", :force = > true do |t|

t.column "number", :integer

t.column "game_id", :integer

t.column "white_move", :string, :limit = > 6

t.column "black_move", :string, :limit = > 6

t.column "white_clock", :float

t.column "black_clock", :float

t.column "white_comment", :text

t.column "black_comment", :text

end

create_table "players", :force = > true do |t|

t.column "first_name", :string, :limit = > 30

t.column "second_name", :string, :limit = > 30

t.column "country_id", :integer

t.column "burn_date", :datetime

t.column "fide_rating", :integer

t.column "photo", :binary

t.column "description", :text

end

create_table "tournament_views", :force = > true do |t|

t.column "name", :string, :limit = > 30

t.column "system", :string, :limit = > 30

t.column "is_match", :boolean, :limit = > nil, :default = > false

t.column "is_command", :boolean, :limit = > nil, :default = > false

t.column "total_games", :integer, :default = > 0

t.column "total_rounds", :integer, :default = > 0

t.column "description", :text

end

create_table "tournaments", :force = > true do |t|

t.column "name", :string, :limit = > 30

t.column "category", :integer

t.column "city_id", :integer

t.column "begin_date", :datetime

t.column "end_date", :datetime

t.column "tournament_view_id", :integer

t.column "status", :string, :limit = > 30

t.column "description", :text

end

create_table "users", :force = > true do |t|

t.column "login", :string, :limit = > 30

t.column "password", :string, :limit = > 50

t.column "name", :string, :limit = > 30

t.column "is_admin", :boolean, :limit = > nil, :default = > false

t.column "email", :string, :limit = > 30

t.column "webpage", :string, :limit = > 30

t.column "desciption", :text

end

end

Javascript (javascript) - здійснюють демонстрацію шахової партії, за допомогою технології AJAX звертаючи за відновленнями позиції на rDGT сервер.

game.js

- -

var images = 'http://localhost:3000/images/classic/';

var moves_url = '/main/game_moves/1';

// Фігура

function figure(id, color, type, current_field, last_field, alive, board) {

this.id = id;

this.color = color;

this.type = type;

this.current_field = current_field;

this.last_field = last_field;

this.alive = alive;

this.set_field = set_field;

this.do_move = do_move;

this.reload = reload;

this.img = document.createElement('img');

this.img.id = this.id;

this.board = board;

this.reload();

//trace('create figure [' + this.id + ']');

}

// Поле

function field(id, color, vertical, horizontal, figure, board) {

this.id = id;

this.color = color;

this.vertical = vertical;

this.horizontal = horizontal;

this.figure = figure;

this.board = board;

this.repaint = repaint;

//trace('create field [' + this.id + ']');

}

// Хід

function move(number, color, from_field, to_field, figure, alive_figure, is_short_castling, is_long_castling, prev_move, next_move, board, time) {

this.number = number;

this.color = color;

this.from_field = from_field;

this.to_field = to_field;

this.figure = figure;

this.alive_figure = alive_figure;

this.forward = forward;

this.backward = backward;

this.is_short_castling = is_short_castling;

this.is_long_castling = is_long_castling;

this.prev_move = prev_move;

this.next_move = next_move;

this.board = board;

this.white_time = white_time;

this.black_time = black_time;

}

// Колекція ходів

function move_collection(board) {

this.board = board;

this.get_move = function(color, number) {

return color == 'white' ? this.moves[(number * 2) - 1] : this.moves[number * 2];

}

this.exists_move = function(color, number) {

return get_move(color, number) != null;

}

this.get_current_move = function() {

return this.current_move;

}

this.add_move = function(move) {

trace('add move: ' + move.number + " " + moveBy.color);

if(current_move == null) {

this.first_move = move;

this.current_move = move;

} else {

move.prev_move = this.current_move;

this.current_move.next_move = move;

this.current_move = move;

}

this.moves.push(move);

}

this.first_move = null;

this.current_move = null;

this.moves = new Array();

}

// Колекція фігур

function figure_collection(board) {

this.board = board;

this.wpA = new figure('wpA', 'white', 'pawn', null, null, true, board);

this.wpB = new figure('wpB', 'white', 'pawn', null, null, true, board);

this.wpC = new figure('wpC', 'white', 'pawn', null, null, true, board);

this.wpD = new figure('wpD', 'white', 'pawn', null, null, true, board);

this.wpE = new figure('wpE', 'white', 'pawn', null, null, true, board);

this.wpF = new figure('wpF', 'white', 'pawn', null, null, true, board);

this.wpG = new figure('wpG', 'white', 'pawn', null, null, true, board);

this.wpH = new figure('wpH', 'white', 'pawn', null, null, true, board);

this.wrA = new figure('wrA', 'white', 'rook', null, null, true, board);

this.wrH = new figure('wrH', 'white', 'rook', null, null, true, board);

this.whB = new figure('whB', 'white', 'horse', null, null, true, board);

this.whG = new figure('whG', 'white', 'horse', null, null, true, board);

this.wbC = new figure('wbC', 'white', 'bishop', null, null, true, board);

this.wbF = new figure('wbF', 'white', 'bishop', null, null, true, board);

this.wq = new figure('wq', 'white', 'queen', null, null, true, board);

this.wk = new figure('wk', 'white', 'king', null, null, true, board);

this.bpA = new figure('bpA', 'black', 'pawn', null, null, true, board);

this.bpB = new figure('bpB', 'black', 'pawn', null, null, true, board);

this.bpC = new figure('bpC', 'black', 'pawn', null, null, true, board);

this.bpD = new figure('bpD', 'black', 'pawn', null, null, true, board);

this.bpE = new figure('bpE', 'black', 'pawn', null, null, true, board);

this.bpF = new figure('bpF', 'black', 'pawn', null, null, true, board);

this.bpG = new figure('bpG', 'black', 'pawn', null, null, true, board);

this.bpH = new figure('bpH', 'black', 'pawn', null, null, true, board);

this.brA = new figure('brA', 'black', 'rook', null, null, true, board);

this.brH = new figure('brH', 'black', 'rook', null, null, true, board);

this.bhB = new figure('bhB', 'black', 'horse', null, null, true, board);

this.bhG = new figure('bhG', 'black', 'horse', null, null, true, board);

this.bbC = new figure('bbC', 'black', 'bishop', null, null, true, board);

this.bbF = new figure('bbF', 'black', 'bishop', null, null, true, board);

this.bq = new figure('bq', 'black', 'queen', null, null, true, board);

this.bk = new figure('bk', 'black', 'king', null, null, true, board);

}

// Колекція полів шахівниці

function field_collection(board) {

this.get_field = get_field;

this.board = board;

this.toArray = function() {

return [this.A1, this.A2, this.A3, this.A4, this.A5, this.A6, this.A7, this.A8,

this.B1, this.B2, this.B3, this.B4, this.B5, this.B6, this.B7, this.B8,

this.C1, this.C2, this.C3, this.C4, this.C5, this.C6, this.C7, this.C8,

this.D1, this.D2, this.D3, this.D4, this.D5, this.D6, this.D7, this.D8,

this.E1, this.E2, this.E3, this.E4, this.E5, this.E6, this.E7, this.E8,

this.F1, this.F2, this.F3, this.F4, this.F5, this.F6, this.F7, this.F8,

this.G1, this.G2, this.G3, this.G4, this.G5, this.G6, this.G7, this.G8,

this.H1, this.H2, this.H3, this.H4, this.H5, this.H6, this.H7, this.H8];

}

this.A1 = new field('fieldA1', 'black', 'A', '1', null, board);

this.B1 = new field('fieldB1', 'white', 'B', '1', null, board);

this.C1 = new field('fieldC1', 'black', 'C', '1', null, board);

this.D1 = new field('fieldD1', 'white', 'D', '1', null, board);

this.E1 = new field('fieldE1', 'black', 'E', '1', null, board);

this.F1 = new field('fieldF1', 'white', 'F', '1', null, board);

this.G1 = new field('fieldG1', 'black', 'G', '1', null, board);

this.H1 = new field('fieldH1', 'white', 'H', '1', null, board);

this.A2 = new field('fieldA2', 'white', 'A', '2', null, board);

this.B2 = new field('fieldB2', 'black', 'B', '2', null, board);

this.C2 = new field('fieldC2', 'white', 'C', '2', null, board);

this.D2 = new field('fieldD2', 'black', 'D', '2', null, board);

this.E2 = new field('fieldE2', 'white', 'E', '2', null, board);

this.F2 = new field('fieldF2', 'black', 'F', '2', null, board);

this.G2 = new field('fieldG2', 'white', 'G', '2', null, board);

this.H2 = new field('fieldH2', 'black', 'H', '2', null, board);

this.A3 = new field('fieldA3', 'black', 'A', '3', null, board);

this.B3 = new field('fieldB3', 'white', 'B', '3', null, board);

this.C3 = new field('fieldC3', 'black', 'C', '3', null, board);

this.D3 = new field('fieldD3', 'white', 'D', '3', null, board);

this.E3 = new field('fieldE3', 'black', 'E', '3', null, board);

this.F3 = new field('fieldF3', 'white', 'F', '3', null, board);

this.G3 = new field('fieldG3', 'black', 'G', '3', null, board);

this.H3 = new field('fieldH3', 'white', 'H', '3', null, board);

this.A4 = new field('fieldA4', 'white', 'A', '4', null, board);

this.B4 = new field('fieldA4', 'black', 'B', '4', null, board);

this.C4 = new field('fieldC4', 'white', 'C', '4', null, board);

this.D4 = new field('fieldD4', 'black', 'D', '4', null, board);

this.E4 = new field('fieldE4', 'white', 'E', '4', null, board);

this.F4 = new field('fieldF4', 'black', 'F', '4', null, board);

this.G4 = new field('fieldG4', 'white', 'G', '4', null, board);

this.H4 = new field('fieldH4', 'black', 'H', '4', null, board);

this.A5 = new field('fieldA5', 'black', 'A', '5', null, board);

this.B5 = new field('fieldB5', 'white', 'B', '5', null, board);

this.C5 = new field('fieldC5', 'black', 'C', '5', null, board);

this.D5 = new field('fieldD5', 'white', 'D', '5', null, board);

this.E5 = new field('fieldE5', 'black', 'E', '5', null, board);

this.F5 = new field('fieldF5', 'white', 'F', '5', null, board);

this.G5 = new field('fieldG5', 'black', 'G', '5', null, board);

this.H5 = new field('fieldH5', 'white', 'H', '5', null, board);

this.A6 = new field('fieldA6', 'white', 'A', '6', null, board);

this.B6 = new field('fieldB6', 'black', 'B', '6', null, board);

this.C6 = new field('fieldC6', 'white', 'C', '6', null, board);

this.D6 = new field('fieldD6', 'black', 'D', '6', null, board);

this.E6 = new field('fieldE6', 'white', 'E', '6', null, board);

this.F6 = new field('fieldF6', 'black', 'F', '6', null, board);

this.G6 = new field('fieldG6', 'white', 'G', '6', null, board);

this.H6 = new field('fieldH6', 'black', 'H', '6', null, board);

this.A7 = new field('fieldA7', 'black', 'A', '7', null, board);

this.B7 = new field('fieldB7', 'white', 'B', '7', null, board);

this.C7 = new field('fieldC7', 'black', 'C', '7', null, board);

this.D7 = new field('fieldD7', 'white', 'D', '7', null, board);

this.E7 = new field('fieldE7', 'black', 'E', '7', null, board);

this.F7 = new field('fieldF7', 'white', 'F', '7', null, board);

this.G7 = new field('fieldG7', 'black', 'G', '7', null, board);

this.H7 = new field('fieldH7', 'white', 'H', '7', null, board);

this.A8 = new field('fieldA8', 'white', 'A', '8', null, board);

this.B8 = new field('fieldB8', 'black', 'B', '8', null, board);

this.C8 = new field('fieldC8', 'white', 'C', '8', null, board);

this.D8 = new field('fieldD8', 'black', 'D', '8', null, board);

this.E8 = new field('fieldE8', 'white', 'E', '8', null, board);

this.F8 = new field('fieldF8', 'black', 'F', '8', null, board);

this.G8 = new field('fieldG8', 'white', 'G', '8', null, board);

this.H8 = new field('fieldH8', 'black', 'H', '8', null, board);

}

function board() {

this.moves = new move_collection(this);

this.figures = new figure_collection(this);

this.fields = new field_collection(this);

this.init = init;

this.last_move = null;

// Обновляє позицію

this.refresh_moves = function() {

// Ajax запит до сервера

new Ajax.Request(moves_url, {

method: 'get',

onSuccess: function(transport) {

all_moves = transport.responseText;

trace('ajax: ' + all_moves);

}

});

trace('call = > parse_moves(' + all_moves + ')')

function existsWhite(move) {

return getWhiteMove(move) != "******";

}

function existsBlack(move) {

return getBlackMove(move) != "******";

}

function getWhiteMove(move) {

return move.substring(0,6);

}

function getWhiteTime(move) {

return move.substring(13, 19);

}

function getBlackMove(move) {

return move.substring(6,12);

}

function getBlackTime(move) {

return move.substring(20, 26);

}

function getFrom(color, move) {

}

function getTo(color, move) {

}

function isShortCastling(color, move) {

}

function isLongCastling(color, move) {

}

moves_split = all_moves.split('|');

moves_strip = new Array();

for(i = 0; i < moves_split.length; i++) {

if(moves_split[i] != "") {

moves_strip.push(moves_split[i]);

trace('split: ' + moves_split[i]);

}

}

var number = moves_strip.length;

trace('number = ' + number);

var current_move = this.moves.get_current_move();

trace('current_move = ' + current_move);

var current_number = current_move != null ? current_move.number : 0;

trace('current_number = ' + current_number);

if(number == current_number) {

if((current_move.color == 'white') && existsBlack(moves_strip[number - 1])) {

var move_annotation = getBlackMove(moves_strip[number - 1]);

var move_time = getBlackTime(moves_strip[number - 1]);

var fieldFrom = getFrom('black', move_annotation);

var fieldTo = getTo('black', move_annotation);

var move = new move(number, 'black', fieldFrom, fieldTo, fieldFrom.figure, fieldTo.figure, isShortCastling('black', move_annotation), isLongCastling('black', move_annotation), current_move, null, this, move_time);

this.moves.add_move(move);

}

}

if(number > current_number){

for(iMove = current_move; iMove < number; iMove++) {

var move_annotation = getWhiteMove(moves_strip[number - 1]);

if(existsWhite(move_annotation)) {

var move_time = getWhiteTime(moves_strip[number - 1]);

var fieldFrom = getFrom('white', move_annotation);

var fieldTo = getTo('white', move_annotation);

var move = new move(iMove + 1, 'white', fieldFrom, fieldTo, fieldFrom.figure, fieldTo.figure, isShortCastling('white', move_annotation), isLongCastling('white', move_annotation), current_move, null, this, move_time);

this.moves.add_move(move);

}

move_annotation = getBlackMove(moves_strip[number - 1]);

if(existsBlack(move_annotation)) {

var move_time = getBlackTime(moves_strip[number - 1]);

var fieldFrom = getFrom('black', move_annotation);

var fieldTo = getTo('black', move_annotation);

var move = new move(iMove + 1, 'black', fieldFrom, fieldTo, fieldFrom.figure, fieldTo.figure, isShortCastling('black', move_annotation), isLongCastling('black', move_annotation), current_move, null, this, move_time);

this.moves.add_move(move);

}

}

}

}

this.refresh_figures = refresh_figures;

this.go_begin = go_begin;

this.go_end = go_end;

this.go_next = go_next;

this.go_preview = go_preview;

this.go_custom = go_custom;

this.repaint = function() {

}

// Парсит дані пришедшие від сервера

this.parse_moves = function() {

var moves = this.all_moves;

trace('call = > parse_moves(' + moves + ')')

function existsWhite(move) {

return getWhiteMove(move) != "******";

}

function existsBlack(move) {

return getBlackMove(move) != "******";

}

function getWhiteMove(move) {

return move.substring(0,6);

}

function getWhiteTime(move) {

return move.substring(13, 19);

}

function getBlackMove(move) {

return move.substring(6,12);

}

function getBlackTime(move) {

return move.substring(20, 26);

}

function getFrom(color, move) {

}

function getTo(color, move) {

}

function isShortCastling(color, move) {

}

function isLongCastling(color, move) {

}

moves_split = moves.split('|');

moves_strip = new Array();

for(i = 0; i < moves_split.length; i++) {

if(moves_split[i] != null) {

moves_strip.push(moves_split[i]);

}

}

var number = moves_strip.length;

var current_move = this.moves.get_current_move;

var current_number = current_move != null ? current_move.number : 0;

if(number == current_number) {

if((current_move.color == 'white') && existsBlack(moves_strip[number - 1])) {

var move_annotation = getBlackMove(moves_strip[number - 1]);

var move_time = getBlackTime(moves_strip[number - 1]);

var fieldFrom = getFrom('black', move_annotation);

var fieldTo = getTo('black', move_annotation);

var move = new move(number, 'black', fieldFrom, fieldTo, fieldFrom.figure, fieldTo.figure, isShortCastling('black', move_annotation), isLongCastling('black', move_annotation), current_move, null, this, move_time);

this.moves.add_move(move);

}

}

if(number > current_number){

for(iMove = current_move; iMove < number; iMove++) {

var move_annotation = getWhiteMove(moves_strip[number - 1]);

if(existsWhite(move_annotation)) {

var move_time = getWhiteTime(moves_strip[number - 1]);

var fieldFrom = getFrom('white', move_annotation);

var fieldTo = getTo('white', move_annotation);

var move = new move(iMove + 1, 'white', fieldFrom, fieldTo, fieldFrom.figure, fieldTo.figure, isShortCastling('white', move_annotation), isLongCastling('white', move_annotation), current_move, null, this, move_time);

this.moves.add_move(move);

}

move_annotation = getBlackMove(moves_strip[number - 1]);

if(existsBlack(move_annotation)) {

var move_time = getBlackTime(moves_strip[number - 1]);

var fieldFrom = getFrom('black', move_annotation);

var fieldTo = getTo('black', move_annotation);

var move = new move(iMove + 1, 'black', fieldFrom, fieldTo, fieldFrom.figure, fieldTo.figure, isShortCastling('black', move_annotation), isLongCastling('black', move_annotation), current_move, null, this, move_time);

this.moves.add_move(move);

}

}

}

}

// Настроювання

this.all_moves = "";

this.moves_delay = 3;

this.moves_url = '/main/game_moves/1';

this.figures_delay = 2;

}

// Ініціалізація дошки

function init() {

trace('call = > init()');

// Розставляємо шахи в початкову позицію

// білі пішаки

this.figures.wpA.set_field(this.fields.A2);

this.figures.wpB.set_field(this.fields.B2);

this.figures.wpC.set_field(this.fields.C2);

this.figures.wpD.set_field(this.fields.D2);

this.figures.wpE.set_field(this.fields.E2);

this.figures.wpF.set_field(this.fields.F2);

this.figures.wp.set_field(this.fields.G2);

this.figures.wp.set_field(this.fields.H2);

// білі фігури

this.figures.wrA.set_field(this.fields.A1);

this.figures.wrH.set_field(this.fields.H1);

this.figures.whB.set_field(this.fields.B1);

this.figures.whG.set_field(this.fields.G1);

this.figures.wbC.set_field(this.fields.C1);

this.figures.wbF.set_field(this.fields.F1);

this.figures.wq.set_field(this.fields.D1);

this.figures.wk.set_field(this.fields.E1);

// чорні пішаки

this.figures.bpA.set_field(this.fields.A7);

this.figures.bpB.set_field(this.fields.B7);

this.figures.bpC.set_field(this.fields.C7);

this.figures.bpD.set_field(this.fields.D7);

this.figures.bpE.set_field(this.fields.E7);

this.figures.bpF.set_field(this.fields.F7);

this.figures.bp.set_field(this.fields.G7);

this.figures.bp.set_field(this.fields.H7);

// чорні фігури

this.figures.brA.set_field(this.fields.A8);

this.figures.brH.set_field(this.fields.H8);

this.figures.bhB.set_field(this.fields.B8);

this.figures.bhG.set_field(this.fields.G8);

this.figures.bbC.set_field(this.fields.C8);

this.figures.bbF.set_field(this.fields.F8);

this.figures.bq.set_field(this.fields.D8);

this.figures.bk.set_field(this.fields.E8);

// Створюємо Ajax опрашиватель сервера

new PeriodicalExecuter(this.refresh_moves, this.moves_delay);

new PeriodicalExecuter(this.refresh_figures, this.figures_delay);

}

// Перемальовування позиції (роблять один хід)

function refresh_figures() {

//trace('call = > refresh_figures');

if(this.exists_move) {

this.current_move = this.moves.get_current_move();

this.current_move.forward();

}

}

// Перейти до початку

function go_begin() {

}

// Перейти до кінця

function go_end() {

}

// Наступний хід

function go_next() {

}

// Попередній хід

function go_preview() {

}

// Перейти до довільного ходу

function go_custom(number, color) {

}

// зробити хід

function do_move(from_field, to_field) {

}

// Повертає поле

function get_field(vertical, horizontal) {

}

// Установити фігуру на поле

function set_field(field_to_set) {

this.last_field = field_to_set;

field_to_set.figure = this;

field_to_set.repaint();

}

// Повертає хід по номері і кольору

function get_move(number, color) {

}

// Повертає текуший хід

function get_current_move() {

returnthis.current_move;

}

// Повертає true якщо є хід який потрібно зробити

function exists_move() {

}

function repaint() {

$(this.id).innerHTML = '';

if(this.figure != null) {

$(this.id).appendChild(this.figure.img);

}

}

function reload() {

this.img.src = images + this.color[0] + this.type[0] + '.gif';

//trace('reload figure [' + this.id + '].src = \"' + this.img.src + '\"');

}

// Хід уперед !! попередню фігуру видалити

functionforward(){

if(this.to_field.figure != null) {

}

this.figure.do_move(this.from_field, this.to_field);

}

// Хід назад

function backward() {

this.figure.do_move(this.to_field, this.from_field);

this.alive_figure.set_field(this.to_field);

}

function trace(message) {

$("debug").innerHTML += message + ' < br / > ';

}

window.onload=function() {

// Запуск

var main_board = new board();

main_board.init();

// setBeginingPosition();

// refreshGame();

// new PeriodicalExecuter(refreshGame, periodicalDelay);

// new PeriodicalExecuter(refreshBoard, 1);

}

Додаток Г

Листинг програми-реєстратора шахових партій

rdgtChess.java

- -

public class rdgtChess implements Runnable

static boolean debug = false;

String comport = "COM1";

public static void main(String[] args) {

rdgtChess t;

if(args.length > 0)

t = new rdgtChess(args[0]);

else

t = new rdgtChess();

}

public rdgtChess() {

(new Thread(this)).start();

}

public rdgtChess(String comport) {

this.comport = comport;

(new Thread(this)).start();

}

// Destructor

public void finalize()

{

rdgtMysql.disconnect();

}

// This is the main loop. It samples all boards and tries at regular intervals

// to find new boards and to mark non-answering boards as, well, non-answering.

Етоголовная частина. Вона опитує всі дошки з регулярним інтервалом часу,

щоб знайти нові дошки і відзначити дошки, що невідповідають, що як невідповідають

public void run() {

rdgtController c = new rdgtController();

if (c.connect(comport) == false) return;

System.out.println(rdgtMysql.connect());

int i = 0;

while (true) {

if ((i==0) || (c.db.count_alive()==0)) {

while (c.find_all_boards()==0) {} c.dump_all_active_boards();

i = 15;

} else {

try {Thread.sleep(1000);} catch(Throwable t) {}}

c.poll_all_active_boards();

i-;

}

}

}

rdgtChessboard.java

- -

class rdgtChessboard {

Integer address;

rdgtHistory history = new rdgtHistory(this);

rdgtSnapshot snapshot = new rdgtSnapshot(this);

rdgtFenhax myFenhax = new rdgtFenhax();

boolean alive;

boolean dumped;

boolean updated;

rdgtDatabase db;

rdgtChessBoardForm board = null;

public rdgtChessboard(Integer _address, rdgtDatabase _db) {

address = _address;

db = _db;

alive = true;

dumped = false;

updated = false;

update_html();

board = new rdgtChessBoardForm();

new Thread(new Runnable() {

public void run() {

board.setVisible(true);

}

}).start();

}

rdgtSnapshot get_snapshot() {

return snapshot;

}

int get_address() {

return address.intValue();

}

public void print_position() {

board.printPosition(snapshot.debugprint());

board.printClock(snapshot.debugprint_clock());

}

String print_figure(int figure) {

if(figure == rdgtProtocol.EMPTY) {

return " ";

} else if (figure == rdgtProtocol.WPAWN) {

return "P";

} else if(figure == rdgtProtocol.WROOK) {

return "R";

} else if(figure == rdgtProtocol.WKNIGHT) {

return "N";

} else if(figure == rdgtProtocol.WBISHOP) {

return "B";

} else if(figure == rdgtProtocol.WQUEEN) {

return "Q";

} else if(figure == rdgtProtocol.WKING) {

return "K";

} else if (figure == rdgtProtocol.BPAWN) {

return "p";

} else if(figure == rdgtProtocol.BROOK) {

return "r";

} else if(figure == rdgtProtocol.BKNIGHT) {

return "n";

} else if(figure == rdgtProtocol.BBISHOP) {

return "b";

} else if(figure == rdgtProtocol.BQUEEN) {

return "q";

} else if(figure == rdgtProtocol.BKING) {

return "k";

} else {

return " ";

}

}

void set_alive(boolean x) {

alive = x;

update_html();

}

void set_dumped(boolean x) {

dumped = x;

}

void set_updated(boolean x) {

updated = x;

history.append(snapshot);

}

boolean get_alive() {

return alive;

}

boolean get_dumped() {

return dumped;

}

boolean get_updated() {

return updated;

}

void set_clockdata(boolean running, boolean batteryLow, boolean frontViewLeftSideHigh, boolean blacksTurn, boolean whitesTurn, int secW, int secB) {

snapshot.set_clockdata(running, batteryLow, frontViewLeftSideHigh, blacksTurn, whitesTurn, secW, secB);

snapshot.debugprint_clock();

}

void update_html() {

rdgtMysql.update_snapshot(snapshot);

String fen = rdgtMysql.snapshot2fen(snapshot);

myFenhax.add(fen);

rdgtMysql.update_moves(rdgtFenhax.getMoves(true, false), rdgtFenhax.getMoves(true, true), address.intValue());

}

void set_emptyboard() {

snapshot.set_emptyboard();

history.append(snapshot);

}

void set_boarddump(int[] all64, int startpos) {

snapshot.set_boarddump(all64, startpos);

dumped = true;

history.append(snapshot);

}

void set_fieldupdate(int piece, int pos) {

snapshot.set_fieldupdate(piece, pos);

updated = true;

history.append(snapshot);

}

}

rdgtConfig.java

- -

class rdgtConfig {

String getDbServer() { return server; }

String getDbUser() { return user; }

String getDbPass() { return pass; }

String getDbBase() { return dbase; }

boolean useDbServer() { return mysql; }

boolean usePgnWriter() { return pgn; }

String getPgnFileName() { return pgnfile; }

String server= "localhost";

String user= "root";

String pass= "zar1562";

String dbase= "rdgt_development";

boolean mysql = true;

boolean pgn = false;

String pgnfile = "default.pgn";

}

rdgtController.java

- -

class rdgtController extends rdgtProtocol {

rdgtDatabase db;

rdgtInterpreter ipr;

rdgtReceiver rec;

rdgtSerialport ser;

rdgtSender snd;

public rdgtController() {

db = new rdgtDatabase();

ipr = new rdgtInterpreter(db);

rec = new rdgtReceiver(ipr);

ser = new rdgtSerialport(rec);

snd = new rdgtSender(ser);

}

boolean connect(String comport) {

if (ser.open(comport)==false) {

System.out.println("Could not open "+comport);

return false;

}

System.out.println("COM port opened: "+comport);

return true;

}

int find_all_boards() {

System.out.println("Scanning for boards...");

db.unalive_all();

int alive = 0;

while (true) {

try {Thread.sleep(300);} catch(Throwable t) {}

snd.send(DGT_BUS_PING, 0);

try {Thread.sleep(1100);} catch(Throwable t) {}

int alivenow = db.count_alive();

if (alivenow == alive) break;

alive = alivenow;

for (Enumeration e = db.get_boards() ; e.hasMoreElements() ;) {

rdgtChessboard b = (rdgtChessboard)(e.nextElement());

if (b.get_alive()==true) {

snd.send(DGT_BUS_IGNORE_NEXT_BUS_PING, b.get_address());

}

}

}

System.out.println("Scanning completed, found "+Integer.toString(alive)+" boards.\n");

return alive;

}

void dump_all_active_boards() {

for (Enumeration e = db.get_boards() ; e.hasMoreElements() ;) {

rdgtChessboard b = (rdgtChessboard)(e.nextElement());

if (b.get_alive()==true) {

b.set_dumped(false);

for (int i=0; i < 3; i++) { if (b.get_dumped()==true) break;

snd.send(DGT_BUS_SEND_BRD, b.get_address());

try {Thread.sleep(200);} catch(Throwable t) {}

}

if (b.get_dumped()==false) {

System.out.println("Board "+Integer.toString(b.get_address())+" does not reply to dump_board.");

b.set_alive(false);

}

}

}

}

void poll_all_active_boards() {

int TIMEOUT = 100;

for (Enumeration e = db.get_boards() ; e.hasMoreElements() ;) {

rdgtChessboard b = (rdgtChessboard)(e.nextElement());

if (b.get_alive()==true) {

snd.send(DGT_BUS_SEND_CLK, b.get_address());

try {Thread.sleep(TIMEOUT);} catch(Throwable t) {}

b.set_updated(false);

snd.send(DGT_BUS_SEND_CHANGES, b.get_address());

try {Thread.sleep(TIMEOUT);} catch(Throwable t) {}

for (int i=0; i < 2; i=i+1) {

if (b.get_updated()==true) break;

snd.send(DGT_BUS_REPEAT_CHANGES, b.get_address());

try {Thread.sleep(TIMEOUT);} catch(Throwable t) {}}

if (b.get_updated()==false) {

System.out.println("Board "+Integer.toString(b.get_address())+" does not reply anymore.");

b.set_alive(false);

} else {

b.print_position();

}

}

}

}

}

rdgtDatabase.java

- -

class rdgtDatabase {

Hashtable boards;

public rdgtDatabase() {

boards = new Hashtable();

}

rdgtChessboard get_board(int address) {

Integer _address = new Integer(address);

rdgtChessboard b = (rdgtChessboard)(boards.get(_address));

if (b==null) {

System.out.println("New board found: ID="+_address.toString());

b = new rdgtChessboard(_address, this);

boards.put(_address, b);

}

return b;

}

int get_boardcount() {

return boards.size();

}

Enumeration get_boards() {

return boards.elements();

}

void unalive_all() {

for (Enumeration e = boards.elements() ; e.hasMoreElements() ;) {

((rdgtChessboard)(e.nextElement())).set_alive(false);

}

}

int count_alive() {

int x = 0;

for (Enumeration e = boards.elements() ; e.hasMoreElements() ;) {

if (((rdgtChessboard)(e.nextElement())).get_alive()==true) x++;

}

return x;

}

}

rdgtFenboard.java

- -

class rdgtFenboard {

int[] itsBoard;

String itsFen;

public rdgtFenboard(){

itsBoard = new int[64];

for(int i=0;i < 64;i++)

itsBoard[i]='.';

itsFen="";

}

public rdgtFenboard(String fen){ setBoard(fen); }

public rdgtFenboard(int[] board) { setBoard(board); }

public boolean setBoard(String fen){

if(!validateFen(fen))

return false;

itsBoard=fen2board(fen);

itsFen=fen;

return true;

}

public int getPieceAt(int x, int y){

if(x < 0 || x > 7 || y < 0 || y > 7) return 0;

return itsBoard[y*8+x];

}

public boolean setBoard(int[] board){

if(board.length != 64)

return false;

itsBoard=board;

return true;

}

public void print(){

printBoard(itsBoard);

}

public int[] getBoard() { return itsBoard; }

public rdgtFenboard mask(rdgtFenboard b){

rdgtFenboard output;

output=new rdgtFenboard(mask(getBoard(),b.getBoard()));

return output;

}

public int diffCount(rdgtFenboard b){

rdgtFenboard m = mask(b);

int[] table=m.getBoard();

int output=0;

for(int i=0;i < 64;i++){

if(table[i]!='.')

output++;

}

return output;

}

int[] fen2board(String aFen){

int[] board = new int[64];

int square=0;

int chr=0;

while(square < 64){

char c = aFen.charAt(chr);

if(c=='r'||c=='R'||c=='n'||c=='N'||c=='b'||c=='B'||c=='q'||c=='Q'||c=='k'||c=='K'||c=='p'||c=='P'){

board[square]=c;

square++;

}

if(c > ='1' && c < ='8'){

for(int i=0;i < c-'1'+1;i++){

board[square]='.';

square++;

}

}

chr++;

}

return board;

}

String[] outputBoard(int[] board){

String s="";

String[] out = new String[8];

for(int chr=0;chr < 64;chr++){

if(board[chr] < 0)

s += "-" + (char)(Math.abs(board[chr]));

else if(board[chr]==0)

s += ", ";

else

s += (char)board[chr] + " ";

if((chr+1)%8==0){

out[chr/8]=s;

s="";

}

}

return out;

}

void printBoard(int[] board){

String[] out = outputBoard(board);

for(int i=0;i < 8;i++){

System.out.println(out[i]);

}

System.out.println();

}

int[] mask(int[] b1, int[] b2){

int[] output=new int[64];

for(int i=0;i < 64;i++){

if(b2[i]!=b1[i]){

if(b2[i]=='.')

output[i]=-b1[i];

else

output[i]=b2[i];

}

else

output[i] = '.';//b2[i]-b1[i];

}

return output;

}

boolean validateFen(String aFen){

/* Only check board part of FEN */

if(aFen.indexOf(' ') > 0){

aFen = aFen.substring(0,aFen.indexOf(' '));

}

int s=0;

for(int c=0;c < aFen.length();c++){

if(aFen.charAt(c) == '/') s++;

}

if(s!=7) return false;

int x=0;

for(int c=0;c < aFen.length();c++){

if(aFen.charAt(c) == '/'){

if(x!=8) return false;

else x=0;

}

else

{

if(aFen.charAt(c) > = '1' && aFen.charAt(c) < = '8')

x+= aFen.charAt(c)-'1' ;

x++;

}

}

if(x!=8) return false;

return true;

}

}

rdgtFendiff.java

- -

class rdgtFendiff {

char piece;

boolean added;

int square;

rdgtFenboard before;

rdgtFenboard after;

public rdgtFenboard getBefore() { return before; }

public rdgtFenboard getAfter() { return after; }

public char getPiece() { return piece; }

public boolean isAdded() { return added; }

public int getSquare() { return square; }

public boolean isWhite(){

if(piece > 'A' && piece < 'Z')

return true;

else

return false;

}

public boolean equals(rdgtFendiff other){

if(getPiece() != other.getPiece()) return false;

if(getSquare() != other.getSquare()) return false;

if(isAdded() != other.isAdded()) return false;

return true;

}

public rdgtFendiff() {

secured=false;

}

public rdgtFendiff(char piece, boolean added, int square){

set(piece,added,square);

}

public rdgtFendiff(int piece, int square){

if(piece < 0){

this.piece = (char)(-piece);

added=false;

}

else {

this.piece=(char)piece;

added=true;

}

this.square=square;

}

public rdgtFendiff(int piece,int square, rdgtFenboard before, rdgtFenboard after){

this.before=before;

this.after=after;

if(piece < 0){

this.piece = (char)(-piece);

added=false;

}

else {

this.piece=(char)piece;

added=true;

}

this.square=square;

}

public void set(char piece, boolean added, int square){

this.piece=piece;

this.added=added;

this.square=square;

}

public String toString() {

String output = ""+piece;

if(added) output += "@";

else output += "&";

output += (char)((square)%8+'a') + "" + (8-square/8);

return output;

}

}

rdgtFenhax.java

- -

public class rdgtFenhax {

static boolean debug=false;

static boolean rotated=false;

public rdgtFenhax(){

boards=new ArrayList();

moves=new movelist();

diffTable=new ArrayList();

result="?-?";

plyCount=0;

}

static String getMoves(boolean shortNotation, boolean nice) {

calcMoves();

return moves.getAll(shortNotation,nice);

}

static String getMoves(){

return getMoves(false,false);

}

static int getPlyCount(){

calcMoves();

return moves.size();

}

static void clear(){

boards.clear();

moves.clear();

diffTable.clear();

result="?-?";

}

static String getResult() { return result; }

static boolean add(String aFen){

rdgtFenboard f = new rdgtFenboard();

if(!f.setBoard(aFen))

return false;

boards.add(f);

if(aFen.indexOf("rnbqkbnr/pppppppp/8/8/8/8/PPPPPPPP/RNBQKBNR") > =0){

clear();

boards.add(f);

}

if((aFen.indexOf("rnbq1bnr/pppppppp") > =0 && aFen.indexOf("PPPPPPPP/RNBQ1BNR") > = 0)||

(aFen.indexOf("rnbqkbnr/pppppppp") > =0 && aFen.indexOf("PPPPPPPP/RNBQ1BNR") > = 0)||

(aFen.indexOf("rnbq1bnr/pppppppp") > =0 && aFen.indexOf("PPPPPPPP/RNBQKBNR") > = 0)){

int[] b=f.getBoard();

boolean black=false;

boolean white=false;

for(int i=16;i < =47;i++){

if(b[i] == 'k') black=true;

if(b[i] == 'K') white=true;

}

if(black && white) result="1/2-1/2";

else if(black) result="0-1";

else if(white) result="1-0";

}

if(boards.size() > =2){

rdgtFenboard last = (rdgtFenboard)boards.get(boards.size()-1);

rdgtFenboard nextlast = (rdgtFenboard)boards.get(boards.size()-2);

if(last.diffCount(nextlast) < 5){

rdgtFenboard m=nextlast.mask(last);

int[] mask = m.getBoard();

for(int i=0;i < 64;i++){

if(mask[i] != '.' && mask[i] < 0){

diffTable.add(new rdgtFendiff(mask[i],i,nextlast,last));

}

}

for(int i=0;i < 64;i++){

if(mask[i] != '.' && mask[i] > 0){

diffTable.add(new rdgtFendiff(mask[i],i,nextlast,last));

}

}

}

else {

clear();

boards.add(f);

}

}

return true;

}

static void calcMoves(){

moves.clear();

if(debug){

for(int i=0;i < diffTable.size();i++){

System.out.print(i + ":" + ((rdgtFendiff)diffTable.get(i)).toString() + " ");

}

System.out.print("\n");

}

int offset=0;

int length=diffTable.size();

while(offset < length){

int start=offset;

int end=-1;

boolean turn = isWhite(((rdgtFendiff)diffTable.get(offset)).getPiece());

int i=start;

while(end==-1){

rdgtFendiff test = (rdgtFendiff)diffTable.get(i);

if(turn != isWhite(test.getPiece()) && test.isAdded()){

end=i-1;

}

else{

i++;

if(i > =length)

end=length-1;

}

if(turn==isWhite(test.getPiece()) && test.isAdded()){

offset=i;

}

}

if(offset==start) offset++;

if(debug) System.out.print(start + "-"+end+" ");

movelist chunkMoves = new movelist(true,true);

for(int s=start;s < end;s++){

rdgtFendiff a = (rdgtFendiff)diffTable.get(s);

for(int e=s+1;e < =end;e++){

rdgtFendiff b = (rdgtFendiff)diffTable.get(e);

if(a.getPiece() == b.getPiece() && a.getSquare() != b.getSquare()){

if(!a.isAdded() && b.isAdded()){

String special="";

if(b.getPiece()=='P' && b.getSquare()/8==0){

for(int j=e+1;j < =end;j++){

rdgtFendiff prom = (rdgtFendiff)diffTable.get(j);

if(prom.isAdded() && prom.isWhite()){

if(a.getSquare()%8 != b.getSquare()%8)

special+=pos2xy(a.getSquare()).substring(0,1)+"x";

special+=pos2xy(b.getSquare())+"="+prom.getPiece();

b=prom;

}

}

}

if(b.getPiece()=='p' && b.getSquare()/8==7){

for(int j=e+1;j < =end;j++){

rdgtFendiff prom = (rdgtFendiff)diffTable.get(j);

if(prom.isAdded() && prom.isWhite()){

if(a.getSquare()%8 != b.getSquare()%8)

special+=pos2xy(a.getSquare()).substring(0,1)+"x";

special+=pos2xy(b.getSquare())+"="+prom.getPiece();

b=prom;

}

}

}

chunkMoves.add(new move(a,b,special));

}

}

}

}

if(chunkMoves.size()==0){

rdgtFendiff a = (rdgtFendiff)diffTable.get(start);

for(int s=start;s < =end;s++){

rdgtFendiff b = (rdgtFendiff)diffTable.get(s);

if(b.isAdded()){

if(a.getPiece()=='P' && a.getSquare()/8==1 && !a.isAdded()){

String special="";

if(a.getSquare()%8 != b.getSquare()%8)

special+=pos2xy(a.getSquare()).substring(0,1)+"x";

special+=pos2xy(b.getSquare())+"="+b.getPiece();

chunkMoves.add(new move(a,b,special));

}

else if(a.getPiece()=='p' && a.getSquare()/8==6 && !a.isAdded()){

String special="";

if(a.getSquare()%8 != b.getSquare()%8)

special+=pos2xy(a.getSquare()).substring(0,1)+"x";

special+=pos2xy(b.getSquare())+"="+b.getPiece();

chunkMoves.add(new move(a,b,special));

}

else

chunkMoves.add(new move(a,b,""+a.getPiece()+"@"+pos2xy(a.getSquare())));

}

}

}

for(int j=0;j < chunkMoves.size();j++){

if(debug) System.out.print((chunkMoves.get(j)).toString() + " ");

moves.add(chunkMoves.get(j));

}

if(debug) System.out.print("\n");

}

}

static String pos2xy(int pos){

String s = "" + (char)((pos)%8+'a') + "" + (8-pos/8);

return s;

}

static boolean isWhite(char piece){

if(piece > 'A' && piece < 'Z')

return true;

else

return false;

}

static movelist moves;

static ArrayList boards;

static ArrayList diffTable;

static String result;

static int plyCount;

}

class move {

rdgtFendiff from;

rdgtFendiff to;

boolean take;

String special;

public move(rdgtFendiff from, rdgtFendiff to){

this.from=from;

this.to=to;

take=false;

special="";

}

public move(rdgtFendiff from, rdgtFendiff to, String special){

this.from=from;

this.to=to;

take=false;

this.special=special;

}

public rdgtFendiff getFrom(){ return from; }

public rdgtFendiff getTo(){ return to; }

public char getPiece(){ return from.getPiece(); }

public int getFromSquare() { return from.getSquare(); }

public int getToSquare() { return to.getSquare(); }

public String getFromCor() { return pos2xy(getFromSquare()); }

public String getToCor() { return pos2xy(getToSquare()); }

public boolean isWhite() { return from.isWhite(); }

public String longNotation() { return moveString(false); }

public String shortNotation() { return moveString(true); }

public void setTake(boolean take){ this.take=take; }

public boolean getTake() { return take; }

String moveString(boolean shortNotation){

if(!special.equals("")) {

if(isCheck(isWhite()))

return special + "+";

else

return special;

}

boolean ep=false;

char takeBit='-';

if(take) takeBit='x';

String s="";

if(getPiece()!='p' && getPiece()!='P')

s+=new String(""+getPiece()).toUpperCase();

if(!shortNotation)

s+=getFromCor()+takeBit;

else {

if(getPiece()=='R' || getPiece()=='r')

if(findRookLength(getToSquare()%8,getToSquare()/8,getPiece()))

s+=getFromCor()+takeBit;

if(getPiece()=='N' || getPiece()=='n')

if(findNightLength(getToSquare()%8,getToSquare()/8,getPiece()))

s+=getFromCor()+takeBit;

if(getPiece()=='B' || getPiece()=='b')

if(findBishopLength(getToSquare()%8,getToSquare()/8,getPiece()))

s+=getFromCor()+takeBit;

if(getPiece()=='Q' || getPiece()=='q')

if(findQueenLength(getToSquare()%8,getToSquare()/8,getPiece()))

s+=getFromCor()+takeBit;

if(getPiece()=='P' || getPiece()=='p')

if(!getFromCor().substring(0,1).equals(getToCor().substring(0,1))) {

s+=getFromCor().substring(0,1)+"x";

if(!take) ep=true;

}

if(take && s.length() > =1){

if(s.charAt(s.length()-1) != 'x')

s+="x";

}

}

s+=getToCor();

if(ep)

s+=" ep.";

/** Is it a check? **/

if(isCheck(isWhite())) s+='+';

return s;

}

boolean isCheck(boolean white){

int k=-1;

int K=-1;

for(int i=0;i < 64;i++){

if(to.getAfter().getPieceAt(i%8,i/8) == 'k') k=i;

if(to.getAfter().getPieceAt(i%8,i/8) == 'K') K=i;

}

boolean check=false;

if(white){

if(findQueenLength(k%8,k/8,'Q')) check=true;

if(findRookLength(k%8,k/8,'R')) check=true;

if(findBishopLength(k%8,k/8,'B')) check=true;

if(findNightLength(k%8,k/8,'N')) check=true;

if(findPawnLength(k%8,k/8,'P')) check=true;

}

else{

if(findQueenLength(K%8,K/8,'q')) check=true;

if(findRookLength(K%8,K/8,'r')) check=true;

if(findBishopLength(K%8,K/8,'b')) check=true;

if(findNightLength(K%8,K/8,'n')) check=true;

if(findPawnLength(K%8,K/8,'p')) check=true;

}

return check;

}

/** Is there a night on a night-distance from square? **/

boolean findNightLength(int x, int y,char n){

rdgtFenboard b = to.getAfter();

if(b.getPieceAt(x-1,y-2) == n) return true;

if(b.getPieceAt(x+1,y-2) == n) return true;

if(b.getPieceAt(x-2,y-1) == n) return true;

if(b.getPieceAt(x+2,y-1) == n) return true;

if(b.getPieceAt(x-2,y+1) == n) return true;

if(b.getPieceAt(x+2,y+1) == n) return true;

if(b.getPieceAt(x-1,y+2) == n) return true;

if(b.getPieceAt(x+1,y+2) == n) return true;

return false;

}

boolean findRookLength(int x, int y, char r){

rdgtFenboard b = to.getAfter();

int xx=0;

int yy=0;

do{

xx++;

if(b.getPieceAt(x+xx,y+yy) == r) return true;

}while(b.getPieceAt(x+xx,y+yy) == '.');

xx=0;

do{

xx-;

if(b.getPieceAt(x+xx,y+yy) == r) return true;

}while(b.getPieceAt(x+xx,y+yy) == '.');

xx=0;

do{

yy-;

if(b.getPieceAt(x+xx,y+yy) == r) return true;

}while(b.getPieceAt(x+xx,y+yy) == '.');

yy=0;

do{

yy++;

if(b.getPieceAt(x+xx,y+yy) == r) return true;

}while(b.getPieceAt(x+xx,y+yy) == '.');

return false;

}

boolean findBishopLength(int x, int y, char r){

rdgtFenboard b = to.getAfter();

int xx=0;

int yy=0;

do{

xx++;

yy++;

if(b.getPieceAt(x+xx,y+yy) == r) return true;

}while(b.getPieceAt(x+xx,y+yy) == '.');

xx=0;

yy=0;

do{

xx-;

yy-;

if(b.getPieceAt(x+xx,y+yy) == r) return true;

}while(b.getPieceAt(x+xx,y+yy) == '.');

xx=0;

yy=0;

do{

yy-;

xx++;

if(b.getPieceAt(x+xx,y+yy) == r) return true;

}while(b.getPieceAt(x+xx,y+yy) == '.');

yy=0;

xx=0;

do{

yy++;

xx-;

if(b.getPieceAt(x+xx,y+yy) == r) return true;

}while(b.getPieceAt(x+xx,y+yy) == '.');

return false;

}

boolean findQueenLength(int x, int y, char q){

if(findRookLength(x,y,q)) return true;

if(findBishopLength(x,y,q)) return true;

return false;

}

boolean findPawnLength(int x, int y, char p){

rdgtFenboard b = to.getAfter();

if(p=='P'){

if(b.getPieceAt(x-1,y-1)==p) return true;

if(b.getPieceAt(x+1,y-1)==p) return true;

}

else {

if(b.getPieceAt(x-1,y-1)==p) return true;

if(b.getPieceAt(x+1,y-1)==p) return true;

}

return false;

}

public String toString(){

return ""+from.toString() + "-" + to.toString();

}

public boolean equals(move other){

if(!from.equals(other.getFrom())) return false;

if(!to.equals(other.getTo())) return false;

return true;

}

String pos2xy(int pos){

String s = "" + (char)((pos)%8+'a') + "" + (8-pos/8);

return s;

}

}

class movelist {

ArrayList moves;

boolean unique;

boolean noSmooth;

public void clear(){moves.clear(); }

public void remove(int n) { moves.remove(n); }

public movelist(){ moves=new ArrayList(); unique=false; }

public movelist(boolean unique, boolean noSmooth) {

moves=new ArrayList();

this.unique=unique;

this.noSmooth=noSmooth;

}

public move get(int n){ return (move)moves.get(n); }

public int size() { return moves.size(); }

public String toString() { return getAll(false,false); }

public void print(boolean shortNotation) {

System.out.println("Moves");

System.out.print(getAll(shortNotation,true));

}

void fixTakes(){

for(int i=1;i < moves.size();i++){

int toSquare = ((move)moves.get(i)).getToSquare();

char p = (char) ((move)moves.get(i-1)).getTo().getAfter().getBoard()[toSquare];

if(p!='.'){

move m=(move)moves.get(i);

m.setTake(true);

moves.set(i,m);

}

}

}

public String getAll(boolean shortNotation,boolean nice){

fixTakes();

String output="";

boolean lastColor=false;

int n=1;

for(int i=0;i < moves.size();i++){

move m=(move)moves.get(i);

if(m.isWhite() && lastColor==false){

if(nice)

output += n+".\t";

else

output += n+". ";

n++;

}

if(n==1 && !m.isWhite()) {

if(nice)

output += "1.\t...\t\t";

else

output += "1. ... ";

}

lastColor=m.isWhite();

int length=output.length();

if(shortNotation)

output += m.shortNotation()+" ";

else

output += m.longNotation()+" ";

if(nice){

if(!m.isWhite())

output += "\n";

else{

if(output.length()-length < 8) output += "\t";

if(output.length()-length < 12) output += "\t";

}

}

}

return output;

}

public void add(move aMove){

if(!unique){

moves.add(aMove);

return;

}

for(int i=0;i < moves.size();i++){

if(((move)moves.get(i)).equals(aMove))

return;

}

if(moves.size() > =1){

move m=(move)moves.get(moves.size()-1);

// O-O

if(m.moveString(false).equals("Ke1-g1") && aMove.moveString(false).equals("Rh1-f1")){

moves.remove(moves.size()-1);

moves.add(new move(aMove.getFrom(),aMove.getTo(),"O-O"));

return;

}

// O-O-O

if(m.moveString(false).equals("Ke1-c1") && aMove.moveString(false).equals("Ra1-d1")){

moves.remove(moves.size()-1);

moves.add(new move(aMove.getFrom(),aMove.getTo(),"O-O-O"));

return;

}

// O-O

if(m.moveString(false).equals("Ke8-g8") && aMove.moveString(false).equals("Rh8-f8")){

moves.remove(moves.size()-1);

moves.add(new move(aMove.getFrom(),aMove.getTo(),"O-O"));

return;

}

// O-O-O

if(m.moveString(false).equals("Ke8-c8") && aMove.moveString(false).equals("Ra8-d8")){

moves.remove(moves.size()-1);

moves.add(new move(aMove.getFrom(),aMove.getTo(),"O-O-O"));

return;

}

}

moves.add(aMove);

}

public void removeSmooth(){

for(int a=0;a < moves.size();a++){

move aMove=(move)moves.get(a);

for(int i=0;i < moves.size();i++){

move test = (move)moves.get(i);

if(test.getPiece() == aMove.getPiece()){

if(aMove.getFrom().getSquare() == test.getTo().getSquare() ||

aMove.getTo().getSquare() == test.getFrom().getSquare()){

if(a==i){

moves.remove(i);

i=moves.size();

a=0;

}

else if(i > a){

moves.remove(i);

moves.remove(a);

i=moves.size();

a=0;

}

else {

moves.remove(a);

moves.remove(i);

i=moves.size();

a=0;

}

}

}

}

}

}

}

rdgtHistory.java

- -

class rdgtHistory {

Vector history = new Vector();

rdgtSnapshot lastadded = null;

rdgtSnapshot last = null;

rdgtChessboard board;

public rdgtHistory(rdgtChessboard _board) {

board = _board;

}

void append(rdgtSnapshot x) {

if(history.size()==0){

history.addElement(x.copy());

board.update_html();

}

else if(x.sameas((rdgtSnapshot)history.lastElement())==false){

history.addElement(x.copy());

board.update_html();

}

}

void debugprint() {

System.out.println("======= History for board: "+board.address.toString());

for (Enumeration e = history.elements(); e.hasMoreElements() ;) {

((rdgtSnapshot)(e.nextElement())).debugprint();

}

}

}

rdgtHtml.java

- -

class rdgtHtml extends rdgtProtocol {

static String extension = ".html";

static String indexfilename = "board_index";

static String historyprefix = "boardhistory_";

static String snapshotprefix = "boardsnapshot_";

static void print_index(rdgtDatabase db) {

StringBuffer s = new StringBuffer(2000);

s.append(" < html > \n < head > \n < meta http-equiv=refresh content=3 > \n < /head > \n");

s.append(" < body > < h1 > Chessboards < /h1 > \n < table border=1 cellspacing=0 cellpadding=10 > \n");

s.append(" < tr > < th > Board id < th > Status < th > Time of last move < th > Snapshot < th > History\n");

for (Enumeration e = db.get_boards() ; e.hasMoreElements() ;) {

rdgtChessboard b = (rdgtChessboard)(e.nextElement());

s.append(" < tr > \n < td valign=top > ");

s.append(Integer.toString(b.get_address()));

s.append("\n < td > ");

if (b.get_alive()==true) s.append("Online"); else s.append("Offline");

s.append(" < td > ");

s.append(b.get_snapshot().get_time().toString());

s.append("\n < td > < a href=\"");

s.append(snapshotprefix);

s.append(Integer.toString(b.get_address()));

s.append(extension);

s.append("\" > Link < /a > < td > < a href=\"");

s.append(historyprefix);

s.append(Integer.toString(b.get_address()));

s.append(extension);

s.append("\" > Link < /a > \n");

}

s.append(" < /table > \n < /body > \n < /html > \n");

if (writefile(indexfilename+extension, s.toString()) == false) {

System.err.println("Error: Failed to write indexfile.");

return;

}

}

static void print_history(rdgtHistory h) {

StringBuffer s = new StringBuffer(2000);

s.append(" < html > \n < head > < /head > \n");

s.append(" < body > < h1 > History for Chessboard: ");

s.append(Integer.toString(h.board.get_address()));

s.append(" < /h1 > \n");

int i = 0;

for (Enumeration e = h.history.elements() ; e.hasMoreElements() ;) {

rdgtSnapshot ss = (rdgtSnapshot)(e.nextElement());

i=i+1;

s.append(" < p > < hr size=1 > < p > < h3 > Move: ");

s.append(Integer.toString(i));

s.append("    ");

s.append(ss.get_time().toString());

s.append(boardview(ss));

s.append("\n");

}

s.append(" < /body > \n < /html > \n");

if (writefile(historyprefix + Integer.toString(h.board.get_address()) + extension, s.toString()) == false) {

System.err.println("Error: Failed to write historyfile.");

return;

}

}

static String boardview(rdgtSnapshot b) {

StringBuffer s = new StringBuffer(1000);

s.append(" < table border=0 cellpadding=0 cellspacing=0 > \n");

boolean filled = true;

for (int i=0; i < 8; i=i+1) {

s.append(" < tr > ");

for (int j=0; j < 8; j=j+1) {

s.append(" < td > < img src=\"images/");

int p = b.pieces[(i*8)+j];

if (p==EMPTY) s.append("empty");

else if (p==WPAWN) s.append("w_pawn");

else if (p==WROOK) s.append("w_rook");

else if (p==WKNIGHT) s.append("w_knight");

else if (p==WBISHOP) s.append("w_bishop");

else if (p==WKING) s.append("w_king");

else if (p==WQUEEN) s.append("w_queen");

else if (p==BPAWN) s.append("b_pawn");

else if (p==BROOK) s.append("b_rook");

else if (p==BKNIGHT) s.append("b_knight");

else if (p==BBISHOP) s.append("b_bishop");

else if (p==BKING) s.append("b_king");

else if (p==BQUEEN) s.append("b_queen");

if (filled) s.append("1"); else s.append("2");

filled = !filled;

s.append(".gif\" > ");

}

filled = !filled;

s.append(" < /tr > \n");

}

s.append("\n < /table > ");

return s.toString();

}

static void print_snapshot(rdgtSnapshot ss) {

StringBuffer s = new StringBuffer(2000);

s.append(" < html > \n < head > \n < meta http-equiv=refresh content=4 > \n < /head > \n");

s.append(" < body > < h1 > Snapshot of Chessboard: ");

s.append(Integer.toString(ss.board.get_address()));

s.append(" < /h1 > \n < h3 > ");

s.append(ss.get_time().toString());

s.append(" < /h3 > \n");

s.append(boardview(ss));

s.append("\n < /body > \n < /html > \n");

if (writefile(snapshotprefix + Integer.toString(ss.board.get_address()) + extension, s.toString()) == false) {

System.err.println("Error: Failed to write snapshotfile.");

return;

}

}

static boolean writefile(String filename, String content) {

FileWriter f = null;

for (int i=0; i < 10; i=i+1) {

try {

f = new FileWriter(filename);

break;

}

catch (Throwable t) {

System.err.println("Error opening "+filename+" for writing. Retrying...");

}

}

if (f==null) {

System.out.println("Failed to open file "+filename);

return false;

}

try {

f.write(content);

f.close();

}

catch (Exception e) {

System.out.println("Error writing file "+filename+". ("+e.toString()+")");

return false;

}

return true;

}

}

rdgtInterpreter.java

- -

class rdgtInterpreter extends rdgtProtocol {

rdgtDatabase db;

public rdgtInterpreter(rdgtDatabase _db) {

db = _db;

}

public boolean interpret(int[] data) {

int len = ((int) data[1] * 0x80) + (int) data[2];

int address = ((int) data[3] * 0x80) + (int) data[4];

String tmp = "Len:" + Integer.toString(len) + " Address:" + Integer.toString(address);

if (data[0] == DGT_BUS_PING) {

System.out.println("Received message: PING " + tmp);

} else if (data[0] == DGT_BUS_UPDATE) {

System.out.println("Received message: UPDATE " + tmp);

} else if (data[0] == DGT_BUS_BWTIME) {

System.out.println("Received message: BWTIME " + tmp);

} else {

System.out.println("Received message: (some other message) " + tmp);

}

if (check_checksum(data) == false) {

System.out.println("Message failed checksum test");

return false;

}

if (data[0] == DGT_BUS_PING) {

if (data.length != 6) { // address+data

System.out.println("Illegal: Got a BUS_PING with wrong size");

return false;

}

db.get_board(address).set_alive(true);

return true;

} else if (data[0] == DGT_BUS_BRD_DUMP) {

if (data.length != (6 + 64)) {

System.out.println("Illegal: Got a BUS_BRD_DUMP with wrong size");

return false;

}

rdgtChessboard c = db.get_board(address);

c.set_boarddump(data, 5);

return true;

} else if (data[0] == DGT_BUS_UPDATE) {

byte pr[] = new byte[data.length - 5];

for (int i = 5; i < data.length; i++) {

pr[i - 5] = (byte) data[i];

}

System.out.println(new String(pr));

rdgtChessboard c = db.get_board(address);

for (int i = 5; i < data.length - 1; i++) {

if (data[i] == EE_POWERUP) {

}

else if (data[i] == EE_EOF) {

}

else if (data[i] == EE_FOURROWS) {

}

else if (data[i] == EE_EMPTYBOARD) {

c.set_emptyboard();

} else if (data[i] == EE_DOWNLOADED) {

}

else if (data[i] == EE_BEGINPOS) {

}

else if (data[i] == EE_BEGINPOS_ROT) {

}

else if (data[i] == EE_START_TAG) {

}

else if (data[i] == EE_WATCHDOG_ACTION) {

}

else if (data[i] == EE_NOP) {

}

else if (data[i] > = 0x40 && data[i] < = 0x5F) { // 2-byte piece update

c.set_fieldupdate(data[i] & 0x0F, data[i + 1]);

i++;

} else if ((data[i] > = 0x60 && data[i] < = 0x69) || (data[i] > = 0x70 && data[i] < = 0x79)) {

i += 2;

} else {

System.out.println("Unknown data in DGT_BUS_UPDATE command.");

return false;

}

}

c.set_updated(true);

return true;

}

else if (data[0] == DGT_BUS_BWTIME) {

if (data.length != 13) {

System.out.println("Illegal: Got a DGT_BUS_BWTIME with wrong size (!=10)");

return false;

}

if ((data[11] & 0x20) != 0) {

System.out.println(" (No clock connected)");

return true;

}

boolean running = (data[11] & 0x01) != 0;

boolean batteryLow = (data[11] & 0x04) != 0;

boolean frontViewLeftSideHigh = (data[11] & 0x02) != 0;

boolean blackPlayersTurn = (data[11] & 0x08) != 0;

boolean whitePlayersTurn = (data[11] & 0x10) != 0;

int hoursW = data[5] & 0x0F;

int minutesW = (data[6] & 0x0F) + ((data[6] > > 4) * 10);

int secondsW = (data[7] & 0x0F) + ((data[7] > > 4) * 10);

int hoursB = data[8] & 0x0F;

int minutesB = (data[9] & 0x0F) + ((data[9] > > 4) * 10);

int secondsB = (data[10] & 0x0F) + ((data[10] > > 4) * 10);

secondsW = (((hoursW * 60) + minutesW) * 60) + secondsW;

secondsB = (((hoursB * 60) + minutesB) * 60) + secondsB;

db.get_board(address).set_clockdata(running, batteryLow, frontViewLeftSideHigh,

blackPlayersTurn, whitePlayersTurn, secondsW, secondsB);

return true;

} else if (data[0] == DGT_BUS_FROM_START) {

} else if (data[0] == DGT_BUS_START_GAME_WRITTEN) {

} else if (data[0] == DGT_BUS_VERSION) {

}

System.err.println("Unknown message (checksum was ok).");

return true;

}

boolean check_checksum(int[] data) {

int sum = 0;

for (int i = 0; i < (data.length - 1); i = i + 1) {

sum = (sum + data[i]) & 0x7F;

}

if (sum == data[data.length - 1]) {

return true;

}

return false;

}

}

rdgtMysql.java

- -

class rdgtMysql extends rdgtProtocol {

static String server= "localhost";

static String user= "root";

static String pass= "zar1562";

static String dbase= "rdgt_development";

static String update_table= "games";

static Connection conn = null;

static Statement stmt = null;

static boolean rotated=false;

static String connect()

{

try

{

Class.forName("com.mysql.jdbc.Driver").newInstance();

conn = DriverManager.getConnection("jdbc:mysql://"+server+"/"+dbase+"?user="+user+"&password="+pass);

return "";

}

catch (SQLException e)

{

return e.getSQLState();

}

catch (Exception e)

{

return "0";

}

}

static boolean disconnect()

{

if (conn != null) {

try

{

conn.close();

return true;

}

catch (SQLException SQLE)

{

return false;

}

}

else

return false;

}

static String execute(String expr)

{

try

{

stmt = null;

stmt = conn.createStatement();

stmt.executeUpdate(expr);

return "";

}

catch (SQLException e)

{

return e.getSQLState();

}

catch (Exception e)

{

return "0";

}

finally

{

if (stmt != null) {

try

{

stmt.close();

}

catch (SQLException SQLE)

{

;

}

}

}

}

static String snapshot2fen (rdgtSnapshot b)

{

StringBuffer s = new StringBuffer(100);

int counter = 0;

for (int i=0; i < 8; i++)

{

for (int j=0; j < 8; j++)

{

if ((counter != 0) && (b.pieces[(i*8)+j] != EMPTY))

{

s.append(counter);

counter = 0;

}

switch(b.pieces[(i*8)+j])

{

case WPAWN:s.append("P"); break;

case WROOK: s.append("R"); break;

case WKNIGHT: s.append("N"); break;

case WBISHOP: s.append("B"); break;

case WKING: s.append("K"); break;

case WQUEEN: s.append("Q"); break;

case BPAWN: s.append("p"); break;

case BROOK: s.append("r"); break;

case BKNIGHT: s.append("n"); break;

case BBISHOP: s.append("b"); break;

case BKING: s.append("k"); break;

case BQUEEN: s.append("q"); break;

default: counter++; break;

}

}

if (counter != 0)

s.append(counter);

s.append("/");

counter = 0;

}

String outfen= s.toString().substring(0,s.toString().length()-1);

switch(b.board.address.intValue()){

case 3737:

case 3811:

case 2896:

case 3740:

case 3588:

case 2897:

default:

rotated=false; break;

}

if(rotated){

String newFen="";

for(int i=outfen.length()-1;i > =0;i-){

newFen += outfen.charAt(i);

}

outfen=newFen;

}

return outfen;

}

static void update_snapshot(rdgtSnapshot b)

{

if (conn != null)

{

String fen = snapshot2fen(b);

String turn;

if(rotated){

if(b.isWhiteTurn()) turn="Black";

else turn="White";

}

else{

if(b.isWhiteTurn()) turn="White";

else turn="Black";

}

String sql_command = "UPDATE "+update_table+" SET fen = '"+fen+"',wtime='"+b.getTimeWhite()+"',btime='"+b.getTimeBlack()+"',turn='"+turn+"' WHERE dgt_active like '%Fen%' AND dgt_board = "+b.board.address;

execute(sql_command);

System.out.println(b.board.address+" "+fen+" "+b.getTimeWhite()+" "+b.getTimeBlack()+" "+turn.substring(0,1));

}

}

static void update_moves(String moves, String movestable, int board_id)

{

if (conn != null)

{

int t=0;

if(moves.length() > 20) t=moves.length()-20;

System.out.println(board_id + " Moves: " + moves.substring(t));

String sql_command = "UPDATE games SET moves = '"+moves+"' WHERE dgt_active like '%Moves%' AND dgt_board = "+board_id;

execute(sql_command);

}

}

}

rdgtProtocol.java

- -

class rdgtProtocol {

static int DGT_TO_BUSMODE = 0x4a;

static int DGT_BUS_SEND_CLK = 0x01 | 0x80;

static int DGT_BUS_SEND_BRD = 0x02 | 0x80;

static int DGT_BUS_SEND_CHANGES = 0x03 | 0x80;

static int DGT_BUS_REPEAT_CHANGES = 0x04 | 0x80;

static int DGT_BUS_SET_START_GAME = 0x05 | 0x80;

static int DGT_BUS_SEND_FROM_START = 0x06 | 0x80;

static int DGT_BUS_PING = 0x07 | 0x80;

static int DGT_BUS_END_BUSMODE = 0x08 | 0x80;

static int DGT_BUS_RESET = 0x09 | 0x80;

static int DGT_BUS_IGNORE_NEXT_BUS_PING = 0x0a | 0x80;

static int DGT_BUS_SEND_VERSION = 0x0b | 0x80;

static int DGT_BUS_BRD_DUMP = 0x03 | 0x80;

static int DGT_BUS_BWTIME = 0x04 | 0x80;

static int DGT_BUS_UPDATE = 0x05 | 0x80;

static int DGT_BUS_FROM_START = 0x06 | 0x80;

static int DGT_BUS_START_GAME_WRITTEN = 0x08 | 0x80;

static int DGT_BUS_VERSION = 0x09 | 0x80;

static boolean is_busmessage(int m) {

return (m== DGT_BUS_BRD_DUMP || m == DGT_BUS_BWTIME ||

m == DGT_BUS_UPDATE || m == DGT_BUS_FROM_START || m == DGT_BUS_PING ||

m == DGT_BUS_START_GAME_WRITTEN || m == DGT_BUS_VERSION);

}

static final int EMPTY = 0x00;

static final int WPAWN = 0x01;

static final int WROOK = 0x02;

static final int WKNIGHT = 0x03;

static final int WBISHOP = 0x04;

static final int WKING = 0x05;

static final int WQUEEN = 0x06;

static final int BPAWN = 0x07;

static final int BROOK = 0x08;

static final int BKNIGHT = 0x09;

static final int BBISHOP = 0x0a;

static final int BKING = 0x0b;

static final int BQUEEN = 0x0c;

boolean is_piece(int p) {

return (p==EMPTY || p==WPAWN || p==WROOK ||

p==WKNIGHT || p==WBISHOP || p==WKING ||

p==WQUEEN || p==BPAWN || p==BROOK ||

p==BKNIGHT || p==BBISHOP || p==BKING ||

p==BQUEEN);

}

static int EE_POWERUP = 0x6a;

static int EE_EOF = 0x6b;

static int EE_FOURROWS = 0x6c;

static int EE_EMPTYBOARD = 0x6d;

static int EE_DOWNLOADED = 0x6e;

static int EE_BEGINPOS = 0x6f;

static int EE_BEGINPOS_ROT = 0x7a;

static int EE_START_TAG = 0x7b;

static int EE_WATCHDOG_ACTION = 0x7c;

static int EE_NOP = 0x7f;

}

rdgtReceiver.java

- -

class rdgtReceiver extends rdgtProtocol {

int messagetype;

int messagelen_msb;

int messagelen_lsb;

int[] data;

int useddata;

int state;

rdgtInterpreter interpreter;

public rdgtReceiver(rdgtInterpreter _interpreter) {

state = 0;

interpreter = _interpreter;

}

void receive(int[] d) {

char c[] = {'0','1','2','3','4','5','6','7','8','9','A','B','C','D','E','F'};

StringBuffer x = new StringBuffer("Received: ");

for (int i=0; i < d.length; i=i+1) {

x.append(c[d[i] > > 4]).append(c[d[i] & 0x0F]).append(" ");

}

if (rdgtChess.debug) System.out.println(x.toString());

_receive (d, 0);

}

void _receive(int[] d, int start) {

if (start == d.length) return;

if (state == 0) { // Find a known messageid.

while (start < d.length) {

if (is_busmessage(d[start])) {

messagetype = d[start];

state = 1;

_receive(d,start+1);

return;

}

System.err.println("Did not understand 1 byte of incoming data.");

start = start + 1;

}

return;

}

if (state == 1) {

if ((d[start] & 0x80) > 0) {

System.err.println("Did not understand 2 bytes of incoming data.");

state = 0;

_receive(d, start);

return;

}

messagelen_msb = d[start];

state = 2;

start = start + 1;

}

if (start == d.length) return;

if (state == 2) {

if ((d[start] & 0x80) > 0) {System.err.println("Did not understand 3 bytes of incoming data.");

state = 0;

_receive(d, start);

return;

}

messagelen_lsb = d[start];

state = 3;

start = start + 1;

int newlen = ((int)messagelen_msb * 0x80) + (int)messagelen_lsb;

if (newlen < 5) {

System.out.println("Too small message length: " + Integer.toString(newlen));

state = 0;

_receive(d, start);

return;

}

data = new int[newlen];

data[0] = messagetype;

data[1] = messagelen_msb;

data[2] = messagelen_lsb;

useddata = 3;

}

if (start == d.length) return;

if (state == 3) {

while (start < d.length && useddata < data.length) {

data[useddata]=d[start];

start = start + 1;

useddata = useddata + 1;

}

if (useddata == data.length) {

interpreter.interpret(data);

start = start + 1;

data = null;

state = 0;}

}

_receive(d, start);

}

}

rdgtSender.java

- -

class rdgtSender extends rdgtProtocol {

rdgtSerialport com;

public rdgtSender(rdgtSerialport _com) {

com = _com;

}

void send(int message, int address) {

String tmp = "Address:"+Integer.toString(address);

System.out.println();

if (message==DGT_TO_BUSMODE) System.out.println("Sending message: SWITCH TO BUSMODE "+tmp);

else if (message==DGT_BUS_SEND_BRD) System.out.println("Sending message: SEND BOARD "+tmp);

else if (message==DGT_BUS_SEND_CHANGES) System.out.println("Sending message: SEND CHANGES "+tmp);

else if (message==DGT_BUS_REPEAT_CHANGES) System.out.println("Sending message: REPEAT CHANGES "+tmp);

else if (message==DGT_BUS_PING) System.out.println("Sending message: PING "+tmp);

else if (message==DGT_BUS_IGNORE_NEXT_BUS_PING) System.out.println("Sending message: IGNORE NEXT PING "+tmp);

else System.out.println("Sending message: (some other message)");

byte x[] = new byte[4];

x[0] = (byte)message;

x[1] = (byte)((address > > 7) & 0x7F);

x[2] = (byte)(address & 0x7F);

x[3] = (byte)(((int)x[0]+(int)x[1]+(int)x[2]) & 0x7F);

com.write(x);

}

}

rdgtSerialport.java

- -

class rdgtSerialport implements SerialPortEventListener {

static CommPortIdentifier portid;

InputStream inStream;

OutputStream outStream;

SerialPort serialPort;

rdgtReceiver receiver;

public rdgtSerialport(rdgtReceiver r) {

receiver = r;

}

public boolean open(String portname) {

CommPortIdentifier id = null;

Enumeration portList;

portList = CommPortIdentifier.getPortIdentifiers();

System.out.println(portList.toString());

while (portList.hasMoreElements()) {

System.out.println("2");

id = (CommPortIdentifier) portList.nextElement();

if (id.getPortType() == CommPortIdentifier.PORT_SERIAL) {

System.out.println("Ports: "+id.getName());

if (id.getName().equals(portname)) break; // found

}

id = null;

}

if (id == null) return false; // not found

try {

serialPort = (SerialPort) id.open("ttchess", 2000);

inStream = serialPort.getInputStream();

outStream = serialPort.getOutputStream();

serialPort.addEventListener(this);

serialPort.notifyOnDataAvailable(true);

serialPort.setSerialPortParams(9600, SerialPort.DATABITS_8,

SerialPort.STOPBITS_1,SerialPort.PARITY_NONE);

serialPort.setDTR(false);

serialPort.setRTS(false);

} catch (Exception e) { return false; }

return true;

}

public boolean write(byte[] data) {

char c[] = {'0','1','2','3','4','5','6','7','8','9','A','B','C','D','E','F'};

StringBuffer x = new StringBuffer(" Sending: ");

for (int i=0; i < data.length; i=i+1) {

int d = data[i];

if (d < 0) d=256+d;

x.append(c[d > > 4]).append(c[d & 0x0F]).append(" ");

}

if (rdgtChess.debug) System.out.println(x.toString());

try {

outStream.write(data);

} catch (IOException e) { return false; }

return true;

}

public void serialEvent(SerialPortEvent event) {

switch(event.getEventType()) {

case SerialPortEvent.OUTPUT_BUFFER_EMPTY:

break;

case SerialPortEvent.DATA_AVAILABLE:

byte[] readBuffer = new byte[200];

try {

while (inStream.available() > 0) {

int numBytes = inStream.read(readBuffer);

if (numBytes > 0) {

int[] buf = new int[numBytes];

for (int i=0; i < numBytes; i=i+1) {

int tmp = readBuffer[i];

if (tmp < 0) tmp=256+tmp;

buf[i]=tmp;

}

receiver.receive(buf);

}

}

} catch (IOException e) {}

break;

}

}

}

rdgtSnapshot.java

- -

class rdgtSnapshot extends rdgtProtocol {

int[] pieces = new int[64];

Date time;

rdgtChessboard board;

boolean clkRunning, clkBatteryLow, clkFrontViewLeftSideHigh, clkBlackTurn, clkWhiteTurn;

int clkSecWhite, clkSecBlack;

public rdgtSnapshot(rdgtChessboard _board) {

time = new Date();

board = _board;

set_emptyboard();

}

public rdgtSnapshot(rdgtSnapshot x) {

for (int i=0; i < 64; i=i+1) pieces[i] = x.pieces[i];

time = x.time;

board = x.board;

clkRunning = x.clkRunning;

clkBatteryLow = x.clkBatteryLow;

clkFrontViewLeftSideHigh = x.clkFrontViewLeftSideHigh;

clkBlackTurn = x.clkBlackTurn;

clkWhiteTurn = x.clkWhiteTurn;

clkSecWhite = x.clkSecWhite;

clkSecBlack = x.clkSecBlack;

}

rdgtSnapshot copy() {

return new rdgtSnapshot(this);

}

void set_clockdata(boolean running, boolean batteryLow, boolean frontViewLeftSideHigh,

boolean blackTurn, boolean whiteTurn, int secW, int secB) {

clkRunning = running;

clkBatteryLow = batteryLow;

clkFrontViewLeftSideHigh = frontViewLeftSideHigh;

clkBlackTurn = blackTurn;

clkWhiteTurn = whiteTurn;

clkSecWhite = secW;

clkSecBlack = secB;

}

public boolean sameas(rdgtSnapshot x) {

for (int i=0; i < 64; i=i+1) if (pieces[i] != x.pieces[i]) return false;

return true;

}

Date get_time() { return time; }

void set_emptyboard() {

time = new Date();

for (int i=0; i < 64; i=i+1) pieces[i]=EMPTY;

}

void set_boarddump(int[] all64, int startpos) {

time = new Date();

for (int i=0; i < 64; i=i+1) {

int p = all64[i+startpos];

if (is_piece(p)==false) {

System.out.println("Confused: Boarddump contained an unknown piece");

pieces[i]=EMPTY;

} else {

pieces[i]=p;

}

}

}

void set_fieldupdate(int piece, int pos) {

time = new Date();

if (pos < 0 || pos > 63) {

System.out.println("Confused: Fieldupdate for pos outside 0..63");

return;

}

if (is_piece(piece)==false) {

System.out.println("Confused: Fieldupdate with an unknown piece");

return;

}

pieces[pos]=piece;

}

String seconds2hms(int s) {

return Integer.toString(s/36000)+Integer.toString((s%36000)/3600)+":"+

Integer.toString((s%3600)/600)+Integer.toString((s%360)/60)+":"+

Integer.toString((s%60)/10)+Integer.toString(s%10);

}

String debugprint_clock() {

StringBuffer s = new StringBuffer(50);

s.append("Clock: White "); s.append(seconds2hms(clkSecWhite));

s.append(" Black "); s.append(seconds2hms(clkSecBlack));

System.out.println(s);

return s.toString();

}

String getTimeWhite(){

return seconds2hms(clkSecWhite);

}

String getTimeBlack(){

return seconds2hms(clkSecBlack);

}

boolean isWhiteTurn(){

return clkFrontViewLeftSideHigh;

}

String debugprint() {

debugprint_clock();

StringBuffer s = new StringBuffer(300);

for (int i=0; i < 8; i=i+1) {

for (int j=0; j < 8; j=j+1) {

int p = pieces[(i*8)+j];

if (p==EMPTY) s.append(".");

if (p==WPAWN) s.append("P");

if (p==WROOK) s.append("R");

if (p==WKNIGHT) s.append("N");

if (p==WBISHOP) s.append("B");

if (p==WKING) s.append("K");

if (p==WQUEEN) s.append("Q");

if (p==BPAWN) s.append("p");

if (p==BROOK) s.append("r");

if (p==BKNIGHT) s.append("n");

if (p==BBISHOP) s.append("b");

if (p==BKING) s.append("k");

if (p==BQUEEN) s.append("q");

}

s.append("\n");

}

System.out.println(s);

return s.toString();

}

}

Додаток Д

Знімки екрана

Д.1 Знімок екрана головної сторінки сервера трансляції шахових партій rDGT

Д.2 Знімок екрана сторінки авторизації користувача

Д.3 Знімок екрана сторінки перегляду поточних online трансляций

Д.4 Знімок екрана сторінки перегляду шахової партії

Додаток Е

Протокол DGT

#ifndef dgtbrd13

#define dgtbrd13

/*

Protocol description for DGT chess board.

Copyright 1998 DGT Projects B.V

Version: 1.03 Single computer and bus support in one .h file

*********************************************************

This protocol is protected under trade mark registration and copyrights.

It may not be used commercially without written permission

of DGT Projects B.V. It is illegal to transfer any registered trade mark

identifications by means of this protocol between any chessboard or other

application and any computer.

*********************************************************

Main functionality of the DGT Electronic Chess Board

- -

The DGT board is basically a sensor which senses the presense of the special

chess set pieces on the squares of the board. The situation on the board is

measured and can be communicated with an average maximum time delay of

200 mS.

Besides this detection function, the board communicates with an optional

DGT TopMatch Chess Clock, to give the data of the clock available to the

general interface.

Finally the board is equipped with an internal storage of the measured

piece positions.

The board supports two methods of communication: for single-board situations

a protocol for communication between one board and one computer is available.

For situations with many boards a network communications protocol is

available, where many boards can be connected in a bus structure. A separate

communication protocol is available for this bus structure.

The communication protocol for single board connections is described

in the following paragraph "Single board communication protocol". This

paragraph describes much more than only the communication protocol. All

developers should read this paragraph, even if they would only use bus

communication.

The special bus communication protocol is derived from the single board

communication and functionality, where the main added feature is the

possibility to address a specific board on a shared communication bus.

The commands and data contens are described in the paragraph "Bus

Communication Protocol", Note however that the contens can not be understood

without reading the single board communication paragraph.

Paragraph: Single board communication protocol

- -

The main function of the board is to transfer piece position information.

For this, three modes are available:

1. IDLE mode. This cancelles any of the two UPDATE modes. No automatic

transfer of moves.

2. UPDATE_BOARD mode. On the moment that the board detects a removal, change

or placing of a piece, it outputs a DGT_SEND_UPDATE message

3. UPDATE mode. As UPDATE_BOARD mode, where additional the clock data are send

regularly (at least every second)

The board accepts command codes from the computer RS232. The commands are

1-byte codes, sometimes followed by data (see code definition)

The board can send data to the computer. Data always carries a message header.

The message header contains a message code and the total message size in bytes.

The start of the incoming message can be recognised by the MSB of the message

identifier set to 1 (see definition).

Board to computer communication interfaces:

RS232 for communication with computer, receiving commands, sending data

- 9600 Baud, 1 stopbit, 1 startbit, no parity

- No use of handshaking, neither software nor hardware

Connection between Digital Game Timer TopMatch Clock and the board:

Based on NEC SBI protocol. Adaption of the definition given in

the DGT TopMatch documentation.

Connector assignments for DGT Electronic Board: See User

and Programmers Manual

Related to the before mentioned modes, and to piece position information

transfer, the following commands to the board are available:

1. DGT_SEND_RESET

puts the DGT Board in IDLE mode

2. DGT_SEND_CLK

on which the DGT board responds with a DGT_MSG_BWTIME message containing clock

information

3. DGT_SEND_BRD

on which the DGT Board responds with a DGT_MSG_BOARD_DUMP message containing

the actual piece exising of all fields

4. DGT_SEND_UPDATE puts the DGT Board in the UPDATE mode, FRITZ5 compatible

5. DGT_SEND_UPDATE_BRD puts the DGT Board in the UPDATE_BOARD mode

6. DGT_SEND_UPDATE_NICE puts the board in UPDATE mode, however transferring only clocktimes when any time info changed.

The DGT_SEND_CLK command and the DGT_SEND_BOARD command do not affect the current board

mode: i.e. when in UPDATE mode, it continues sending DGT_SEND_UPDATE messages.

Board Identification:

Each DGT Electronic Board carries a unique serial number,

a EEPROM configuration version number and a embedded program version number.

These data are unalterable by the users.

Current identification is:

"DGT Projects - This DGT board is produced by DGT Projects.\n

DGT Projects is a registered trade mark.\n

220798 ISP/bus/8KP/8KE/P6/Fritz5 Vs 1.00. Serial nr. 00137 1.0"

The board can be loaded by the user with a non-volatile one-byte bus number,

for future use with multiple board configurations.

On-board EEPROM:

The board carries a 8 kB cyclic non-volatile memory, in which all position

changes and clock information is stored during all power-up time. This

file can be read and processed.

Start of Definitions:

- -*/

/* COMMAND CODES FROM PC TO BOARD: */

/* resulting in returning message(s): */

#define DGT_SEND_CLK 0x41

/* results in a DGT_MSG_BWTIME message */

#define DGT_SEND_BRD 0x42

/* results in a DGT_MSG_BOARD_DUMP message */

#define DGT_SEND_UPDATE 0x43

/* results in DGT_MSG_FIELD_UPDATE messages and DGT_MSG_BWTIME messages

as long as the board is in UPDATE mode */

#define DGT_SEND_UPDATE_BRD 0x44

/* results in DGT_MSG_FIELD_UPDATE messages

as long as the board is in UPDATE_BOARD mode */

#define DGT_RETURN_SERIALNR 0x45

/* results in a DGT_MSG_SERIALNR message */

#define DGT_RETURN_BUSADRES 0x46

/* results in a DGT_MSG_BUSADRES message */

#define DGT_SEND_TRADEMARK 0x47

/* results in a DGT_MSG_TRADEMARK message */

#define DGT_SEND_VERSION 0x4d

/* results in a DGT_MSG_VERSION message */

#define DGT_SEND_UPDATE_NICE 0x4b

/* results in DGT_MSG_FIELD_UPDATE messages and DGT_MSG_BWTIME messages,

the latter only at time changes,

as long as the board is in UPDATE_NICE mode*/

#define DGT_SEND_EE_MOVES 0x49

/* results in a DGT_MSG_EE_MOVES message */

/* not resulting in returning messages: */

#define DGT_SEND_RESET 0x40

/* puts the board in IDLE mode, cancelling any UPDATE mode */

/* DESCRIPTION OF THE MESSAGES FROM BOARD TO PC

A message consists of three header bytes:

MESSAGE ID one byte, MSB (MESSAGE BIT) always 1

MSB of MESSAGE SIZE one byte, MSB always 0, carrying D13 to D7 of the total message length, including the 3 header byte

LSB of MESSAGE SIZE one byte, MSB always 0, carrying D6 to D0 of the

total message length, including the 3 header bytes

followed by the data:

0 to ((2 EXP 14) minus 3) data bytes, of which the MSB is always zero.

*/

/* DEFINITION OF THE BOARD-TO-PC MESSAGE ID CODES and message descriptions */

/* the Message ID is the logical OR of MESSAGE_BIT and ID code */

#define MESSAGE_BIT 0x80

/* ID codes: */

#define DGT_NONE 0x00

#define DGT_BOARD_DUMP 0x06

#define DGT_BWTIME 0x0d

#define DGT_FIELD_UPDATE 0x0e

#define DGT_EE_MOVES 0x0f

#define DGT_BUSADRES 0x10

#define DGT_SERIALNR 0x11

#define DGT_TRADEMARK 0x12

#define DGT_VERSION 0x13

/* Macros for message length coding (to avoid MSB set to 1) */

#define BYTE char

#define LLL_SEVEN(a) ((BYTE)(a&0x7f)) /* 0000 0000 0111 1111 */

#define LLH_SEVEN(a) ((BYTE)((a & 0x3F80) > > 7)) /* 0011 1111 1000 0000 */

/* DGT_MSG_BOARD_DUMP is the message that follows on a DGT_SEND_BOARD

command */

#define DGT_MSG_BOARD_DUMP (MESSAGE_BIT|DGT_BOARD_DUMP)

#define DGT_SIZE_BOARD_DUMP 67

/* message format:

byte 0: DGT_MSG_BOARD_DUMP

byte 1: LLH_SEVEN(DGT_SIZE_BOARD_DUMP) (=0 fixed)

byte 2: LLL_SEVEN(DGT_SIZE_BOARD_DUMP) (=67 fixed)

byte 3-66: Pieces on position 0-63

Board fields are numbered from 0 to 63, row by row, in normal reading

sequence. When the connector is on the left hand, counting starts at

the top left square. The board itself does not rotate the numbering,

when black instead of white plays with the clock/connector on the left hand.

In non-rotated board use, the field numbering is as follows:

Field A8 is numbered 0

Field B8 is numbered 1

Field C8 is numbered 2

..

Field A7 is numbered 8

..

Field H1 is numbered 63

So the board always numbers the black edge field closest to the connector

as 57.

Piece codes for chess pieces: */

#define EMPTY 0x00

#define WPAWN 0x01

#define WROOK 0x02

#define WKNIGHT 0x03

#define WBISHOP 0x04

#define WKING 0x05

#define WQUEEN 0x06

#define BPAWN 0x07

#define BROOK 0x08

#define BKNIGHT 0x09

#define BBISHOP 0x0a

#define BKING 0x0b

#define BQUEEN 0x0c

#define PIECE1 0x0d /* future use: pointing device in rest */

#define PIECE2 0x0e /* future use: pointing device right button */

#define PIECE3 0x0f /* future use: pointing device left button */

/* message format DGT_MSG_BWTIME */

#define DGT_MSG_BWTIME (MESSAGE_BIT|DGT_BWTIME)

#define DGT_SIZE_BWTIME 10

/*

byte 0: DGT_MSG_BWTIME

byte 1: LLH_SEVEN(DGT_SIZE_BWTIME) (=0 fixed)

byte 2: LLL_SEVEN(DGT_SIZE_BWTIME) (=10 fixed)

byte 3:

D4: 1 = Flag fallen for left player, and clock blocked to zero

0 = not the above situation

D5: 1 = Time per move indicator on for left player (i.e. Bronstein, Fischer)

0 = Time per move indicator off for left player

D6: 1 = Left players flag fallen and indicated on display

0 = not the above situation

(D7 is MSB)

D0-D3: Hours (units, 0-9 Binary coded) white player (or player at the A side of the board)

byte 4: Minutes (0-59, BCD coded)

byte 5: Seconds (0-59, BCD coded)

byte 6-8: the same for the other player

byte 9: Clock status byte: 7 bits

D0 (LSB): 1 = Clock running

0 = Clock stopped by Start/Stop

D1: 1 = tumbler position high on (white) player (front view: \ , left side high)

0 = tumbler position high on the other player (front view: /, right side high)

D2: 1 = Battery low indication on display

0 = no battery low indication on display

D3: 1 = Black players turn

0 = not black players turn

D4: 1 = White players turn

0 = not white players turn

D5: 1 = No clock connected; reading invalid

0 = clock connected, reading valid

D6: not used (read as 0)

D7: Always 0

The function of the information bits are derived from the full information

as described in the programmers reference manual for the DGT TopMatch

*/

/* message format DGT_MSG_FIELD_UPDATE: */

#define DGT_MSG_FIELD_UPDATE (MESSAGE_BIT|DGT_FIELD_UPDATE)

#define DGT_SIZE_FIELD_UPDATE 5

/*

byte 0: DGT_MSG_FIELD_UPDATE

byte 1: LLH_SEVEN(DGT_SIZE_FIELD_UPDATE) (=0 fixed)

byte 2: LLL_SEVEN(DGT_SIZE_FIELD_UPDATE) (=5 fixed)

byte 3: field number (0-63) which changed the piece code

byte 4: piece code including EMPTY, where a non-empty field became empty

*/

/* message format: DGT_MSG_TRADEMARK which returns a trade mark message */

#define DGT_MSG_TRADEMARK (MESSAGE_BIT|DGT_TRADEMARK)

/*

byte 0: DGT_MSG_TRADEMARK

byte 1: LLH_SEVEN(DGT_SIZE_TRADEMARK)

byte 2: LLL_SEVEN(DGT_SIZE_TRADEMARK)

byte 3-end: ASCII TRADEMARK MESSAGE, codes 0 to 0x3F

The value of DGT_SIZE_TRADEMARK is not known beforehand, and may be in the

range of 0 to 256

Current trade mark message: ...

*/

/* Message format DGT_MSG_BUSADRES return message with bus adres */

#define DGT_MSG_BUSADRES (MESSAGE_BIT|DGT_BUSADRES)

#define DGT_SIZE_BUSADRES 5

/*

byte 0: DGT_MSG_BUSADRES

byte 1: LLH_SEVEN(DGT_SIZE_BUSADRES)

byte 2: LLL_SEVEN(DGT_SIZE_BUSADRES)

byte 3,4: Busadres in 2 bytes of 7 bits hexadecimal value

Byte 3: 0bbb bbbb with bus adres MSB 7 bits

byte 4: 0bbb bbbb with bus adres LSB 7 bits

The value of the 14-bit busadres is het hexadecimal representation

of the (decimal coded) serial number

i.e. When the serial number is "01025 1.0" the busadres will be

byte 3: 0000 1000 (0x08)

byte 4: 0000 0001 (0x01)

*/

/* Message format DGT_MSG_SERIALNR return message with bus adres */

#define DGT_MSG_SERIALNR (MESSAGE_BIT|DGT_SERIALNR)

#define DGT_SIZE_SERIALNR 12

/* returns 5 ASCII decimal serial number + space + 3 byte version string: */

/* byte 0-5 serial number string, sixth byte is LSByte */

/* byte 6: space */

/* byte 7-9: Internal storage version nr: format "1.0" */

/* Message format DGT_MSG_EE_MOVES, which is the contens of the storage array */

/* Message format DGT_MSG_VERSION return message with bus adres */

#define DGT_MSG_VERSION (MESSAGE_BIT|DGT_VERSION)

#define DGT_SIZE_VERSION 5

/*

byte 0: DGT_MSG_VERSION

byte 1: LLH_SEVEN(DGT_SIZE_VERSION)

byte 2: LLL_SEVEN(DGT_SIZE_VERSION)

byte 3,4: Version in 2 bytes of 7 bits hexadecimal value

Byte 3: 0bbb bbbb with main version number MSB 7 bits

byte 4: 0bbb bbbb with sub version number LSB 7 bits

The value of the version is coded in binary

i.e. When the number is "1.02" the busadres will be

byte 3: 0000 0001 (0x01)

byte 4: 0000 0010 (0x02)

*/

#define DGT_MSG_EE_MOVES (MESSAGE_BIT|DGT_EE_MOVES)

/* DGT_SIZE_EE_MOVES is defined in dgt_ee1.h: current (0x2000-0x100+3) */

/*

message format:

byte 0: DGT_MSG_EE_MOVES

byte 1: LLH_SEVEN(DGT_SIZE_EE_MOVES)

byte 2: LLL_SEVEN(DGT_SIZE_EE_MOVES)

byte 3-end: field change storage stream: See defines below for contens

The DGT_MSG_EE_MOVES message contains the contens of the storage,

starting with the oldest data, until the last written changes, and will

always end with EE_EOF

*/

/*

Description of the EEPROM data storage and dump format

- -

General: The internal EEPROM storage can be seen as a cyclic buffer with length

0x1f00 bytes, with one pointer, pointing to the last written byte in the buffer.

Only at this pointer location, data can be written, incrementing the pointer.

The written data always overwrites the oldest data.

In this buffer, sequentially messages are written. The messages are of various

length, from 1 byte to 5 bytes, specific for every message.

Various events generate a message that is written in the storage, in the

sequence as the events occur. When the buffer is downloaded and read, the event

messages can be found, starting with the oldest event, and the latest event in

the end of the buffer, followed by EE_EOF.

- At power-on, three tags EE_NOP are written, followed by a one-byte

EE_POWERUP message.

After this, an UPDATE_BOARD message is written (in virtually random sequence)

for every piece that is found on the board, at power-on.

When the board is equipped with a watchdog timer, and the watchdog times out,

an EE_WATCHDOG_ACTION is written and after that, the above described power-up

procedure takes place.

- When at any time a normal starting position for chess is found, with the

player for white having the board connector on his left hand, an EE_BEGINPOS tag

is written, and an EE_BEGINPOS_ROT tag is written when white has the

connector at his right hand (rotated)

- When 16 chess figures are found on the board, all in the A, B, G and H row,

which are not(!) in a normal chess starting position, the one-byte

EE_FOURROWS message is written, to be tolerant on erroneous placement and i.e. to be able to play the "Random Chess" as proposed by Bobby

Fischer. The exact position of the pieces has to be analyzed on the context: or found in the previous piece move messages, or found in the

coming piece move messages.

When an empty board is detected, the one-byte EE_EMPTYBOARD message is

written.

The above described detection of begin positions or empty-board has a certain

hysteresis: only after more than two pieces have been out of the begin

positions the search for begin positions is restarted, resulting in possibly

new tag writing. This to avoid flushing the buffer full with data, only because

of one bad positioned and flashing piece.

When the data of the internal storage are sent upon reception of the

DGT_SEND_EE_MOVES command, the one-byte EE_DOWNLOADED message is sent

On every detected change of piece positions this change is written to EEPROM

in a 2-byte message, which cover exactly the same data as is sent to the PC

in the UPDATE_BOARD mode.

The formatting of the 2-byte piece update tag is:

First byte: 0t0r nnnn (n is piece code, see before)

(piece code EMPTY when a piece is removed)

(t is recognition bit, always 1)

(r is reserved)

so the first byte of this tag is always in the

range 0x40 to 0x5f

Second byte: 00ii iiii (i = 0 to 63 (0x3f), the field number as

defined before)

NB: when one piece only is changing, the new value is overwrites the

piece update field described above, instead of generating a new message

in the internal storage.

The same kind of optimization is included for begin-position tags:

a EE_BEGINPOS or EE_BEGINPOS_ROT or EE_FOURROWS is not written, when

between the previous written tags and the new occurence of the begin-

situation only 2 or 1 piece were out of the tagged beginsituation.

On the pressing of the clock, the time of the halted clock is written in

a time message. It might be that when the moves are done very fast, the

storage is skipped. Note: the two clock sides are identified only by

left and right side of the clock: When the board is swapped, the clock

data are not (!) swapped.

The clock data are written on tumbler position change, so at the beginning

of the game, the game starting times will be lost.

Format of a three-byte time message:

First byte: 0uuf hhhh (f=1 for time in left clock screen, seen from the front)

(hhhh: hours, valued 0 to 9)

(uu recognition bits, both 1, so byte 0 has the

(value range of 0x60 to 0x69, or 0x70 to 0x79)

Second byte: 0MMM mmmm (MMM: Tens of minutes (range 0 to 5),

(mmmm: minute units, range 0 to 9)

Third byte: 0SSS ssss (SSS: tens of seconds, range 0-5)

(ssss: seconds units, range 0-9)

On the recognition of the first byte of a message: The above definitions

imply that the first byte of a message is always ranged

from 40-5f for a field change message, 60-69 or 70-79 for a time message,

and 6a to 6f, or 7a to 7f for a 1-byte message.

(all values hexadecimal)

*/

/* Definition of the one-byte EEPROM message codes */

#define EE_POWERUP 0x6a

#define EE_EOF 0x6b

#define EE_FOURROWS 0x6c

#define EE_EMPTYBOARD 0x6d

#define EE_DOWNLOADED 0x6e

#define EE_BEGINPOS 0x6f

#define EE_BEGINPOS_ROT 0x7a

#define EE_START_TAG 0x7b

#define EE_WATCHDOG_ACTION 0x7c

#define EE_NOP 0x7f

/* 7d and 7e reserved for future use*/

/*

Notes on the communication dynamics:

The squares of the board are sampled one by one, where a full scan takes

about 200-250 ms. Due to this scan time, it can be, that a piece that is

moved from square e.g. A2 to A3 can be seen on both squares, in the same

scan. On a next scan of course, the old position is not seen anymore.

When in UPDATE mode, this means, that the information on changes on the

squares can come in opposite sequence: first the new occurence is reported,

then the clearing of the old position is sent.

When a piece B on C4 is taken by piece A on B3, it can be that the following

changes are reported:

A on C4

Empty on B3

(and Empty on C4 is never seen)

An other extreme situation can occur e.g. when a queen on C1 takes a pawn

on C4. The reported changes can be (in sequence):

Empty on C4 (the pawn is taken by one hand)

Queen on C2

Queen on C3

Empty on C1

Empty on C2

Queen on C4

Empty on C3

For writing software it is important to take these dynamics into account.

Some effort needs to be made to reconstruct the actual moves of the pieces.

See also the programmers and users manual

Paragraph: Bus communication protocol

- -

Differencens between busmode and single board mode:

* In bus mode, RS232 input and RS232 output are connected to all boards.

The RS232 output of the board is configured as a pull-up driver: with a

pull-down resistor on the RS232 pull-up line. Now all boards receive all

commands from the computer, and can all send data to the computer.

* In single board mode the board has a small incoming commands

buffer (10 bytes).

* The bus mode has only a one-command incoming commands buffer

* When entered in single board mode, the board status always switches to IDLE:

changes are not send automatically

Bus mode is default power up mode of the board. The board recognises

bus commands from the start.

However, single board commands are recognised and answered.

The board switches to single board mode on the moment, a single board

command is recognised. Switching back to bus mode is invoked by the

extra command DGT_TO_BUSMODE or by sending a busmode command. (NB This

busmode command causing the swithing is not processed!)

For all detailed hardware descriptions: call.

*/

/* one added functon for swiching to busmode by command: */

#define DGT_TO_BUSMODE 0x4a

/*

This is an addition on the other single-board commands. This command is

recognised in single-board mode. The RS232 output goes in

pull-up mode and bus commands are immediatly recognised hereafter.

Note that when the board is in single-board mode, and eventually a bus

mode command is found, this command is not processed, but the board

switches to bus mode. The next (bus) command is processed regularly.*/

/* Bus mode commands: */

#define DGT_BUS_SEND_CLK (0x01 | MESSAGE_BIT)

#define DGT_BUS_SEND_BRD (0x02 | MESSAGE_BIT)

#define DGT_BUS_SEND_CHANGES (0x03 | MESSAGE_BIT)

#define DGT_BUS_REPEAT_CHANGES (0x04 | MESSAGE_BIT)

#define DGT_BUS_SET_START_GAME (0x05 | MESSAGE_BIT)

#define DGT_BUS_SEND_FROM_START (0x06 | MESSAGE_BIT)

#define DGT_BUS_PING (0x07 | MESSAGE_BIT)

#define DGT_BUS_END_BUSMODE (0x08 | MESSAGE_BIT)

#define DGT_BUS_RESET (0x09 | MESSAGE_BIT)

#define DGT_BUS_IGNORE_NEXT_BUS_PING (0x0a | MESSAGE_BIT)

#define DGT_BUS_SEND_VERSION (0x0b | MESSAGE_BIT)

// extra return headers for bus mode:

#define DGT_MSG_BUS_BRD_DUMP (0x03 | MESSAGE_BIT)

#define DGT_MSG_BUS_BWTIME (0x04 | MESSAGE_BIT)

#define DGT_MSG_BUS_UPDATE (0x05 | MESSAGE_BIT)

#define DGT_MSG_BUS_FROM_START (0x06 | MESSAGE_BIT)

#define DGT_MSG_BUS_PING (0x07 | MESSAGE_BIT)

#define DGT_MSG_BUS_START_GAME_WRITTEN (0x08 | MESSAGE_BIT)

#define DGT_MSG_BUS_VERSION (0x09 | MESSAGE_BIT)

// extra defines for bus length info:

#define DGT_SIZE_BUS_PING 6

#define DGT_SIZE_BUS_START_GAME_WRITTEN 6

#define DGT_SIZE_BUS_VERSION 8 // was 6 up to version 1.2

/* Definition of different commands&data

All commands DGT_BUS_xx have the following format:

byte 1: command, i.e. DGT_BUS_SEND_BDR (D7 always 1)

byte 2: MSB of addressed board (D7 always 0)

byte 3: LSB of addressed board (D7 always 0)

byte 4: checksum: this is the sum of all bytes from start of the message

upto the last byte before the checksum. (D7 always 0)

I.e. message code 0x81 0x10 0x06 will carry checksum byte 0x17

DGT_BUS_SEND_CLK

asks for clock information of addressed board.

Will result in a DGT_MSG_BUS_BWTIME message from the board.

DGT_BUS_SEND_BRD

asks for a board dump of addressed board.

Will result in a DGT_MSG_BUS_BRD_DUMP message from the board.

DGT_BUS_SEND_CHANGES

asks for all stored information changes from the moment of the last

DGT_BUS_SEND_CHANGES. Will result in a DGT_MSG_BUS_UPDATE message from

the board.

In case these data do not arrive properly, the data can be asked again

with the DGT_BUS_REPEAT_CHANGES command.

DGT_BUS_REPEAT_CHANGES

Causes the board to send last sent packet of changes again.

DGT_BUS_SET_START_GAME

sets an EE_START_TAG tag in the internal board changes buffer, for use in the

following command DGT_BUS_SEND_FROM_START. After this EE_START_TAG the

positions of the pieces are all logged in the file.

The command is answered with a DGT_MSG_BUS_START_GAME_WRITTEN message,

about 70 msec. after receipt of DGT_BUS_SET_START_GAME

DGT_BUS_SEND_FROM_START

causes the board to send a DGT_MSG_BUS_FROM_START message, containing

all update information starting with EE_START_TAG until the last registered

changes (excluding the moves that are to be sent with the DGT_BUS_SEND_CHANGES

command). Remember that after the EE_START_TAG all piece positions are written

in the eeprom file.

DGT_BUS_PING

causes the addressed board to send a DGT_MSG_BUS_PING message.

NB: when the DGT_BUS_PING command is sent with board address 0 (zero)

all connected boards will reply with a DGT_MSG_BUS_PING message, randomly

spread over a 1100 msec. interval. This to avoid collision. For reliable

identification of all connected boards, this process should be repeated

sometimes with checking of checksums!

DGT_IGNORE_NEXT_BUS_PING

is used in the process of detecting connected boards on a bus. After this

command (which itself sends a DGT_MSG_BUS_PING as handshake) the first

following DGT_BUS_PING with address zero (!) is ignored. This command

can be used to suppress response of already detected boards, and decreases

the chance of bus collisions.

This command responds immediately with a DGT_MSG_BUS_PING.

DGT_BUS_END_BUSMODE

causes the board to quit busmode, and go into single-connection mode.

Be careful not to use this command in a multiple board configuration!

NOTE: Any single-board command arriving during bus mode will

switch a board to single-board mode and will be processed. When sent

with address 0 the command is processed on all connected boards

DGT_BUS_RESET

forces a power-up reset procedure. NB: this procedure takes some seconds.

When sent with address 0 the command is processed on all conected boards

DEFINITION OF THE MESSAGE DATA FORMATS FROM BOARD TO PC

- -

General: the message format is:

byte 1: message type byte (MSB = 1)

byte 2: message length MSB (from byte 1 to checksum) (D7=0)

byte 3: message length LSB (containing D0 to D6 of the length (D7 = 0)

byte 4: board address MSB (D7=0)

byte 5: board address LSB (D7=0)

< data bytes: 0 to theoretically 16K-6 bytes >

last byte: checksum. This is the sum of all byte values from byte 1 to

the byte before this checksum. D7 is forced to 0

DGT_MSG_BUS_BRD_DUMP

the data area contains the piece codes from field 1 to field 64, in format

identical as the single board command

DGT_MSG_BUS_BWTIME

the data area contains the clock time information, in format identical as

the single board command

DGT_MSG_BUS_UPDATE

the data area contains a variable amount of change information, formatted

as described in the DGT_DUMP_EEMOVES message

DGT_MSG_BUS_FROM_START

the data area contains a variable amount of change information, formatted

as described in the DGT_DUMP_EEMOVES message

DGT_MSG_BUS_PING

the data area is empty: a message of 6 bytes is returned.

DGT_MSG_BUS_START_GAME_WRITTEN

The same format as for DGT_MSG_BUS_PING

DGT_MSG_BUS_VERSION

The two data bytes contain binary version number: first byte main number

second byte sub number.

Tips for usage of the bus mode:

A. On connection of power and starting of the communication process:

- Check communication with addressed DGT_BUS_PING commands to all expected

boards.

LOOP:

- Send DGT_BUS_IGNORE_NEXT_PING to all found boards

- Check eventually extra boards or unknown board busnumbers by using

a DGT_BUS_PING with address zero.

- Register the found boards, and go to LOOP:, until no more boards are found

B. At the start of an event: when all boards have pieces in starting

position, send DGT_BUS_SET_START_GAME commands to all boards.

- Read full clock times from all boards.

C. During a game: send DGT_BUS_SEND_CHANGES to all boards sequentially,

once every few seconds. The returned data should logically match

with the expected piece positions. When any mismatch occurs: ask full

position with DGT_BUS_SEND_BRD.

D. When previous data are lost: send a DGT_BUS_SEND_FROM_START command

which returns the full registered changes from the starting position.

On every sent message: The responce time at the board is within milliseconds

normally, except when the board is storing a measured change in the

internal EEPROM: Then the responce time can be up to 20 milliseconds.

So allow a time-out on sent messages of say 80 mS.

Checksum errors: when a received checksum does not match, resend the command

except on the DGT_BUS_SEND_CHANGES: then the command DGT_BUS_REPEAT_CHANGES

should be used, to avoid discarding of the changes sent by the board.

On clock data:

- reading data out of the clock and make them available

for communication causes a delay of up to 1 second between clock display

and received data.

*/

#endif

Приложениеж

Загальна структура транслятора шахових партій

Додаток З

Загальна структура реєстратора шахових партій

Додаток И

Аналіз результатів тестових іспитів

№ п/п

Показник

Абсолютний

кількісний показник

Відносний кількісний показник у %

Ступінь відповідності умовам соревновательного процесу

(суб'єктивна оцінка головного арбітра змагань)

1

Кількість збоїв у роботі СШПО в ході усього сорев-новательного про-цесса

0

-

ЦІЛКОМ ВІДПОВІДАЄ

2

Кількість вре-менних простоїв у роботі СШПО в ході усього сорев-новательного про-цесса

0

-

ЦІЛКОМ ВІДПОВІДАЄ

3

Кількість несоот-ветствий отобража-емого ходу ходу, зробленому на ша-хматной дошці

5

0,48

ЦІЛКОМ ВІДПОВІДАЄ

4

Кількість вре-менних затримок у ході відображення ігрового процесу

1

0,01

ЦІЛКОМ ВІДПОВІДАЄ

5

Кількість вре-менних затримок переносу шахмат-них партій у елек-тронную форму

1

0,01

ЦІЛКОМ ВІДПОВІДАЄ

Директор СП "ШК" Амзоров А. М.

Головний арбітр змагань Федоров В. Н.

Додаток ДО

Листинг модуля віщання шахових партій

// Фігура

var Figure = {

create: function(color, type, vertical) {

function figure() {}

var self = new figure();

self.id = color + type + vertical;

self.image = document.createElement('img');

self.image.src = get_image_path() + (color + type + '.gif').toLowerCase();

self.image.size = '8x8';

return self;

}

};

// Поледоски

var Field = {

create: function(vertical, horizontal) {

function field() {}

var self = new field();

// Ідентифікатор полючи, відповідає осередку в таблиці, що є шахівницею

self.id = "field" + vertical + horizontal;

self.horizontal = horizontal;

self.vertical = vertical;

self.cell = $(self.id);

//

function v(letter) {

letter = letter.toLowerCase();

if(letter == 'a') {

return 1;

}

if(letter == 'b') {

return 2;

}

if(letter == 'c') {

return 3;

}

if(letter == 'd') {

return 4;

}

if(letter == 'e') {

return 5;

}

if(letter == 'f') {

return 6;

}

if(letter == 'g') {

return 7;

}

if(letter == 'h') {

return 8;

}

return 0;

}

var vv = v(self.vertical);

var hh = parseInt(self.horizontal);

function isWhite(summa) {

var is_white = (summa / 2) - (Math.floor(summa / 2)) == 0;

//log(summa + ' - ' + is_white);

return !is_white;

}

self.cell.className = isWhite(vv + hh) ? 'board_white_field' : 'board_black_field';

self.set_figure = function(figure) {

if(figure == null) {

log('null in ' + self.id);

}

self.delete_figure();

self.cell.appendChild(figure.image);

self.current_figure = figure;

}

self.init_figure = function(figure) {

self.set_figure(figure);

self.first_figure = figure;

self.last_figure = figure;

}

self.delete_figure = function() {

this.cell.innerHTML = "";

}

self.first_figure = null;

self.current_figure = null;

self.last_figure = null;

return self;

}

};

// Ходшахматнойпартии

var Move = {

create: function() {

function move() {}

var self = new move();

self.color = '';

self.next = null;

self.prev = null;

self.number = 0;

self.field_from = null;

self.field_to = null;

self.figure = null;

self.figure_dead = null;

self.is_short_castling = false;

self.is_long_castling = false;

self.forward = function() {

if(self.is_short_castling || self.is_long_castling) {

self.field_from[0].delete_figure();

self.field_from[1].delete_figure();

self.field_to[0].set_figure(self.figure[0]);

self.field_to[1].set_figure(self.figure[1]);

} else {

self.field_from.delete_figure();

self.field_to.set_figure(self.figure);

}

}

return self;

}

};

var Chess = {

version: "2.0",

refresh_delay: 2, // інтервал часу між відновленнями позиції в секундах

repaint_delay: 0.5, // інтервал часу між перемальовуваннями позиції в секундах

moves: '/main/game_moves/1',

createBoard: function() {

var board = Board.create();

board.init();

return board;

},

createField: function(vertical, horizontal) {

var self = Field.create(vertical, horizontal);

return self;

},

createFigure: function(color, type, vertical) {

var self = Figure.create(color, type, vertical);

return self;

},

createMove: function() {

var self = Move.create();

return self;

}

};

// Шахматнаядоска

var Board = {

create: function() {

function board() { }

var self = new board();

self.white_number = 0;

self.black_number = 0;

self.first_move = null;

self.current_move = null;

self.last_move = null;

// Можуть бути стану

// listen - стежити за ходом партій, відображаються актуальні ходи

// custom - спостерігач вибрав довільну позицію в партії і навигирует по партії вільно

self.status = 'listen';

self.fields = new Array(64);

self.figures = new Array(32);

self.all_moves = '';

// Відновлення позиції

self.refresh = function() {

function existsMove(color, annotation) {

var move = getMove(color, annotation);

var exists = move != "******" && move != "";

return exists;

}

function getMove(color, annotation) {

var m = annotation.substring(color == 'w' ? 0 : 6, color == 'w' ? 6 : 12);

return m;

}

function isCastling(color, type, annotation) {

var move = getMove(color, annotation);

var castling = (type == 'short' ? move.substring(0, 3) == 'O-O' : move.substring(0, 5) == 'O-O-O');

return castling;

}

function getField(is_short, is_long, target, color, annotation) {

if(is_short || is_long) {

if(color == 'w') {

if(is_short) {

return new Array(self.fields[target == 'from' ? 4 : 6], self.fields[target == 'from' ? 7 : 5]);

}

if(is_long) {

return new Array(self.fields[target == 'from' ? 4 : 2], self.fields[target == 'from' ? 0 : 3]);

}

}

if(color == 'b') {

if(is_short) {

return new Array(self.fields[target == 'from' ? 60 : 62], self.fields[target == 'from' ? 63 : 61]);

}

if(is_long) {

return new Array(self.fields[target == 'from' ? 60 : 58], self.fields[target == 'from' ? 56 : 59]);

}

}

}

var field = annotation.substring(color == 'w' ? (target == 'from' ? 1 : 4) : (target == 'from' ? 7 : 10), color == 'w' ? (target == 'from' ? 3 : 6) : (target == 'from' ? 9 : 12));

var v = field.substring(0, 1).toLowerCase();

var h = field.substring(1, 2).toLowerCase();

//log('getField: v ' + v + ' h: ' + h);

var iField = (parseInt(h) - 1) * 8;

//log('tmp ' + iField);

if(v == 'b') {

iField += 1;

}

if(v == 'c') {

iField += 2;

}

if(v == 'd') {

iField += 3;

}

if(v == 'e') {

iField += 4;

}

if(v == 'f') {

iField += 5;

}

if(v == 'g') {

iField += 6;

}

if(v == 'h') {

iField += 7;

}

//log('return ' + iField);

return self.fields[iField];

}

function getFigure(is_short, is_long, target, color, field) {

if(is_short || is_long) {

if(color == 'w') {

if(is_short) {

return new Array(self.figures[0], self.figures[7]);

}

if(is_long) {

return new Array(self.figures[0], self.figures[6]);

}

}

if(color == 'b') {

if(is_short) {

return new Array(self.figures[16], self.figures[23]);

}

if(is_long) {

return new Array(self.figures[16], self.figures[22]);

}

}

}

if(target == 'alive') {

return field.last_figure;

}

if(target == 'dead') {

return field.last_figure;

}

}

// Запитуємо відновлення позиції

new Ajax.Request(Chess.moves, {

method: 'get',

onSuccess: function(transport) {

self.all_moves = transport.responseText;

}

});

// Анализируемходипартии

var splits = self.all_moves.split('|');

var moves = new Array();

for(i = 0; i < splits.length; i++) {

if(splits[i] != null) {

moves.push(splits[i

}

}

// Кількість отриманих ходів

var number = moves.length;

var current_number = self.last_move == null ? 1 : self.last_move.number;

if(number == current_number && self.last_move != null && self.last_move.color == 'w') {

var move_annotation = moves[number - 1];

if(move_annotation != '' && existsMove('b', moves[number - 1])) {

var move = Chess.createMove();

move.is_short_castling = isCastling('b', 'short', move_annotation);

move.is_long_castling = isCastling('b', 'long', move_annotation);

move.field_from = getField(move.is_short_castling, move.is_long_castling, 'from' , 'b', move_annotation);

move.field_to = getField(move.is_short_castling, move.is_long_castling, 'to', 'b', move_annotation);

move.figure = getFigure(move.is_short_castling, move.is_long_castling, 'alive', 'b', move.field_from);

move.figure_dead = getFigure(false, false, 'dead', 'b', move.field_to);

move.number = self.last_move != null ? ('b' == 'w' ? (self.last_move.number + 1) : self.last_move.number) : 1;

move.color = 'b';

move.field_from.last_figure = null;

move.field_to.last_figure = move.figure;

move.prev = self.last_move;

if(self.last_move != null) {

self.last_move.next = move;

}

self.last_move = move;

self.changes = true;

}

}

if(number > current_number) {

var c = ['w', 'b'];

for(var iMove = current_number; iMove < = number; iMove++) {

for(var ic = 0; ic < c.length; ic++) {

var move_annotation = moves[iMove - 1];

if(existsMove(c[ic], move_annotation)) {

var move = Chess.createMove();

if(self.first_move == null) {

self.first_move = move;

}

move.is_short_castling = isCastling(c[ic], 'short', move_annotation);

move.is_long_castling = isCastling(c[ic], 'long', move_annotation);

move.field_from = getField(move.is_short_castling, move.is_long_castling, 'from' , c[ic], move_annotation);

move.field_to = getField(move.is_short_castling, move.is_long_castling, 'to', c[ic], move_annotation);

move.figure = getFigure(move.is_short_castling, move.is_long_castling, 'alive', c[ic], move.field_from);

move.figure_dead = getFigure(move.is_short_castling, move.is_long_castling, 'dead', c[ic], move.field_to);

move.number = self.last_move != null ? (c[ic] == 'w' ? (self.last_move.number + 1) : self.last_move.number) : 1;

move.color = c[ic];

var ff = move.field_from;

var ft = move.field_to;

var fg = move.figure;

if(fg == null) {

continue;

}

move.field_from.last_figure = null;

move.field_to.last_figure = move.figure;

move.prev = self.last_move;

if(self.last_move != null) {

self.last_move.next = move;

}

self.last_move = move;

self.changes = true;

}

}

}

}

}

self.changes = false;

// Перерисовкапозиции

self.repaint = function() {

if(self.current_move == null) {

if(self.first_move == null) {

return;

}

self.current_move = self.first_move;

}

if(self.current_move.color == 'w' && self.white_number == self.current_move.number ||

self.current_move.color == 'b' && self.black_number == self.current_move.number) {

if(self.current_move.next != null) {

self.current_move = self.current_move.next;

}

return;

}

self.current_move.forward();

if(self.current_move.color == 'w') {

self.white_number++;

}

if(self.current_move.color == 'b') {

self.black_number++;

}

if(self.current_move.next != null) {

self.current_move = self.current_move.next;

}

}

// Инициализируем дошку, створюємо полючи і фігури

self.init = function() {

var v = new Array("A", "B", "C", "D", "E", "F", "G", "H");

var f = new Array("K", "Q", "B", "N", "R", "P");

var c = new Array("w", "b");

// Создаемпредставлениедоски - таблицю

var tableBoard = document.createElement('table');

tableBoard.border = 1;

tableBoard.align = "center";

tableBoard.width = "512px";

var tableBody = document.createElement('tbody');

tableBoard.appendChild(tableBody);

var tableDiv = $('board');

tableDiv.appendChild(tableBoard);

var rows = new Array(document.createElement('tr'), document.createElement('tr'), document.createElement('tr'), document.createElement('tr'),

document.createElement('tr'), document.createElement('tr'), document.createElement('tr'), document.createElement('tr'));

for(var iRow = 7; iRow > = 0; iRow-) {

tableBody.appendChild(rows[iRow]);

}

// создаемячейки

for(var iVertical = 0; iVertical < 8; iVertical++) {

for(var iHorizontal = 8; iHorizontal > 0; iHorizontal-) {

var cell = document.createElement('td');

cell.width = '64px';//(100 / 8).toString() + "%";

cell.height = cell.width;

cell.align = 'center';

cell.id = "field" + v[iVertical] + iHorizontal.toString();

rows[iHorizontal - 1].appendChild(cell);

}

}

// полючи

log('creating fields ...');

var iField = 0;

for(var iHorizontal = 1; iHorizontal < 9; iHorizontal++) {

for(var iVertical = 0; iVertical < 8; iVertical++) {

self.fields[iField] = Chess.createField(v[iVertical], iHorizontal.toString());

iField++;

}

}

log('creating figure ...');

// фігури

self.figures[0] = Chess.createFigure(c[0], f[0], ''); // wk - 0

self.figures[1] = Chess.createFigure(c[0], f[1], ''); // wq - 1

self.figures[2] = Chess.createFigure(c[0], f[2], v[2]); // wbC - 2

self.figures[3] = Chess.createFigure(c[0], f[2], v[5]); // wbF - 3

self.figures[4] = Chess.createFigure(c[0], f[3], v[1]); // wnB - 4

self.figures[5] = Chess.createFigure(c[0], f[3], v[6]); // wnG - 5

self.figures[6] = Chess.createFigure(c[0], f[4], v[0]); // wrA - 6

self.figures[7] = Chess.createFigure(c[0], f[4], v[7]); // wrH - 7

self.figures[8] = Chess.createFigure(c[0], f[5], v[0]); // wpA - 8

self.figures[9] = Chess.createFigure(c[0], f[5], v[1]); // wpB - 9

self.figures[10] = Chess.createFigure(c[0], f[5], v[2]); // wpC - 10

self.figures[11] = Chess.createFigure(c[0], f[5], v[3]); // wpD - 11

self.figures[12] = Chess.createFigure(c[0], f[5], v[4]); // wpE - 12

self.figures[13] = Chess.createFigure(c[0], f[5], v[5]); // wpF - 13

self.figures[14] = Chess.createFigure(c[0], f[5], v[6]); // wpG - 14

self.figures[15] = Chess.createFigure(c[0], f[5], v[7]); // wpH - 15

self.figures[16] = Chess.createFigure(c[1], f[0], ''); // bk - 16

self.figures[17] = Chess.createFigure(c[1], f[1], ''); // bq - 17

self.figures[18] = Chess.createFigure(c[1], f[2], v[2]); // bbC - 18

self.figures[19] = Chess.createFigure(c[1], f[2], v[5]); // bbF - 19

self.figures[20] = Chess.createFigure(c[1], f[3], v[1]); // bnB - 20

self.figures[21] = Chess.createFigure(c[1], f[3], v[6]); // bnG - 21

self.figures[22] = Chess.createFigure(c[1], f[4], v[0]); // brA - 22

self.figures[23] = Chess.createFigure(c[1], f[4], v[7]); // brH - 23

self.figures[24] = Chess.createFigure(c[1], f[5], v[0]); // bpA - 24

self.figures[25] = Chess.createFigure(c[1], f[5], v[1]); // bpB - 25

self.figures[26] = Chess.createFigure(c[1], f[5], v[2]); // bpC - 26

self.figures[27] = Chess.createFigure(c[1], f[5], v[3]); // bpD - 27

self.figures[28] = Chess.createFigure(c[1], f[5], v[4]); // bpE - 28

self.figures[29] = Chess.createFigure(c[1], f[5], v[5]); // bpF - 29

self.figures[30] = Chess.createFigure(c[1], f[5], v[6]); // bp - 30

self.figures[31] = Chess.createFigure(c[1], f[5], v[7]); // bp - 31

// розставляємо вихідну позицію

self.set_begin_position();

}

self.set_begin_position = function() {

log('initialize begin position ...');

self.fields[56].init_figure(self.figures[22]);

self.fields[57].init_figure(self.figures[20]);

self.fields[58].init_figure(self.figures[18]);

self.fields[59].init_figure(self.figures[17]);

self.fields[60].init_figure(self.figures[16]);

self.fields[61].init_figure(self.figures[19]);

self.fields[62].init_figure(self.figures[21]);

self.fields[63].init_figure(self.figures[23]);

self.fields[48].init_figure(self.figures[24]);

self.fields[49].init_figure(self.figures[25]);

self.fields[50].init_figure(self.figures[26]);

self.fields[51].init_figure(self.figures[27]);

self.fields[52].init_figure(self.figures[28]);

self.fields[53].init_figure(self.figures[29]);

self.fields[54].init_figure(self.figures[30]);

self.fields[55].init_figure(self.figures[31]);

self.fields[8].init_figure(self.figures[8]);

self.fields[9].init_figure(self.figures[9]);

self.fields[10].init_figure(self.figures[10]);

self.fields[11].init_figure(self.figures[11]);

self.fields[12].init_figure(self.figures[12]);

self.fields[13].init_figure(self.figures[13]);

self.fields[14].init_figure(self.figures[14]);

self.fields[15].init_figure(self.figures[15]);

self.fields[0].init_figure(self.figures[6]);

self.fields[1].init_figure(self.figures[4]);

self.fields[2].init_figure(self.figures[2]);

self.fields[3].init_figure(self.figures[1]);

self.fields[4].init_figure(self.figures[0]);

self.fields[5].init_figure(self.figures[3]);

self.fields[6].init_figure(self.figures[5]);

self.fields[7].init_figure(self.figures[7]);

}

self.set_end_position = function() {

}

self.set_position = function(number, color) {

}

self.next_move = function() {

}

self.prev_move = function() {

}

return self;

}

};

var board = Chess.createBoard();

// Периодическоеобновлениепозиции

new PeriodicalExecuter(board.refresh, Chess.refresh_delay);

// Периодическаяперерисовкапозиции

new PeriodicalExecuter(board.repaint, Chess.repaint_delay)