gsu.bydl.gsu.by/Images/_i4f/_diploms/KRAVCHENKO.docx · Web view5.3 По мере...

127
МИНИСТЕРСТВО ОБРАЗОВАНИЯ РЕСПУБЛИКИ БЕЛАРУСЬ Учреждение образования «Гомельский государственный университет имени Франциска Скорины» Факультет математики и технологий программирования Кафедра математических проблем управления и информатики Допущена к защите Зав. кафедрой_______________ В.С.Смородин "____"________________20___г. Автоматизация загрузки результатов Internet-олимпиад в систему DL Дипломная работа Исполнитель студент группы ПМ-51 __________________ Ю.М. Кравченко Научный руководитель ассистент кафедры МПУиИ __________________ М.А. Писпанен Рецензент д.т.н., профессор кафедры ВМиП __________________ В.В.Можаровский

Transcript of gsu.bydl.gsu.by/Images/_i4f/_diploms/KRAVCHENKO.docx · Web view5.3 По мере...

Page 1: gsu.bydl.gsu.by/Images/_i4f/_diploms/KRAVCHENKO.docx · Web view5.3 По мере выполнения программы, она выводит предупреждения в консоль.

МИНИСТЕРСТВО ОБРАЗОВАНИЯ РЕСПУБЛИКИ БЕЛАРУСЬ

Учреждение образования«Гомельский государственный университет

имени Франциска Скорины»Факультет математики и технологий программирования

Кафедра математических проблем управления и информатики

Допущена к защитеЗав. кафедрой_______________ В.С.Смородин "____"________________20___г.

Автоматизация загрузки результатов Internet-олимпиад в систему DL

Дипломная работа

Исполнитель студент группы ПМ-51 __________________ Ю.М. Кравченко

Научный руководительассистент кафедры МПУиИ __________________ М.А. Писпанен Рецензент д.т.н., профессор кафедры ВМиП __________________ В.В.Можаровский

Гомель 2017

Содержание

Page 2: gsu.bydl.gsu.by/Images/_i4f/_diploms/KRAVCHENKO.docx · Web view5.3 По мере выполнения программы, она выводит предупреждения в консоль.

Введение...................................................................................................................31. Детальная постановка задачи...........................................................................4

1.1 Технология загрузки результатов ВКОШП.............................................41.2 Технология загрузки результатов Белорусской республиканской олимпиады..........................................................................................................111.3 Постановка задачи автоматизации интернет-олимпиад.......................21

2. Программно-файловая структура..................................................................243. Алгоритмы.........................................................................................................30

3.1 Файлы JSP-страниц......................................................................................303.2 Классы и методы..........................................................................................32

4. Технология использования...............................................................................404.1 Технология автоматической загрузки результатов ВКОШП..................404.2 Технология загрузки результатов Белорусской республиканской олимпиады..........................................................................................................45

5. Результаты апробации....................................................................................555.1 Результаты апробации ВКОШП.................................................................555.2 Результаты апробации Республиканской олимпиады...........................59

Заключение............................................................................................................67Список литературы...............................................................................................68Приложение А Разработанный программный код.............................................69

2

Page 3: gsu.bydl.gsu.by/Images/_i4f/_diploms/KRAVCHENKO.docx · Web view5.3 По мере выполнения программы, она выводит предупреждения в консоль.

Введение

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

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

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

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

Средой разработки приложения является интегрированная среда разработки программного обеспечения IntelliJ IDEA, языком написания приложения - Java.

В ходе выполнения дипломной работы решаются следующие задачи: изучение базы данных MS SQL, используемой приложением; изучение и загрузка результатов олимпиад в ручном режиме; изучение каркасов разработки JSP, ApacheVelocity, JiXB, JDBC; автоматизация загрузки результатов Всероссийской олимпиады

школьников по программированию (ВКОШП) для сайта dl.gsu.by; загрузка результатов ВКОШП за 2015 и 2016 года; автоматизация загрузки результатов Белорусской

республиканской олимпиады для dl.gsu.by, загрузка результатов; реализация компонентов автоматизации.Актуальность данной темы обусловлена стремлением

автоматизировать все рутинные процессы, которые отнимают значительную часть рабочего времени.

Основной функцией программного компонента будет являться автоматизация загрузки результатов интернет-олимпиад для сайта dl.gsu.by

Данная дипломная работа состоит из 5 частей.В первой главе части дипломной работы описывается детальная

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

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

В следующем разделе описывается алгоритм работы файлов.В четвертой части дипломной работы описывается технология загрузки

олимпиад в автоматическом режиме.В последней главе дипломной работы описывается апробация работы.

3

Page 4: gsu.bydl.gsu.by/Images/_i4f/_diploms/KRAVCHENKO.docx · Web view5.3 По мере выполнения программы, она выводит предупреждения в консоль.

4

Page 5: gsu.bydl.gsu.by/Images/_i4f/_diploms/KRAVCHENKO.docx · Web view5.3 По мере выполнения программы, она выводит предупреждения в консоль.

1. Детальная постановка задачи

1.1 Технология загрузки результатов ВКОШП

ВКОШП – это Всероссийская командная олимпиада школьников по программированию. Олимпиада проводится в один компьютерный тур. На туре команде предоставляется персональный компьютер и предлагается решить несколько задач. В олимпиаде принимают участие команды, каждая из которых составлена из трех школьников. Выше оказывается классифицирована команда, решившая большее количество задач. При равенстве количества решенных задач выше оказывается классифицирована команда, у которой меньше суммарное штрафное время. Каждый год выбирается количество команд, которые награждаются дипломами 1, 2 и 3 степени. Так, например, в 2015 году команды, решившие 6 задач, награждались дипломами 3 степени, команды, решившие 7 задач, награждались дипломами 2 степени, а команды, решившие 8 и более задач, награждаются дипломами 1 степени.

Для просмотра составов команд необходимо зайти по ссылкам как показано на рисунке 1.

Рисунок 1– Просмотр составов команд

Если зайти по данной ссылке, то можно просмотреть составы команд за разные годы (рисунок 2).

5

Page 6: gsu.bydl.gsu.by/Images/_i4f/_diploms/KRAVCHENKO.docx · Web view5.3 По мере выполнения программы, она выводит предупреждения в консоль.

Рисунок 2 – Составы гомельских команд по годам

Процесс загрузки рассмотрен по шагам на примере “Десятой Всероссийской командной олимпиады школьников по программированию”.

1. Перед началом загрузки сделайте пожалуйста backup базы ROlimp (SQL Server).

2. Подключаемся к базе ROlimp.В случае возникновения проблем с 1 и 2 пунктами обратитесь на сайт

Microsoft в раздел базы данных или же перейдите по ссылке: https://msdn.microsoft.com/ru-ru/library/ms187510(v=sql.110).aspx где подробно разъяснено, как и что делать.

3. Создаем курс для олимпиады в базе ROlimp, таблице Courses:INSERT INTO Courses(Name, EName, ShortName, AwardType,

Active, Type, Accept, TimeBegin, TimeEnd, DefaultTaskHiLevel, DefaultTheoryLevel, RealtimeResults, PublicDetails, TableType, ParentID, Num, TasksViewType, CanGetSolution, Hidden, CanGetTest) VALUES(

'Деcятая Всероссийская командная олимпиада школьников по программированию', 'Russia 2009', 'C09', 1, 1, 3, 3, '2009-11-23', '2009-12-02', 10000, 10000, 1, 1, 5, 26, 1,1,1, 0, 0)

ParentID – 26 для данного типа соревнования.

6

Page 7: gsu.bydl.gsu.by/Images/_i4f/_diploms/KRAVCHENKO.docx · Web view5.3 По мере выполнения программы, она выводит предупреждения в консоль.

Запрос стандартный кроме указания Name, TimeBegin, TimeEnd соответствующих вашей олимпиаде.

Необходимо знать ID (который был сгенерирован SQL Server автоматически) с которым был создан данный курс, т.к. он понадобится в дальнейшем. В данном случае ID = 75.

4. Данные из оригинальной таблицы результатов (в данном случае original\Standings.mht) необходимо представить в определенном формате и сохранить в текстовый файл. Более того, придется найти все гомельские команды и дать им такие имена, которые они имеют в базе ROlimp. В данном случае это команды:

Гомель, сборная #1Гомель, сборная #3Гомель, сборная #2Имена должны быть измены как показано ниже:Гомель, ГОМЕЛЬ-1Гомель, ГОМЕЛЬ-3Гомель, ГОМЕЛЬ-2В данном случае получился следующий файл: rus2009.txt.5. Необходимо конвертировать данный текстовый файл в XML

версию, которая используется для загрузки результатов в базу. Для этого:5.1 Запускаем программу (r-import\trunk\dev\src\TextToXML2.java),

которая преобразовывает текстовый формат в XML представление, передавая ей полный путь к текстовому файлу (в данном случае D:\Projects\DL\src\svn\r-import\trunk\dev\stuff\rus2009.txt).

5.2 После выполнения в той же директории будет создан XML файл (в данном случае rus2009.xml).

5.3 По мере выполнения программы, она выводит предупреждения в консоль. Так если в консоли присутствуют сообщения Fix(1), это значит, что города, указанные в текстовом файле, отсутствуют в базе ROlimp. В данном случае таких сообщений было несколько. Каждое из них говорит, какой SQL запрос может исправить проблему. Итак, необходимо запустить следующий SQL запросы на базе ROlimp (смотреть файл files\rus2009fixCities_draft.sql в приложении).

5.4 Страны, к которым относятся неопознанные города (можно поискать в google), придется определить самостоятельно. Когда страны будут определены, необходимо проверить есть ли они в таблице Counties. Если да, то на месте xxx в SQL скрипт нужно подставить ID страны в таблице Countries. Если страны нет, то требуется добавить её самостоятельно и узнав ID подставить его в запрос. В данном случае SQL скрипт принял вид (files/rus2009fixCities_final.sql). Запустите скрипт, что бы города были добавлены в базу.

5.5 Повторите пункт 5 еще раз.5.6 Подготавливаем rus2009.xml к import-у в ROlimp.5.6.1 Устанавливаем courseID в ID нашего курса (пункт 3):

<competitionInfo7

Page 8: gsu.bydl.gsu.by/Images/_i4f/_diploms/KRAVCHENKO.docx · Web view5.3 По мере выполнения программы, она выводит предупреждения в консоль.

name="Россия 2009" contestType="TEAM" courseID="75" openDate="23.11.2009" collapseDate="02.12.2009" language="rus" > <header> <task name="A" /> <task name="B" /> <task name="C" /> <task name="D" /> <task name="E" /> <task name="F" /> <task name="G" /> <task name="H" /> <task name="I" /> <task name="J" /> <task name="K" /> </header></competitionInfo>

5.6.2 Необходимо найти все гомельские команды в xml файле и заменить:

Гомель, ГОМЕЛЬ-1Гомель, ГОМЕЛЬ-3Гомель, ГОМЕЛЬ-2на простоГОМЕЛЬ-1ГОМЕЛЬ-3ГОМЕЛЬ-25.6.3 Также проставить информацию по дипломам для гомельских

команд (в данном случае ГОМЕЛЬ-1 – диплом 1-й степени, ГОМЕЛЬ-2 – диплом 3-й степени).

В итоге был получен конечный файл ( files\rus2009_final.xml).5.7 Импортируем rus2009_final.xml в ROlimp.5.7.1 Убедитесь, что сделан backup базы ROlimp.5.7.2 Необходимо найти класс LoadXMLtoDB.5.7.3 Убедитесь, что используется следующий способ создания

ResultXML ResultXML rXML = new ResultXML(ResultXML.SaveResultInDB);

5.7.4 При запуске import используется следующий метод:FileReader r = new FileReader("D:\\Projects\\DL\\src\\svn\\

r-import\\trunk\\dev\\xmls\\rus2009_final.xml"); rXML.parseStream(new InputSource(r));5.7.5 Запускается класс на выполнение.5.7.6 В консоль выводится информация по мере import-а данных.

Смотрите import_to_sqlserver\log.txt ( лог для данной олимпиады, у вас, конечно, будет отличаться).

6. Нужно зайти на сайт как показано на рисунке 2.

8

Page 9: gsu.bydl.gsu.by/Images/_i4f/_diploms/KRAVCHENKO.docx · Web view5.3 По мере выполнения программы, она выводит предупреждения в консоль.

7. Результаты данной олимпиады отображены на сайте (рисунок 3).

Рисунок 3 – Отображение команд после import-а XML

8. Составы команд взяты из прошлых годов, для занесения информации о командах за этот год, а также для указания актуальной информации по классам участников необходимо выполнить sql скрипты из files\fix_teams.sql. После выполнения составы команд обновятся (рисунок 4):

Рисунок 4 – Отображение команд после корректировки команд

9

Page 10: gsu.bydl.gsu.by/Images/_i4f/_diploms/KRAVCHENKO.docx · Web view5.3 По мере выполнения программы, она выводит предупреждения в консоль.

9. Для данного соревнования отсутствует ссылка на таблицу результатов. Что бы её добавить:

9.1 Выполните запрос на базе данных ROlimp (это в данном случае):INSERT INTO resulttables ( CourseID, Title, ETitle, URL, EURL ) VALUES ( 75, 'Девятая Всероссийская командная олимпиада

школьников по программированию', 'Russia 2009', 'xrestable.jsp?

hd=2&hid=643&pi=6&pi=7&u.c=75&lng=rus&u.a&c.l=4&c.n=2&c.s=2&c.s=7', 'xrestable.jsp?hd=2&hid=643&pi=6&pi=7&u.c=75&lng=eng&u.a&c.l=4&c.n=2&c.s=2&c.s=7');

CourseID – ID нашего курса (у вас свой).URL – корректная ссылка на результаты, где hid у вас такой, какой

первый HeaderItemID был сгенерирован при импорте данных в базу ROlimp из rus2009_final.xml – можно посмотреть в лог файле (см 5.7.6, но у каждого будет свое значение).

INSERT INTO dl2ResultsCell (HeaderItemID,UserID,Value,TypeID) VALUES (643,1543,9.0,1).

u.c – id нашего курса (данный 75, у вас свой).10. После выполнения скрипта обновите страницу составов команд

Ссылка на результаты добавлена. (рисунок 5).

Рисунок 5 - Ссылка на таблицу результатов10

Page 11: gsu.bydl.gsu.by/Images/_i4f/_diploms/KRAVCHENKO.docx · Web view5.3 По мере выполнения программы, она выводит предупреждения в консоль.

11. Ссылка на дипломы по участникам должна работать корректно (рисунок 6).

Рисунок 6 – Ссылка на дипломы

12. Дипломы по школам так же распределены корректно (рисунок 7):

11

Page 12: gsu.bydl.gsu.by/Images/_i4f/_diploms/KRAVCHENKO.docx · Web view5.3 По мере выполнения программы, она выводит предупреждения в консоль.

Рисунок 7 – Отображение дипломов по школам

13.Результаты загружены

1.2 Технология загрузки результатов Белорусской республиканской олимпиады

Для того, чтобы просмотреть уже закруженные результаты необходимо зайти по ссылке Олимпиады на сайте dl.gsu/by/olymp. Появится список уже загруженных олимпиад (рисунок 8).

12

Page 13: gsu.bydl.gsu.by/Images/_i4f/_diploms/KRAVCHENKO.docx · Web view5.3 По мере выполнения программы, она выводит предупреждения в консоль.

Рисунок 8 - Список республиканских олимпиад

Если зайти по одной из ссылок (2009 (Минск), например), то можно просмотреть различные виды статистик по данной олимпиаде, переходя по соответствующей ссылке (рисунок 9).

Рисунок 9 - Результаты проведения Белорусской республиканской олимпиады 2009 года и доступ к различным видам статистик

Переходить по ссылкам (Статистика по дипломам, Статистика за разные годы, и т.д.) дает возможность просмотреть различные виды отчетов о проведении олимпиад. Данные для формирования данных отчетов содержаться в двух базах MS Access базе (Olymp\mdb\book.mdb) и MS SQL Server базе ROlimp на DL_SERVER-е. Загрузка результатов очередной олимпиады сводится к загрузке данных в базы, указанные выше.

Процесс загрузки рассмотрен по шагам на примере вымышленной (в момент написания данного документа) олимпиаде “Белорусская республиканская олимпиада 2010 года”

13

Page 14: gsu.bydl.gsu.by/Images/_i4f/_diploms/KRAVCHENKO.docx · Web view5.3 По мере выполнения программы, она выводит предупреждения в консоль.

1. Перед началом загрузки сделайте пожалуйста backup-ы баз, указанных выше.

2. Подключаемся к базе ROlimp.3. Создаем событие проведения олимпиады в базе ROlimp, таблице

Calendar:INSERT INTO Calendar ( ID, Year, Month, DayStart, DayEnd, NameID, Place, Contestant, URLResult ) VALUES ( 216, 2010, 3, '2010-03-24', '2010-03-29', 17, 'Гомель', 1, 'showRes.asp?id=216');ID – следующий максимальный id в таблице Calendar.NameID – 17 для данного типа соревнование.Place – место проведения соревнования.Contestant – 1 для данного типа соревнования.URLResult – должен быть showRes.asp?id=<id>, где <id> - такой же как

и ID.Остальные поля интуитивны и не требуют пояснения.4. Заходим по ссылке Олимпиады. Олимпиада появилась в списке

(рисунок 10):

Рисунок 10 – Отображение названия олимпиады в списке олимпиад

14

Page 15: gsu.bydl.gsu.by/Images/_i4f/_diploms/KRAVCHENKO.docx · Web view5.3 По мере выполнения программы, она выводит предупреждения в консоль.

Если выполнить переход по ссылке, то произойдет ошибка отображения страницы из-за отсутствия данных по данной олимпиаде в базе MS Access book.mdb.

5. Загружаем результаты проведения нашей олимпиады в базу book.mdb.

5.1 Результаты представлены таблицей Respublica в базе book.mdb (рисунок 11):

Рисунок 11 – Таблица Respublica в базе book.mdb

5.2 В данном случае оригинальные результаты представлены в виде следующего xls файла (рисунок 12):

Рисунок 12 – Оригинальные результаты олимпиады

5.3 Проще всего создать новый лист в xls, преобразовать данные в формат таблицы Respublica и выполнить import данных в базу book.mdb.

5.4 Преобразовываем данные в соответствии с форматом таблицы Respublica (рисунок 13):

15

Page 16: gsu.bydl.gsu.by/Images/_i4f/_diploms/KRAVCHENKO.docx · Web view5.3 По мере выполнения программы, она выводит предупреждения в консоль.

Рисунок 13 – Преобразованные данные

5.5 Поле Price означает вид награды (7 – Диплом 1-й степени, 8 – Диплом 2-й степени, 9 – Диплом 3-й степени, 10 – Похвальный лист, 12 – отсутствие награды).

5.6 Выполните корректировку из 9.3.2.5.7 Открываем book.mdb.5.8 Из всплывающего меню выбираем Import… (рисунок 14):

Рисунок 14 – Выбор команды Import

5.9 Выбираем наш xls файл с преобразованными данными (рисунок 15):

16

Page 17: gsu.bydl.gsu.by/Images/_i4f/_diploms/KRAVCHENKO.docx · Web view5.3 По мере выполнения программы, она выводит предупреждения в консоль.

Рисунок 15 – Выбор файла с преобразованными данными

5.10 Выбираем нашу страницу, нажимаем Next (рисунок 16):

Рисунок 16 – Выбор команды Next

5.11 Далее по умолчанию (рисунок 17):

17

Page 18: gsu.bydl.gsu.by/Images/_i4f/_diploms/KRAVCHENKO.docx · Web view5.3 По мере выполнения программы, она выводит предупреждения в консоль.

Рисунок 17 – Выбор команды по умолчанию

5.12 Импортируем данные в таблицу Respublica (рисунок 18):

Рисунок 18 – Импорт данных в таблицу Respublica

5.13 Завершаем Import.

18

Page 19: gsu.bydl.gsu.by/Images/_i4f/_diploms/KRAVCHENKO.docx · Web view5.3 По мере выполнения программы, она выводит предупреждения в консоль.

5.14 Закрываем файл book.mdb (если не закрыть файл, результаты могут не отображаться из за совместного доступа к файлу).

6. Снова заходим по ссылке 2010 (Гомель).7. Отображаются результаты проведения данной олимпиады

(рисунок 19):

Рисунок 19 – Результаты проведения олимпиады

8. Если выполнять переход по ссылкам на различные виды отчетов (Статистика по дипломам, Статистика за разные годы, и т.д.), то некоторые из отчетов будут не доступны, а некоторые не будут содержать данных по данной олимпиаде. Причиной является отсутствие необходимых данных в базе ROlimp MS SQL Server-а.

9. Загружаем необходимые данные в ROlimp.9.1 Экспортируем данные по данной олимпиаде из book.mdb в xml

файл.9.1.1 Открываем book.mdb.9.1.2 Находим модуль Functions (рисунок 20):

Рисунок 20 – Модуль Functions

19

Page 20: gsu.bydl.gsu.by/Images/_i4f/_diploms/KRAVCHENKO.docx · Web view5.3 По мере выполнения программы, она выводит предупреждения в консоль.

9.1.3 Заходим в него.9.1.4 Необходимо найти функцию work и меняем в ней файл в который

будет происходить export. В данном случае это будеn d:\bel (Set f = fs.OpenTextFile("d:\bel" & rYear & ".xml", 2, True, TristateFalse))

9.1.5 Создаем процедуру для запуска export-а:Sub export()Call work(2010)End Sub9.1.6 Запускаем процедуру (рисунок 21):

Рисунок 21 – Запуск процедуры

9.1.7 В данном случае был создан файл d:\bel2010.xml.9.2 Создаем курс для нашей олимпиады в базе ROlimp, таблица

Courses:INSERT INTO Courses (Name, AwardType, Active, Type,

Accept, TimeBegin, TimeEnd, DefaultTaskHiLevel, DefaultTheoryLevel, RealTimeResults, PublicDetails, TableType, ParentID, Num, TasksViewType, CanGetSolution, Hidden, CanGetTest) VALUES ('Республиканская олимпиада по информатике 2010', 1, 1, 2, 3, '2010-03-24', '2010-03-29', 10000, 10000, 1, 1, 5, 29, 1, 1, 1, 0, 0);

Запрос стандартный кроме указания Name, TimeBegin, TimeEnd соответствующих вашей олимпиаде.

Необходимо знать ID (который был сгенерирован SQL Server автоматически) с которым был создан данный курс, т.к. он понадобится в дальнейшем. В данном случае ID = 74.

9.3 Подготавливаем bel2010.xml к import-у в ROlimp.9.3.1 Устанавливаем courseID в ID нашего курса (см 9.2)<competitionInfo name="Республика 2010" contestType="USER" courseID="74" openDate="24.03.2010"

collapseDate="29.03.2010" language="rus" > <header> <day name="Day 1"> <task name="Task 1" /> <task name="Task 2" /> <task name="Task 3" /> </day> <day name="Day 2"> <task name="Task 4" />

20

Page 21: gsu.bydl.gsu.by/Images/_i4f/_diploms/KRAVCHENKO.docx · Web view5.3 По мере выполнения программы, она выводит предупреждения в консоль.

<task name="Task 5" /> <task name="Task 6" /> </day></header></competitionInfo>9.3.2 Все region у всех contestant должны быть описаны в ROlimp

таблица Regions. Замечание: Если у вас в bel2010.xml г. Минск в атрибуте region с пробелом, то необходимо его убрать (лучше всего это выполнить на стадии подготовки xls в book.mdb, чтобы избежать лишней работы по корректировки данных). Тоже касается и других значений (данные должны полностью соответствовать таблице Regions).

9.4 Импортируем bel2010.xml в ROlimp.9.4.1 Необходимо убедиться, что сделан backup базы ROlimp.9.4.2 Проверяем параметры соединения с базой в olymp.db.DBUtil

(находится в модуле r-olimp) (username, password, jdbcConnection).9.4.3 Находим класс LoadXMLtoDB.9.4.4 Убедитесь, что используется следующий способ создания

ResultXML ResultXML rXML = new ResultXML(ResultXML.SaveResultInDB);9.4.5 При запуске export использовал следующий метод:FileReader r = new FileReader("D:\\Projects\\DL\\src\\svn\\

r-import\\trunk\\dev\\xmls\\bel2010.xml"); rXML.parseStream(new InputSource(r));9.4.6 Запускаем класс на выполнение.9.4.7 В консоль выводится информация по мере import-а данных.

Смотрите export_to_sqlserver\log.txt (данный лог, в ином случае, конечно, будет отличаться).

10. Теперь будут доступны все виды отчетов.11. Если перейти по отчету Все гомельчане (рисунок 22):

Рисунок 22 – Таблица результатов

то отобразится следующая страница (рисунок 23).

21

Page 22: gsu.bydl.gsu.by/Images/_i4f/_diploms/KRAVCHENKO.docx · Web view5.3 По мере выполнения программы, она выводит предупреждения в консоль.

Рисунок 23 – Страница результатов всех гомельчан

Ссылка «Таблица результатов» для нашего соревнования будет не верной. Для обновления ссылки необходимо:

11.1 Выполнить запрос на базе данных ROlimp:INSERT INTO resulttables (CourseID, Title, ETitle, URL,

EURL) VALUES (74, 'Республика 2010','Rebublics contest 2010', 'xrestable.jsp?hd=2&hid=610&u.c=74&pi=11&pi=3&c.s=1&c.s=9&lng=rus', 'xrestable.jsp?hd=2&hid=610&u.c=74&pi=11&pi=3&c.s=1&c.s=9&lng=eng');

CourseID – ID нашего курса (у вас свой).URL – корректная ссылка на результаты, где hid у вас такой, какой

первый HeaderItemID был сгенерирован при импорте данных в базу ROlimp из bel2010.xml – можно посмотреть в лог файле (см 9.4.7, но у вас будет свое значение).

INSERT INTO dl2ResultsCell (HeaderItemID,UserID,Value,TypeID) VALUES (610,200034,600.0,1).

u.c – id нашего курса (мой 74, у вас свой).12. Если участник не пресутствет в базе ROlimp, то при загрузке XML

он создается автоматически. К сожалению школу участника узнать не удается и из-за отсутствия данной информации некоторые отчеты могут выглядеть неполными. Так, например, отчет “Статистика за разные годы”. С помощью SQL скрипта, приведенного в приложении А (vkoshp.sql) можно узнать у каких участников в каких курсах не заполнена информация об учебном заведении:

13. Находим для данных пользователей в таблице UsersHistory последнюю запись и проставляем в ней название учебного заведения.

14. Загрузка закончена.

1.3 Постановка задачи автоматизации интернет-олимпиад

22

Page 23: gsu.bydl.gsu.by/Images/_i4f/_diploms/KRAVCHENKO.docx · Web view5.3 По мере выполнения программы, она выводит предупреждения в консоль.

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

Олимпиада проводится в один компьютерный тур. На туре команде предоставляется персональный компьютер и предлагается решить несколько задач. В олимпиаде принимают участие команды, каждая из которых составлена из трех школьников. Выше оказывается классифицирована команда, решившая большее количество задач. При равенстве количества решенных задач выше оказывается классифицирована команда, у которой меньше суммарное штрафное время. Каждый год выбирается количество команд, которые награждаются дипломами 1, 2 и 3 степени. Так, например, в 2015 году команды, решившие 6 задач, награждались дипломами 3 степени, команды, решившие 7 задач, награждались дипломами 2 степени, а команды, решившие 8 и более задач, награждаются дипломами 1 степени.

Высокоуровневая схема работы компонента представлена на рисунке 24.

Рисунок 24 – Схема работы компонента

Оригинальные результаты проведения олимпиады находятся на сайте https://neerc.ifmo.ru/school/russia-team/. Исходные данные предоставлены в виде таблицы формата HTML находящейся по адресу: https://neerc.ifmo.ru/school/archive/2015-2016/ru-olymp-team-russia-2015-standings (для 2015 года проведения), где для каждого года в адресной строке меняется год на соответствующий. Так для 2016 года таблица будет находится по адресу: https://neerc.ifmo.ru/school/archive/2016-2017/ru-olymp-team-russia-2016-standings.html. Каждая таблица результатов содержит следующие данные: номер по списку команды, команду (в названии команды

23

Page 24: gsu.bydl.gsu.by/Images/_i4f/_diploms/KRAVCHENKO.docx · Web view5.3 По мере выполнения программы, она выводит предупреждения в консоль.

указан город, название команды, состав участников), время решения задач, количество решенных задач.

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

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

24

Page 25: gsu.bydl.gsu.by/Images/_i4f/_diploms/KRAVCHENKO.docx · Web view5.3 По мере выполнения программы, она выводит предупреждения в консоль.

2. Программно-файловая структура

Основная программно-файловая структура компонента может быть представлена с помощью следующей схемы (рисунок 25):

Рисунок 25 – Программно-файловая структура

Рассмотрим более детально каждый файл, представленный на этой схеме.

Главная страница, с которой происходит загрузка олимпиад - olymp-res.jsp. На странице присутствует форма для загрузки данных в которой задается тип олимпиады, год проведения олимпиады, даты проведения, место проведения олимпиады (для республиканской олимпиады по программированию).

После заполнения формы и отправки данных происходит вызов класса LoadOlympResultsServlet в который эти данные передаются.

LoadOlympResultsServlet.java – это основной "маршрутизатор" внутри компонента. Он определяет, как поступать с полученными из формы со страницы olymp-res.jsp данными, вызывает методы из LoadOlympResultsService, в случае необходимости перенаправляет на страницы olymp-res-countries.jsp и olymp-res-diploms.jsp, позже дополняет данные полученной с этих страниц информацией.

LoadOlympResutsService.java – это файл, содержащий одноименный класс с основными методами загрузки. Создает объект класса VKOSHP, инициализирует его, загружает необходимую информацию с сайта с

25

Page 26: gsu.bydl.gsu.by/Images/_i4f/_diploms/KRAVCHENKO.docx · Web view5.3 По мере выполнения программы, она выводит предупреждения в консоль.

результатами ВКОШП, обращается к TextToXML2.java для создания списка объектов класса ResultContainer.java. Вызывает LoadXMLToDB.java для загрузки XML-файла в БД. Для обращений к базе использует методы класса DBUtil.java

TextToXML2.java: преобразует полученную из LoadOlympResutsService строку в объект класса ResultsContainer, предоставляя ему XML-файл с результатами олимпиады, а также список городов, для которых не найдены страны в базе данных ROlimp.

ResultsContainer.java: хранит в себе финальный XML-файл с результатами олимпиады, а также списки: городов с ненайденными странами и команд которым нужно задать степень диплома.

VKOSHP.java: содержит основную информацию об олимпиаде ВКОШП, а также предоставляет парсер, который преобразует полученную по URL-адресу с сайта с результатами ВКОШП HTML-страницу в строку определенного формата.

LoadXMLToDb.java: осуществляет финальную загрузку XML-файла в базу данных, используя XML-парсер из класса ResultXML.

ResultXML.java: XML-парсер, загружающий в БД информацию о результатах олимпиады.

Оlymp-res-countries.jsp – это страница, на которой для каждого полученного из сервлета LoadOlympResultsServlet города создается поле для ввода страны, в которой этот город находится. Предоставляет ссылки на запрос в Google по имени города. После ввода данных, происходит их отправка обратно в LoadOlympResultsServlet.

Оlymp-res-diploms.jsp – это страница, где для каждой команды, полученной из сервлета LoadOlympResultsServlet, создается поле для ввода степени диплома, полученного этой командой. По умолчанию значения во всех полях 0. После ввода данных, происходит их отправка обратно в LoadOlympResultsServlet.

Оlymp-res-finished.jsp - окончательная страница загрузки. На нее происходит перенаправление после загрузки всех данных в базу. Содержит ссылку на таблицу результатов на сайте dl.gsu.by.

Оlymp-res-respublica.jsp – показывает информацию о загруженных данных. Предоставляет полученный id из таблицы Corses, также предоставляет поле для ввода HeaderItemId.

Все файлы можно найти в папке проекта dl-web.Далее подробно рассмотрим таблицы, используемые для хранения

результатов. Первым шагом в загрузке результатов является создание курса для олимпиады в базе ROlimp, таблица Courses. Структура таблицы приведена в таблице 1.

26

Page 27: gsu.bydl.gsu.by/Images/_i4f/_diploms/KRAVCHENKO.docx · Web view5.3 По мере выполнения программы, она выводит предупреждения в консоль.

Таблица 1 – Структура таблицы Courses

Атрибут Тип Описание

ID числовой Уникальный идентификатор курсаName, EName символьный Название курсаShortName символьный Сокращенное название курсаActive логический Активен ли курс (скрывает курс для

всех см. поле Hidden)Type числовой Тип курса (1 - учебный, 2 - личное

соревнование или 3 - командное соревнование)

Accept числовой Доступен 1 - инд. Пользователям, 2 - командам или 3 - и тем и другим

TimeBegin дата/время Время закрытия курсаTimeEnd дата/время Время начала курсаDefaultTaskHiLevel числовой «Верхний» уровень доступа к

дереву задач, устанавливаемый по умолчанию

DefaultTheoryLevel, числовой Уровень доступа к дереву теории, устанавливаемый по умолчанию

TableType, числовой Тип таблицы 1, 2, 3 – старые типы таблиц 5 – таблица на java

ParentID числовой Курс - родитель (организация дерева)

Num, числовой Порядок сортировки (организация дерева)

CanGetSolution числовой Пользователь может брать свое решение обратно

Hidden логический Курс скрыт для не-редакторов

При загрузке республиканской олимпиады необходимо добавить записи в таблицу Calendar, где создавалось событие проведения олимпиады в базе ROlimp. Рассмотрим структуру таблицы Calendar (таблица 2)

Таблица 2 – Структура таблицы Calendar

Название поля Тип Назначение1 2 3

ID числовой Уникальный идентификатор ячейки

Year числовой Год проведения олимпиадыMonth числовой Месяц проведения олимпиады

27

Page 28: gsu.bydl.gsu.by/Images/_i4f/_diploms/KRAVCHENKO.docx · Web view5.3 По мере выполнения программы, она выводит предупреждения в консоль.

Окончание таблицы 2

1 2 3DayStart дата/время Дата начала проведения соревнованийDayEnd дата/время Дата окончания соревнованийNameID числовой 17, для данного типа соревнование.Plase символьный место проведения соревнования.Contestant числовой 1, для данного типа соревнованияURLResult символьный Строка showRes.asp?id=<id>, где <id> - такой же

как и ID.

Для хранения результатов олимпиады используются таблицы, структура которых приведена ниже.

Таблица dl2ResultsCell.Данная таблица используется для хранения информации по

результатам соревнований. Каждая запись в таблице описывает одну клеточку таблицы результатов. Для указания, какие данные хранятся в данной клеточке (ячейке) используется поле "type" (таблица 3).

Таблица 3 – Таблица dl2ResultsCell

Название поля Тип Назначение

headerItemId числовой Код соревнования из таблицы  dl2ResultsHeaderItem

userId числовой Код участника соревнования (Pupils/Teams)

[value] вещественный Значение в ячейке результатаtypeId числовой Тип ячейки (dl2ResultsCellType)ts timestamp “Слепок” времени внесения результатов

Таблица dl2ResultsCellType.Справочник типов ячеек, которые используются для хранения

результатов (таблица 4).

Таблица 4 – Таблица dl2ResultsCellType.Название поля Тип Назначение

1 2 3ID числовой Уникальный идентификатор ячейки

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

28

Page 29: gsu.bydl.gsu.by/Images/_i4f/_diploms/KRAVCHENKO.docx · Web view5.3 По мере выполнения программы, она выводит предупреждения в консоль.

Окончание таблицы 41 2 3

rusDescription символьный Комментарий к названию ячейки по-русскиengTitle символьный Аналогично rusTitleengDescription

символьный Комментарий к названии ячейки по-английски

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

descOrder логический Указывает на порядок сортировки по данному полю (прямой/обратный)

className символьный Имя класса, который отвечает за преобразование и вывод значения, находящегося в ячейке.

Таблица dl2ResultsHeaderItemMapping.Таблица используется для связывания между собой элементов шапки

соревнований из таблицы Courses. Значения полей openDate и coolapseDate должны совпадать с датами открытия закрытия курса из таблицы Courses или же, если есть ограничения на даты открытия (часть задач открывается в один день, часть в другой), тогда даты должны совпадать с датами из таблицы TasksHiLoDates. Структура таблицы представлена таблицей 5.

Таблица 5 – Таблица dl2ResultsHeaderItemMappingНазвание поля

Тип Назначение

headerItemId числовой Уникальный идентификатор элемента шапкиcourseId числовой Код соревнования, с которым связан элемент

шапкиnodeId числовой Код узла в дереве задач.openDate дата/время Дата начала соревнованияcollapseDate дата/время Дата завершения соревнования

Таблица dl2ResultsHeaderItemТаблица используется для хранения шапки таблиц результатов. Шапка

хранится в виде иерархической структуры. Структура таблицы представлена таблицей 6.

29

Page 30: gsu.bydl.gsu.by/Images/_i4f/_diploms/KRAVCHENKO.docx · Web view5.3 По мере выполнения программы, она выводит предупреждения в консоль.

Таблица 6 – Таблица dl2ResultsHeaderItemНазвание поля

Тип Назначение

itemId числовой Уникальный идентификатор элемента шапкиparentItemId числовой Код элемента-родителяchildIndex числовой Номер элемента в порядке его отображения в

таблице результатовrusTitle символьны

йНазвание элемента шапки по-русски

engTitle символьный

Название элемента шапки по-английски

tmp числовой Значение до конца не выясненоtmpParent числовой Используется для отладкиdeep числовой Уровень вложенности элемента шапки

(глубина)tmp2 числовой Используется для отладкиRootItemID числовой Код корневого элемента в шапке

30

Page 31: gsu.bydl.gsu.by/Images/_i4f/_diploms/KRAVCHENKO.docx · Web view5.3 По мере выполнения программы, она выводит предупреждения в консоль.

3. Алгоритмы

3.1 Файлы JSP-страниц

Главная страница, с которой происходит загрузка олимпиад - olymp-res.jsp. При обращении по этому адресу, на экран выводится форма, которую необходимо заполнить для загрузки олимпиад. Код страницы olymp-res.jsp приведен в приложении.

Данный код практически полностью статичен, помимо того, что строка для ввода места проведения олимпиады показывается и прячется в зависимости от выбранного пункта меню (ВКОШП или Республика), а также помимо того, что выпадающий список с годом проведения имеет максимальное значение равное текущему году, заданному на сервере.

После заполнения данных формы, необходимо нажать на "загрузить результаты олимпиады". После этого, идет обращение к сервлету LoadOlympResultsServlet, где в http-параметрах запроса передаются необходимые данные.

Далее, рассмотрим страницу olymp-res-countries.jsp.<body>Список городов, для которых не найдены страны:<form method='POST' action='load-olymp-results.jsp'> <div style="padding-top: 10px"> <span style="display: table-cell; width: 200px;

font-weight: bold">Город</span> <span style="display: table-cell; width: 200px;

font-weight: bold">Страна</span> </div> <c:forEach var="city" items="${countries}"

varStatus="loop"> <p style="display: table"> <a href="http://google.com/#q=$

{fn:replace(city,' ','+')}" target="_blank" title="Найти город в Google"><label

for="country_${loop.index} " style="di

splay: table-cell; width: 200px; cursor: pointer;">${city}</label></a>

<input name="country_${loop.index}" style="display: table-cell; width: 200px" type="text" required/>

</p> <input name="load_cities" type="hidden"

value="true"/> <input name="cities_size" type="hidden" value="$

{countriesSize}"/> </c:forEach><input type="submit" value="Загрузить

города"></form></body>Данная страница получает список городов, для которых не были

найдены страны в базе данных. Используя специальный тег c:forEach, 31

Page 32: gsu.bydl.gsu.by/Images/_i4f/_diploms/KRAVCHENKO.docx · Web view5.3 По мере выполнения программы, она выводит предупреждения в консоль.

происходит итерация по списку переданных городов, где для каждого создается элемент, содержащий название города и ссылку для поиска его по названию в поисковой системе Google, а также поле для ввода страны, которой соответствует этот город. Также, на странице представлены дополнительные поле для ввода, невидимые пользователю. Они необходимы для корректной обработки результатов, полученных с этой страницы в сервлете LoadOlympResultsServlet. Для отправки данных предоставлено поле для ввода типа input, которое на интерфейсе представлено кнопкой, по нажатию на которую произойдет перенаправление пользователя на страницу ввода степеней дипломов для команд либо страницу окончания загрузки.

Рассмотрим страницу olymp-res-diploms.jsp, отвечающую за отображение списка команд, для которых необходимо задать степени дипломов.

<body><div style='padding-bottom: 20px;'> <a href="http://neerc.ifmo.ru/school/archive/${year}-$

{year + 1}/ru-olymp-team-russia-${year}-standings.html" target="_blank">Таблица результатов</a></div><form method='POST' action='load-olymp-results.jsp'> <div> <span style="display: table-cell; width: 350px;

font-weight: bold">Команда</span> <span style="display: table-cell; width: 260px;

font-weight: bold">Степень диплома (0 - нет диплома)</span> </div> <c:forEach var="team" items="${teams}" varStatus="loop"> <p style="display: table"> <label for="team_${loop.index} " style="display:

table-cell; width: 350px">${team}</label> <input name="team_${loop.index}" style="display:

table-cell; width: 50px" type="text" value="0"/> </p> <input name="load_diploms" type="hidden"

value="true"/> <input name="teams_size" type="hidden" value="$

{teamsSize}"/> </c:forEach> <input type="submit" value="Загрузить диплом для

команд"></form></body>В страницу передается список команд, степени дипломов которым

необходимо задать. Используя тег c:forEach, для каждой команды будет создан элемент с ее названием и соответствующий элемент для ввода степени диплома, в котором по умолчанию будет задано значение 0. Также, как и в случае со страницей загрузки стран для городов, на странице присутствуют скрытые поля, необходимые для корректной обработки данных формы

32

Page 33: gsu.bydl.gsu.by/Images/_i4f/_diploms/KRAVCHENKO.docx · Web view5.3 По мере выполнения программы, она выводит предупреждения в консоль.

сервлетом. Отправка данных происходит по нажатию на кнопку «Загрузить диплом для команд», представленную элементом input с типом «submit».

Также на странице предоставлена ссылка на страницу результатов олимпиады (для удобства).

Наконец, рассмотрим страницу olymp-res-finished.jsp, представляющую собой страницу с информацией об окончании загрузки олимпиады.

<html><head> <title>Результаты загружены</title></head><body><div>Результаты олимпиады успешно загружены.</div><a href="/olymp/result/teamInter.asp"

target="_blank">Перейти на страницу олимпиад</a></body></html>Как можно видеть, страница полностью статична и предоставляет

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

3.2 Классы и методы

Основная работа с данными происходит в методе doPost класса LoadOlympResultsServlet. Рассмотрим его более детально. Сначала происходит проверка на то, не является ли полученный запрос – данными со страницы olymp-res-diploms.jsp, представляющие собой список степеней диплома для белорусских команд:

String loadDiploms = request.getParameter("load_diploms"); if (loadDiploms != null &&

Boolean.valueOf(loadDiploms)) { try { loadDiplomsAndResults(request, response); } catch (SQLException e) { throw new RuntimeException(e); } return; }Как можно видеть, в случае, когда данные действительно пришли из

olymp-res-diploms.jsp, вызывается метод loadDiplomsAndResults, куда передаются объекты, представляющий собой HTML-запрос и HTML-ответ.

Далее, если данные получены не из olymp-res-diploms.jsp, происходит проверка на то, получены ли они из olymp-res-countries.jsp. За это отвечает следующий участок кода:

String loadCities = request.getParameter("load_cities");33

Page 34: gsu.bydl.gsu.by/Images/_i4f/_diploms/KRAVCHENKO.docx · Web view5.3 По мере выполнения программы, она выводит предупреждения в консоль.

if (loadCities != null && Boolean.valueOf(loadCities) && citiesWithNoCountries != null) {

try { loadCountriesForCities(request, response); } catch (SQLException e) { throw new RuntimeException(e); } return; }Как можно видеть, в случае, когда данные действительно пришли из

olymp-res-countries.jsp, вызывается метод loadCountriesForCities, куда передаются объекты, представляющий собой HTML-запрос и HTML-ответ.

Если же запрос был получен ни от olymp-res-diploms.jsp, ни от olymp-res-countries.jsp, значит необходимо вызвать логику обработки данных для запроса со страницы olymp-res.jsp:

startDate = request.getParameter("startDate"); endDate = request.getParameter("endDate"); int olympTypeInt =

Integer.valueOf(request.getParameter("ot")); int year =

Integer.valueOf(request.getParameter("y")); OlympType olympType = olympTypeInt == 0 ?

OlympType.VKOSHP : OlympType.undefined;String result; try { result =

LoadOlympResultsService.loadOlympResults(olympType, year); } catch (SQLException e) { throw new RuntimeException(e); } this.year = year; this.olympType = olympType;Здесь данные из объекта request, представляющего собой HTML-

запрос, преобразуются в соответствующие типы данных Java. Также определяется тип олимпиады, который вместе с годом и датами проведения заносится во внутренние переменные класса LoadOlympResultsServlet. Также, здесь происходит загрузка результатов олимпиады для определенного типа олимпиады и года путем вызова метода LoadOlympResultsService.loadOlympResults, результат которого заносится в переменную result и представляет собой строку определенного формата.

Далее происходят следующие преобразования:ResultContainer res =

LoadOlympResultsService.generateResult(result); List<String> countriesNotFound =

res.getCountriesNotFound(); if (countriesNotFound.isEmpty()) { if (res.getGomelTeamNames().isEmpty()) { createCourseAndFinish(res, new

HashMap<String, Integer>(), request, response); } else {

34

Page 35: gsu.bydl.gsu.by/Images/_i4f/_diploms/KRAVCHENKO.docx · Web view5.3 По мере выполнения программы, она выводит предупреждения в консоль.

forwardToDiploms(res.getGomelTeamNames(), request, response);

} return; }

List<String> parsedResult = new ArrayList<String>();

for (String c : countriesNotFound) { parsedResult.add(c.split(",")[0]); } citiesWithNoCountries = parsedResult;

request.setAttribute("countries", parsedResult); request.setAttribute("countriesSize",

parsedResult.size());Изначально, происходит преобразование переменной типа results в

объект класса ResultContainer, который содержит XML-файл и список городов, страны у которых не были найдены в БД, а также список команд, для которых нужно задать степени дипломов, путем вызова метода LoadOlympResultsService.generateResult. Если список городов, страны для которых не были найдены пуст, как и список команд, для которых еще не были заданы дипломы, то произойдет окончательная загрузка результатов в БД и перенаправление на страницу olymp-res-finished.jsp. Если же список городов, страны для которых не были найдены пуст, но при этом список команд, для которых еще не были заданы степени дипломов не пуст, то произойдет перенаправление на страницу olymp-res-diploms.jsp, где в параметрах запроса будут указаны команды. Наконец, если список городов, для которых не были найдены страны не пуст, то произойдет перенаправление на страницу olymp-res-countries.jsp, где в параметрах запроса будет указан список этих городов.

Далее, рассмотрим класс LoadOlympResultsService, методы которого вызываются из класса LoadOlympResultsServlet, описанного выше.

35

Page 36: gsu.bydl.gsu.by/Images/_i4f/_diploms/KRAVCHENKO.docx · Web view5.3 По мере выполнения программы, она выводит предупреждения в консоль.

private static final Map<OlympType, Olympiad> olymps = new HashMap<OlympType, Olympiad>();

private static Olympiad currentOlymp = null; static { olymps.put(OlympType.VKOSHP, new VKOSHP()); } public static String loadOlympResults(OlympType

olympType, int year) throws SQLException, IOException { currentOlymp = olymps.get(olympType); if (currentOlymp == null) { throw new RuntimeException("Olymp type not

found: " + olympType); } currentOlymp.init(year); Long courseId =

getCourseID(currentOlymp.getParentID(), year); if (courseId > -1) { currentOlymp.removeResults(courseId); } String url = currentOlymp.getResultsURL(); return

currentOlymp.parseResults(loadContentsFromURL(url)); }На данном участке кода можно видеть инициализацию статической

переменной olymps, представляющей собой отображение типа олимпиады на объект класса, соответствующего данной олимпиаде. Далее он инициализируется типом и объектом классов, представляющих собой ВКОШП.

Метод loadOlympResultsService принимает в качестве параметров тип и год проведения олимпиады. Используя тип, берется соответствующий ему объект класса из переменной olymps и результат заносится в переменную currentOlymp. Далее, происходит инициализация объекта олимпиады путем вызова у него метода init и передачей ему года проведения олимпиады. Затем происходит проверка на то, не существует ли в базе данных результатов олимпиады данного типа с таким же годом проведения. Если они существуют, то необходимо их перед загрузкой новых результатов удалить, что приводит к вызову метода removeResults. Для загрузки результатов, необходимо сначала получить соответствующий им URL, что осуществляется с помощью вызова метода getResultsURL у объекта олимпиады. После этого, у того же объекта олимпиады вызывается парсер результатов путем вызова метода parseResults, куда передается HTML-страница, полученная в результате вызова метода loadContentsFromURL класса LoadOlympResultsService, который в свою очередь получает URL-адрес необходимой страницы в качестве параметра.

36

Page 37: gsu.bydl.gsu.by/Images/_i4f/_diploms/KRAVCHENKO.docx · Web view5.3 По мере выполнения программы, она выводит предупреждения в консоль.

public static void createCourseAndLoadResults(int year, String startDate, String endDate, String res, Map<String, Integer> teamNameToDiplom) throws Exception {

int courseID = createCourse( year, 3, currentOlymp.getTitle(), currentOlymp.getShortTitleEN(), currentOlymp.getFullStartDate(startDate), currentOlymp.getFullEndDate(endDate), currentOlymp.getParentID()); String newRes = res .replace("name=\"Set

name\"", "name=\"" + currentOlymp.getShortTitleRU() + "\"") .replace("courseID=\"XX\"",

"courseID=\"" + courseID + "\"") .replace("openDate=\"XX.XX.XXXX\"",

"openDate=\"" + startDate + "." + year + "\"") .replace("collapseDate=\"XX.XX.XXXX\

"", "collapseDate=\"" + endDate + "." + year + "\""); String finalRes = putDiplomasForTeams(newRes,

teamNameToDiplom); log.debug(finalRes); int hid = LoadXMLtoDB.loadResults(finalRes); loadTeamResults( hid, courseID, currentOlymp.getTitle(), currentOlymp.getShortTitleEN()); }Метод createCourseAndLoadResults класса LoadOlympResultsService

производит все основные действия по загрузке результатов олимпиады в базу данных. Сначала, он создает новую запись в таблице Courses, вызывая метод createCourse этого же класса. Далее, он подставляет в полученный XML-файл информацию о названии олимпиады, ее courseID (ID записи в таблице Courses), дату начала и окончания. После этого, дополняет информацию о степенях дипломах для команд и затем осуществляет загрузку данных о результатах олимпиады путем передачи XML-файла с результатами в метод LoadXMLToDb.loadResults. После этого, для того чтобы отображать ссылку на результаты на странице со списком олимпиад на сайте dl.gsu.by, вызывается метод loadTeamResults, производящий последние манипуляции с данными о результатах олимпиады в БД.

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

37

Page 38: gsu.bydl.gsu.by/Images/_i4f/_diploms/KRAVCHENKO.docx · Web view5.3 По мере выполнения программы, она выводит предупреждения в консоль.

public static void loadMissingCountriesForCities(Map<String, String> citiesToCountries) {

List<Country> countries = Arrays.asList(Country.getAllCountries());

Map<String, Country> countryNameToCountry = new HashMap<String, Country>();

for (Country c : countries) { countryNameToCountry.put(c.getName(0).toLowerCase(),

c); } Map<String, Country> citiesToCountriesObject = new

HashMap<String, Country>(); for (Map.Entry<String, String> entry :

citiesToCountries.entrySet()) { citiesToCountriesObject.put(entry.getKey(),

countryNameToCountry.get(entry.getValue().toLowerCase())); } for (Map.Entry<String, Country> entry :

citiesToCountriesObject.entrySet()) { if (entry.getValue() != null) { City.registerCity(entry.getKey(), 0,

entry.getValue()); } } return; }В качестве параметра этот метод принимает отображение названия

города на название страны. В первую очередь, происходит загрузка из БД списка всех стран, где каждая страна представлена объектом класса Country. После этого, на основе вышеупомянутого списка, создается отображение названия страны на объект класса Country. Далее, на основе обоих отображений создается еще одно, которое отображает название города на соответствующую ему страну, представленную теперь объектом класса Country. Наконец, для каждого элемента этого отображения вызывается метод City.registerCity, в который передается название города и объект класса Country, представляющий соответствующую этому городу страну.

public static ResultContainer generateResult(String input) throws IOException {

try { return TextToXML2.getXMLAsString(input); } catch (ParserException e) { throw new IOException(e); } }Метод generateResult класса LoadOlympResultsService необходим для

преобразования строки определенного формата в объект класса ResultContainer, который включает в себя: результирующий XML-файл, список городов, страны для которых не были найдены, а также список команд, для которых необходимо задать степени дипломов.

38

Page 39: gsu.bydl.gsu.by/Images/_i4f/_diploms/KRAVCHENKO.docx · Web view5.3 По мере выполнения программы, она выводит предупреждения в консоль.

Рассмотрим класс TextToXML2 и его методы getXMLAsString и buildXMLFromFile.

public static ResultContainer getXMLAsString(String txtContents) throws IOException, ParserException {

TextToXML2 converter = new TextToXML2(); return converter.buildXMLFromFile(txtContents); }Метод getXMLAsString создает объект класса TextToXML2 и вызывает

метод buildXMLFromFile, передавая туда переданную ему же строку.Метод buildXMLFromFile (см. Приложение А) изначально объявляет

переменные для количества команд, которым необходимо указать степени дипломов, список результатов (объектов класса ResultRecord), парсера результатов, языка. Затем происходит инициализация парсера и передача ему строки определенного формата, которую он преобразовывает в список объектов класса ResultRecord. После этого, происходит итерирование этого списка для того чтобы выяснить, для каких городов необходимо загрузить страны, а также для каких команд необходимо задать степени дипломов. В добавок к этому, если у команды перечислено несколько городов, поиск страны будет осуществляться только по первому.

После вышеуказанного, метод создаст и инициализирует объект класса Velocity из библиотеки Apache Velocity. В него передастся список результатов и затем вызовется метод merge, который создаст XML-файл, содержимое которого поместится в строку, представленную переменной sw. После всего, метод вернет объект класса ResultContainer, который будет содержать XML-файл, список городов, страны для которых не были найдены и список команд, для которых необходимо загрузить данные о степенях дипломов.

Рассмотрим класс LoadXMLToDB, производящий загрузку XML-файла в базу данных.

public class LoadXMLtoDB { public static int loadResults(String inputContents)

throws Exception { ResultXML rXML = new

ResultXML(ResultXML.SaveResultInDB); InputStream s = new BufferedInputStream(new

ByteArrayInputStream(inputContents.getBytes())); List<Long> result = rXML.parseAndGetHeaderIDS(new

InputSource(s)); Collections.sort(result); return result.get(0).intValue(); }}Как можно видеть, в классе представлен единственный статический

метод, который осуществляет загрузку результатов под названием loadResults. В этом методе создается объект класса ResultXML, которому передается специальный режим (в нашем случае он означает сохранение результатов в БД). После этого, переданная в метод строка преобразуется в

39

Page 40: gsu.bydl.gsu.by/Images/_i4f/_diploms/KRAVCHENKO.docx · Web view5.3 По мере выполнения программы, она выводит предупреждения в консоль.

поток и передается методу parseAndGetHeaderIDS класса ResultXML, который производит обработку переданного XML и загрузку данных в БД и возвращает список HeaderItemID – идентификаторов записей, записанных в БД. После этого, данный список сортируется и возвращается его минимальное значение, преобразованное в тип данных int. Это необходимо для последующего корректного отображения ссылки на результаты проведения олимпиады.

40

Page 41: gsu.bydl.gsu.by/Images/_i4f/_diploms/KRAVCHENKO.docx · Web view5.3 По мере выполнения программы, она выводит предупреждения в консоль.

4. Технология использования

4.1 Технология автоматической загрузки результатов ВКОШП

Для загрузки результатов ВКОШП пользователю необходимо перейти на страницу загрузки результатов олимпиад находящуюся по адресу http://dl.gsu.by/admin/olymp/rimport/olymp-res.jsp. (рисунок 26)

Рисунок 26 - Главная страница загрузки результатов

На данной странице необходимо заполнить все поля соответствующей информацией: год проведения олимпиады, дату начала проведения олимпиады в формате день/месяц, дату окончания проведения олимпиады. После этого пользователю необходимо загрузить результаты, нажав на кнопку «Загрузить результаты олимпиады». После этого перед ним появится список городов, для которых не найдены страны (рисунок 27).

41

Page 42: gsu.bydl.gsu.by/Images/_i4f/_diploms/KRAVCHENKO.docx · Web view5.3 По мере выполнения программы, она выводит предупреждения в консоль.

Рисунок 27 – Страница со списком городов, для которых не были найдены страны

Пользователю необходимо вручную ввести названия городов (регистр не важен). Для удобства поиска стран добавлен поиск в google. Для этого необходимо просто щелкнуть по городу и автоматически пользователь будет перенаправлен на страницу с результатами поиска. После ввода всех стран необходимо нажать «Загрузить города».

После загрузки стран всем белорусским командам необходимо проставить степени полученных ими дипломов. На странице необходимо проставить все дипломы вручную. Для удобства просмотра таблицы основных результатов на страницу добавлена ссылка на таблицу результатов. По умолчанию все степени дипломов равны 0. Диплом 1 степени – это цифра 1 в поле ввода, диплом второй степени - 2 и третья степень диплома – это, соответственно, цифра 3 в поле ввода. После ввода необходимых данных необходимо нажать на кнопку «Загрузить дипломы для команд». (рисунок 28)

42

Page 43: gsu.bydl.gsu.by/Images/_i4f/_diploms/KRAVCHENKO.docx · Web view5.3 По мере выполнения программы, она выводит предупреждения в консоль.

Рисунок 28– Загрузка дипломов для команд

После всех манипуляций появится сообщение о загрузке результатов и ссылка для просмотра результатов (рисунок 29).

Рисунок 29– Страница для загрузки дипломов

После перехода на страницу результатов загрузки олимпиады появится следующее окно (рисунок 30):

Рисунок 30 – Страница с результатами загрузки

В некоторых случаях необходимо редактировать составы команд. Для этого необходимо перейти по ссылке «Редактирование команд» на главной странице (рисунок 31).

43

Page 44: gsu.bydl.gsu.by/Images/_i4f/_diploms/KRAVCHENKO.docx · Web view5.3 По мере выполнения программы, она выводит предупреждения в консоль.

Рисунок 31 – Страница с ссылкой на редактирование команд

После перехода по ссылке на экране появится страница со списком всех имеющихся белорусских команд (рисунок 32).

Рисунок 32 – Страница со списком всех белорусских команд44

Page 45: gsu.bydl.gsu.by/Images/_i4f/_diploms/KRAVCHENKO.docx · Web view5.3 По мере выполнения программы, она выводит предупреждения в консоль.

Пользователю необходимо выбрать нужную команду, щелкнув по ней мышью. Появится следующая страница (на примере команды Гомель-1). (рисунок 33)

Рисунок 33 – Страница для редактирования команд

На данной странице необходимо ввести основную информацию о составе команды: (ФИО участника, школа, класс, дата вступления в команду). Также для удобства использования добавлена инструкция по заполнению данной страницы. После всех вышеуказанных действий получаем страницу с загруженными результатами (рисунок 34).

Рисунок 34– Страница с загруженными результатами

Загрузка результатов завершена.

45

Page 46: gsu.bydl.gsu.by/Images/_i4f/_diploms/KRAVCHENKO.docx · Web view5.3 По мере выполнения программы, она выводит предупреждения в консоль.

4.2 Технология загрузки результатов Белорусской республиканской олимпиады

Для загрузки результатов Белорусской республиканской олимпиады по информатике, необходимо перейти на страницу http://dl.gsu.by/admin/olymp/rimport/olymp-res.jsp. Затем пользователю в выпадающем списке под названием "Выберите олимпиаду" необходимо выбрать пункт "Республика".

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

После ввода всех необходимых данных, нужно нажать на кнопку "Загрузить результаты олимпиады". (рисунок 35)

Рисунок 35 – Страница загрузки результатов

Далее, пользователь будет перенаправлен на страницу, где будет предоставлена информация о произведенных действиях и предоставлен ID записи, добавленной в таблицу Courses (Необходим для последующей загрузки). Страница представлена на рисунке 36.

Рисунок 36 – Страница olymp-res-respublica.jsp

46

Page 47: gsu.bydl.gsu.by/Images/_i4f/_diploms/KRAVCHENKO.docx · Web view5.3 По мере выполнения программы, она выводит предупреждения в консоль.

Также, на этой странице предоставлено поле для ввода HeaderItemId из пункта 11.1 инструкции (см. технологию ручной загрузки), позволяющее загрузить последние необходимые данные для олимпиады в базу данных, после загрузки соответствующего XML-файла с помощью r-import. Для этого, необходимо выполнить следующие пункты инструкции:

Загрузить результаты проведения олимпиады в базу book.mdb.Результаты представлены таблицей Respublica в базе book.mdb

(рисунок 37).

Рисунок 37 – Таблица Respublica в базе book.mdb

В 2017 году оригинальные результаты представлены в виде следующего xls файла (рисунок 38).

Рисунок 38 – Отображение результатов Белорусской республиканской олимпиады по программированию – 2017

47

Page 48: gsu.bydl.gsu.by/Images/_i4f/_diploms/KRAVCHENKO.docx · Web view5.3 По мере выполнения программы, она выводит предупреждения в консоль.

Проще всего создать новый лист в xls, преобразовать данные в формат таблицы Respublica и выполнить import данных в базу book.mdb.

Преобразовываем данные в соответствии с форматом таблицы Respublica. Поле Price означает вид награды (7 – Диплом 1-й степени, 8 – Диплом 2-й степени, 9 – Диплом 3-й степени, 10 – Похвальный лист, 12 – отсутствие награды).

Все region у всех contestant должны быть описаны в таблице Regions базы данных ROlimp. Если у вас г. Гомель в атрибуте region с пробелом, то необходимо его убрать (лучше всего это выполнить на стадии подготовки xls в book.mdb, чтобы избежать лишней работы по корректировки данных). Тоже касается и других значений (данные должны полностью соответствовать таблице Regions).

Далее открываем book.mdb. Из всплывающего меню выбираем Import… (рисунок 39).

Рисунок 39 – Выбор пункта меню

Выбираем наш xls файл с преобразованными данными. Далее выбираем нашу страницу, нажимаем Next (рисунок 40).

48

Page 49: gsu.bydl.gsu.by/Images/_i4f/_diploms/KRAVCHENKO.docx · Web view5.3 По мере выполнения программы, она выводит предупреждения в консоль.

Рисунок 40 – Выбор страницы

Далее выбираем по умолчанию (рисунок 41).

Рисунок 41 – Выбор по умолчанию

Импортируем данные в таблицу Respublica (рисунок 42).

49

Page 50: gsu.bydl.gsu.by/Images/_i4f/_diploms/KRAVCHENKO.docx · Web view5.3 По мере выполнения программы, она выводит предупреждения в консоль.

Рисунок 42 – Импорт данных

Завершаем Import.Закрываем файл book.mdb (если не закрыть файл, результаты могут не

отображаться из-за совместного доступа к файлу).Снова заходим по ссылке 2017 (Гомель).Отображаются результаты проведения нашей олимпиады (рисунок 43).

50

Page 51: gsu.bydl.gsu.by/Images/_i4f/_diploms/KRAVCHENKO.docx · Web view5.3 По мере выполнения программы, она выводит предупреждения в консоль.

Рисунок 43 – Отображение результатов проведения олимпиады

Если выполнять переход по ссылкам на различные виды отчетов (Статистика по дипломам, Статистика за разные годы, и т.д.), то некоторые из отчетов будут не доступны, а некоторые не будут содержать данных по нашей олимпиаде. Причиной является отсутствие необходимых данных в базе Rollinp MS SQL Server-а.

Загружаем необходимые данные в ROlimp. Экспортируем данные по нашей олимпиаде из book.mdb в xml файл. Открываем book.mdb. Находим модуль Functions (рисунок 44).

51

Page 52: gsu.bydl.gsu.by/Images/_i4f/_diploms/KRAVCHENKO.docx · Web view5.3 По мере выполнения программы, она выводит предупреждения в консоль.

Рисунок 44 – Модуль Functions

Заходим в него. Находим функцию work и меняем в ней файл в который будет происходить export. В моем случае это будеn d:\bel (Set f = fs.OpenTextFile("d:\bel" & rYear & ".xml", 2, True, TristateFalse))/

Создаем процедуру для запуска экспорта:Sub export()Call work(2017)End SubЗапускаем процедуру (рисунок 45).

Рисунок 45 – Запуск процедуры

В моем случае был создан файл d:\bel2017.xml.Курс для нашей олимпиады в базе ROlimp, таблице Courses уже создан

автоматически.Необходимо знать ID (который был сгенерирован SQL Server

автоматически) с которым был создан данный курс, т.к. он понадобится нам в дальнейшем. В моем случае ID = 74.

Подготавливаем bel2010.xml к import-у в ROlimp.

52

Page 53: gsu.bydl.gsu.by/Images/_i4f/_diploms/KRAVCHENKO.docx · Web view5.3 По мере выполнения программы, она выводит предупреждения в консоль.

Устанавливаем courseID в ID нашего курса.<competitionInfo name="Республика 2010" contestType="USER" courseID="74" openDate="24.03.2010"

collapseDate="29.03.2010" language="rus" > <header> <day name="Day 1"> <task name="Task 1" /> <task name="Task 2" /> <task name="Task 3" /> </day> <day name="Day 2"> <task name="Task 4" /> <task name="Task 5" /> <task name="Task 6" /> </day></header></competitionInfo>Опять же, как сказано выше, все region у всех contestant должны быть

описаны в ROlimp таблица Regions. Замечание: Если у вас в bel2010.xml г. Минск в атрибуте region с пробелом, то необходимо его убрать (лучше всего это выполнить на стадии подготовки xls в book.mdb, чтобы избежать лишней работы по корректировки данных). Тоже касается и других значений (данные должны полностью соответствовать таблице Regions).

Импортируем bel2017.xml в ROlimp.Пожалуйста, убедитесь, что вы сделали backup базы ROlimp.Проверяем параметры соединения с базой в olymp.db.DBUtil

(находится в модуле r-olimp) (username, password, jdbcConnection).Находим класс LoadXMLtoDB.Пожалуйста, убедитесь, что используется следующий способ создания ResultXML ResultXML rXML = new

ResultXML(ResultXML.SaveResultInDB);При запуске export я использовала следующий метод:FileReader r = new FileReader("D:\\Projects\\DL\\src\\svn\\

r-import\\trunk\\dev\\xmls\\bel2010.xml"); rXML.parseStream(new InputSource(r));Далее запускаем класс на выполнение.В консоль выводится информация по мере, import-а данных. Смотрите

export_to_sqlserver\log.txt. Теперь будут доступны все виды отчетов.Если перейти по отчету все гомельчане, то появится следующая

статистика (рисунок 46).

53

Page 54: gsu.bydl.gsu.by/Images/_i4f/_diploms/KRAVCHENKO.docx · Web view5.3 По мере выполнения программы, она выводит предупреждения в консоль.

Рисунок 46 – Отображение результатов всех гомельчан в 2017 году

Ссылка «Таблица результатов» для нашего соревнования будет не-верной. Для обновления ссылки необходимо ввести на странице olymp-res-respublica.jsp представленной на рисунке 47, в поле для ввода HeaderItemId значение, которое позволяет загрузить последние необходимые данные для олимпиады в базу данных, после загрузки соответствующего XML-файла с помощью r-import. HeaderItemID был сгенерирован при импорте данных в базу ROlimp из bel2017.xml. Его можно посмотреть в лог файле.

Рисунок 47 – Страница olymp-res-respublica.jsp

Если участник не присутствует в базе ROlimp, то при загрузке XML он создается автоматически. К сожалению школу участника узнать не удается и из-за отсутствия данной информации некоторые отчеты могут выглядеть неполными. Так, например, отчет “Статистика за разные годы” (рисунок 48).

54

Page 55: gsu.bydl.gsu.by/Images/_i4f/_diploms/KRAVCHENKO.docx · Web view5.3 По мере выполнения программы, она выводит предупреждения в консоль.

Рисунок 48 – Отображение статистики за разные годы

С помощью следующего SQL скрипта можно узнать у каких участников в каких курсах не заполнена информация об учебном заведении:

select * from (SELECT HIM.CourseID,-1 TeamID,RC.UserID,RC.value,(

SELECT top 1 Name FROM UsersHistory WHERE date <= OpenDate and ID= RC.UserID ORDER BY date desc) as Name, ( SELECT top 1 City FROM UsersHistory WHERE date <= OpenDate and ID= RC.UserID ORDER BY date descas CityID, ( SELECT top 1 Region FROM UsersHistory WHERE date <= OpenDate and ID= UserID ORDER BY date desc) as RegionID, ( SELECT top 1 Country FROM UsersHistory WHERE date <= OpenDate and ID= RC.UserID ORDER BY date desc) as CountryID,( SELECT top 1 Form FROM UsersHistory WHERE date <= OpenDate and ID= RC.UserID ORDER BY date desc)as FormID, ( SELECT top 1 School FROM UsersHistory WHERE date <=

OpenDate and ID= RC.UserID ORDER BY date desc) as School, OpenDate FROM dl2resultscell RC INNER JOIN dl2resultsHeaderItemmapping HIM ON HIM.HeaderItemID= RC.HeaderItemID

WHERE typeid = 9 and userID> 200000) as xxx where school is null and regionid = 3 order by courseid desc

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

Загрузка закончена.55

Page 56: gsu.bydl.gsu.by/Images/_i4f/_diploms/KRAVCHENKO.docx · Web view5.3 По мере выполнения программы, она выводит предупреждения в консоль.

5. Результаты апробации

5.1 Результаты апробации ВКОШП

При загрузке Всероссийской командной олимпиады школьников по программированию были созданы и обновлены записи в таблицах базы данных ROlimp. Вследствие этого были обновлены следующие страницы.

Страница с результатами загрузки олимпиады, на которой представлен год загрузки и команды участники. Страница находится по адресу http://dl.gsu.by/olymp/result/teamInter.asp. Страница представлена на рисунке 49.

Рисунок 49 – Страница с результатами олимпиад56

Page 57: gsu.bydl.gsu.by/Images/_i4f/_diploms/KRAVCHENKO.docx · Web view5.3 По мере выполнения программы, она выводит предупреждения в консоль.

Перейти на страницу с результатами всех команд можно по ссылке http://dl.gsu.by/olymp/xrestable.jsp?hd=2&hid=785&pi=6&pi=7&u.c=107&lng=rus&u.a&c.l=4&c.n=2&c.s=2&c.s=7.. На данной странице показано итоговое место команды в общем зачете, название команды, страна и город команды, время, затраченное на выполнение задач, количество решенных задач. Страница с результатами представлена на рисунке 50.

Рисунок 50 – Страница просмотра результатов всех команд-участников

Состав команды и ее результаты можно посмотреть просто нажав на нее. Страница для команды Гомель-1 находится по адресу http://dl.gsu.by/servlet/olympResultsShowUserRank?u.id=13&u.c=107&lng=rus На данной странице представлен состав команды, а также результаты участия команды в соревнованиях прошлых лет (рисунок 51).

57

Page 58: gsu.bydl.gsu.by/Images/_i4f/_diploms/KRAVCHENKO.docx · Web view5.3 По мере выполнения программы, она выводит предупреждения в консоль.

Рисунок 51 – Просмотр состава и результата команды Гомель-1

Страница с результатами загрузки результатов ВКОШП-2015 находится по адресу http://dl.gsu.by/olymp/xrestable.jsp?hd=2&hid=773&pi=6&pi=7&u.c=106&lng=rus&u.a&c.l=4&c.n=2&c.s=2&c.s=7. Страница представлена на рисунке 52.

Рисунок 52 – Страница результатов ВКОШП-201558

Page 59: gsu.bydl.gsu.by/Images/_i4f/_diploms/KRAVCHENKO.docx · Web view5.3 По мере выполнения программы, она выводит предупреждения в консоль.

Страница с результатами гомельчан на международных командных олимпиадах представлена по адресу http://dl.gsu.by/olymp/result/personalResult.asp. На странице отображено имя участника, количество заработанных им дипломов и года участия. Скриншот страницы приведен на рисунке 53.

Рисунок 53 – Результаты гомельчан в международных командных олимпиадах

Страница с участием учебных заведений в завоевании медалей и дипломов на международных соревнованиях. Ссылка на страницу: http://dl.gsu.by/olymp/result/SchoolInter.asp. Страница показана на рисунке 54.

59

Page 60: gsu.bydl.gsu.by/Images/_i4f/_diploms/KRAVCHENKO.docx · Web view5.3 По мере выполнения программы, она выводит предупреждения в консоль.

Рисунок 54– Участие учебных заведений

5.2 Результаты апробации Республиканской олимпиады

Главная страница со списком всех загруженных олимпиад находится по адресу http://dl.gsu.by/olymp/result.asp. Скриншот страницы представлен на рисунке 55.

60

Page 61: gsu.bydl.gsu.by/Images/_i4f/_diploms/KRAVCHENKO.docx · Web view5.3 По мере выполнения программы, она выводит предупреждения в консоль.

Рисунок 55 – Страница со списком всех олимпиад

Страница с результатами Белорусской республиканской олимпиады может быть получена по следующей ссылке http://dl.gsu.by/olymp/showRes.asp?id=231. Страница представлена на рисунке 56.

Рисунок 56 – Страница с результатами Белорусской республиканской олимпиады

61

Page 62: gsu.bydl.gsu.by/Images/_i4f/_diploms/KRAVCHENKO.docx · Web view5.3 По мере выполнения программы, она выводит предупреждения в консоль.

Страница статистики по дипломам на республиканской олимпиаде доступна по ссылке http://dl.gsu.by/olymp/rdiplom.asp?ry=2017. Также на этой странице представлены участники, прогноз на следующий годи результаты школ в завоевании дипломов и похвальных листов.(рисунок 57)

Рисунок 57 – Страница статистики по дипломам

На странице http://dl.gsu.by/olymp/rgomel.asp представлены общие результаты участия областей (участник/диплом+похвальный лист), статистика по школам гомельской области, распределение дипломов по степеням (область можно выбрать), распределение дипломов по классам, а также 3 лучших места по классам и все места участников по гомельской области. (рисунок 58-63)

62

Page 63: gsu.bydl.gsu.by/Images/_i4f/_diploms/KRAVCHENKO.docx · Web view5.3 По мере выполнения программы, она выводит предупреждения в консоль.

Рисунок 58 – Общие результаты (дипломы и похвальные листы)

Рисунок 59 – Статистика по гомельским школам

63

Page 64: gsu.bydl.gsu.by/Images/_i4f/_diploms/KRAVCHENKO.docx · Web view5.3 По мере выполнения программы, она выводит предупреждения в консоль.

Рисунок 60 – Распределение дипломов по степеням

Рисунок 61– Страница с распределением дипломов по классам

64

Page 65: gsu.bydl.gsu.by/Images/_i4f/_diploms/KRAVCHENKO.docx · Web view5.3 По мере выполнения программы, она выводит предупреждения в консоль.

Рисунок 62– Страница с лучшими местами по классам

Рисунок 63– Все места участников

Страница личных достижений гомельчан на республиканских олимпиадах находится по адресу http://dl.gsu.by/olymp/rpersonal.asp . На странице указано имя участника, школа, года участия в республиканской олимпиаде, результат (количество дипломов и отзывов). Скриншот страницы представлен на рисунке 64.

65

Page 66: gsu.bydl.gsu.by/Images/_i4f/_diploms/KRAVCHENKO.docx · Web view5.3 По мере выполнения программы, она выводит предупреждения в консоль.

Рисунок 64 – Персональные достижения гомельчан

Страница результатов гомельчан на республиканских олимпиадах по годам находится по адресу http://dl.gsu.by/olymp/info/allgomel. На странице представлен список всех гомельчан, отсортированный по классам с результатом. Страница отображена на рисунке 65.

66

Page 67: gsu.bydl.gsu.by/Images/_i4f/_diploms/KRAVCHENKO.docx · Web view5.3 По мере выполнения программы, она выводит предупреждения в консоль.

Рисунок 65 – Достижение гомельчан в 2017 году

Страница результатов по классам находится по адресу http://dl.gsu.by/olymp/showres.asp?id=231&nc=0. На данной странице отображено место команды в общем зачете, имя участника, команда, которую он представлял, количество решенных задач и полученных очков, а также полученная награда. Скриншот страницы представлен на рисунке 66.

Рисунок 66 – Статистика по классам

67

Page 68: gsu.bydl.gsu.by/Images/_i4f/_diploms/KRAVCHENKO.docx · Web view5.3 По мере выполнения программы, она выводит предупреждения в консоль.

Заключение

В ходе дипломной работы были изучены необходимые теоретические вопросы, связанные с разработкой компонента для загрузки результатов интернет-олимпиад. Данный компонент реализован с помощью языка программирования Java и фреймворков JSP, Apache Velocity, JiXB, JDBC.

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

Средой разработки приложения являлась интегрированная среда разработки программного обеспечения IntelliJ IDEA, языком написания приложения - Java.

В ходе выполнения дипломной работы решились следующие задачи: изучение базы данных MS SQL, используемой приложением; изучение и загрузка результатов олимпиад в ручном режиме; изучение каркасов разработки JSP, ApacheVelocity, JiXB, JDBC; автоматизация загрузки результатов Всероссийской олимпиады

школьников по программированию (ВКОШП) для сайта dl.gsu.by; загрузка результатов ВКОШП за 2015 и 2016 года; автоматизация загрузки результатов республиканской олимпиады

для dl.gsu.by, загрузка результатов; реализация компонентов автоматизации. В итоге был разработан компонент, который представляет собой

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

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

68

Page 69: gsu.bydl.gsu.by/Images/_i4f/_diploms/KRAVCHENKO.docx · Web view5.3 По мере выполнения программы, она выводит предупреждения в консоль.

Список литературы

1 Брайан Хоган, HTML5 и CSS3 Веб-разработка по стандартам нового поколения. ООО Издательство «Питер», 2012 – 272 c.

2 Колисниченко, Д. PHP и MySQL. Разработка Web-приложений / Д. Колисниченко; БХВ-Петербург, 2016 – 608 с.

3 Макфарланд, Д. Большая книга CSS3 / Д. Макфарланд; издательство «Питер», 2012 – 896 с.

4 Майкл Эферган Java: справочник .- QUE Corporation, 1997, Издательство "Питер Ком", 1998

5 Герберт Ш. Java. Полное руководство.8-е изд. - СПб.: Москва, 2012. - 1140 с.: ил. - Парал. тит. англ.

6 Монахов, В. Язык программирования Java и среда NetBeans. / В. Монахов - СПб.: БХВ - Петербург, 2011. - 704 с.

7 Блинов, И. Java. Промышленное программирование / И. Блинов, В. Романчик - Минск: УниверсалПресс, 2007. - 704с.

8 Эккель, Б. Философия Java. Библиотека программиста. / Б. Эккель - 4-е изд.,доп. - СПб.: Питер, 2009. - 640с.

9 Хабибулин, И. Самоучитель Java. / И.Ш. Хабибулин. - Спб.: БХВ-Петербург, 2001. - 464с

10 Изучение технологий Java [Электронный ресурс]. - Режим доступа: http://java-course.ru/student/book1/servlet/ - Дата доступа: 9.04.2017.

69

Page 70: gsu.bydl.gsu.by/Images/_i4f/_diploms/KRAVCHENKO.docx · Web view5.3 По мере выполнения программы, она выводит предупреждения в консоль.

Приложение АРазработанный программный код

Jsp-страницыOlymp-res.jsp<%@ page contentType="text/html;charset=windows-1251" %><%@ page pageEncoding="CP1251" %><%@ taglib prefix="dl" uri='/WEB-INF/tld/dl.tld' %><%@ taglib uri="http://java.sun.com/jsp/jstl/core"

prefix="c" %><%@taglib prefix="fmt"

uri="http://java.sun.com/jsp/jstl/fmt" %>

<jsp:useBean id="now" class="java.util.Date"/><fmt:formatDate var="year" value="${now}" pattern="yyyy"/><html><head> <title>Distance Learning Belarus | Загрузка результатов

олимпиад</title> <meta http-equiv="Content-Type" content="text/html;

charset=windows-1251"></head><body><script> function showMe(e) { var element =

document.getElementById("placeSelection"); if(e.selectedIndex === 1) { element.style.display = "block"; } else { element.style.display = "none"; } }</script><form method='POST' action='load-olymp-results.jsp'> <div> <label> <span style="display: table-cell; width:

240px">Выберите олимпиаду:</span> <select onchange="showMe(this);" style="display:

table-cell; width: 200px" name="ot"> <option value="0">ВКОШП</option> <option value="1">Республика</option> </select> </label> </div> <div>&nbsp;</div> <div> <label> <span style="display: table-cell; width:

240px">Выберите год олимпиады:</span>

70

Page 71: gsu.bydl.gsu.by/Images/_i4f/_diploms/KRAVCHENKO.docx · Web view5.3 По мере выполнения программы, она выводит предупреждения в консоль.

<select style="display: table-cell; width: 200px" name="y">

<c:forEach begin="2010" end="${year}" varStatus="loop">

<option value="${loop.index}" <c:if test="${year ==

loop.index}">selected</c:if>>${loop.index}</option> </c:forEach> </select> </label> </div> <div style="margin: 15px 0"> <label> <span style="display: table-cell; width:

240px">Введите дату начала олимпиады (дд.мм):</span> <input style="display: table-cell; width: 200px"

value ="12.12" type="text" name="startDate" required/> </label> </div> <div style="margin-bottom: 15px"> <label> <span style="display: table-cell; width:

240px">Введите дату окончания олимпиады (дд.мм):</span> <input style="display: table-cell; width: 200px"

value="13.12" type="text" name="endDate" required/> </label> </div> <div id="placeSelection" style="margin-bottom: 15px;

display: none;"> <label> <span style="display: table-cell; width:

240px">Введите место проведения олимпиады:</span> <input style="display: table-cell; width: 200px"

type="text" name="place"/> </label> </div> <input type="submit" value="Загрузить результаты

олимпиады"></form><div style="padding-top: 20px"> <a href="../teams/teamlist.jsp">Редактирование

команд</a></div></body></html>Olymp-res-respulica.jsp<%@ page contentType="text/html;charset=windows-1251" %><%@ page pageEncoding="CP1251" %><%@ taglib prefix="dl" uri='/WEB-INF/tld/dl.tld' %><%@ taglib uri="http://java.sun.com/jsp/jstl/core"

prefix="c" %><%@taglib prefix="fmt"

uri="http://java.sun.com/jsp/jstl/fmt" %>71

Page 72: gsu.bydl.gsu.by/Images/_i4f/_diploms/KRAVCHENKO.docx · Web view5.3 По мере выполнения программы, она выводит предупреждения в консоль.

<html><head> <title>Distance Learning Belarus | Загрузка результатов

олимпиад</title> <meta http-equiv="Content-Type" content="text/html;

charset=windows-1251"></head><body><div>Загрузка результатов Республиканской олимпиады по

информатике ${year}:</div><div>Создана запись в таблице Calendar согласно пункта 3

инструкции.</div><div>Создана запись в таблице Courses согласно пункта 9.2

инструкции.</div><div>CourseID для использования в пункте 9.3.1: <b>$

{courseID}</b>.</div>

<div style="margin-top: 30px;">Выполните остальные пункты инструкции вплоть до 11.1. Чтобы выполнить его, введите полученный HeaderItemID в поле

ниже и нажмите "Загрузить".</div><form method='POST' action='load-olymp-results.jsp'> <label> <span style="display: table-cell; width:

240px">Введите HID:</span> <input style="display: table-cell; width: 200px"

type="text" name="hid"/> </label> <input type="hidden" value="${courseID}"

name="courseID"/> <input type="hidden" value="${year}" name="year"/> <input type="hidden" value="true"

name="load_respublica_hid"/> <input type="submit" value="Загрузить"></form></body></html>olymp-res-diploms.jsp<%@ page contentType="text/html;charset=UTF-8"

language="java" %><%@ page pageEncoding="CP1251" %><%@ taglib prefix="dl" uri='/WEB-INF/tld/dl.tld' %><%@ taglib uri="http://java.sun.com/jsp/jstl/core"

prefix="c" %><html><head> <title>Distance Learning Belarus | Загрузка результатов

олимпиад</title> <meta http-equiv="Content-Type" content="text/html;

charset=windows-1251"></head>

72

Page 73: gsu.bydl.gsu.by/Images/_i4f/_diploms/KRAVCHENKO.docx · Web view5.3 По мере выполнения программы, она выводит предупреждения в консоль.

<body><div style='padding-bottom: 20px;'> <a href="http://neerc.ifmo.ru/school/archive/${year}-$

{year + 1}/ru-olymp-team-russia-${year}-standings.html" target="_blank">Таблица результатов</a></div><form method='POST' action='load-olymp-results.jsp'> <div> <span style="display: table-cell; width: 350px;

font-weight: bold">Команда</span> <span style="display: table-cell; width: 260px;

font-weight: bold">Степень диплома (0 - нет диплома)</span> </div> <c:forEach var="team" items="${teams}" varStatus="loop"> <p style="display: table"> <label for="team_${loop.index} " style="display:

table-cell; width: 350px">${team}</label> <input name="team_${loop.index}" style="display:

table-cell; width: 50px" type="text" value="0"/> </p> <input name="load_diploms" type="hidden"

value="true"/> <input name="teams_size" type="hidden" value="$

{teamsSize}"/> </c:forEach> <input type="submit" value="Загрузить диплом для

команд"></form></body></html>

olymp-res-countries.jsp<%@ page contentType="text/html;charset=windows-1251" %><%@ page pageEncoding="CP1251" %><%@ taglib prefix="dl" uri='/WEB-INF/tld/dl.tld' %><%@ taglib uri="http://java.sun.com/jsp/jstl/core"

prefix="c" %><%@ taglib prefix="fn"

uri="http://java.sun.com/jsp/jstl/functions" %>

<html><head> <title>Distance Learning Belarus | Загрузка результатов

олимпиад</title> <meta http-equiv="Content-Type" content="text/html;

charset=windows-1251"></head><body>Список городов, для которых не найдены страны:<form method='POST' action='load-olymp-results.jsp'> <div style="padding-top: 10px">

73

Page 74: gsu.bydl.gsu.by/Images/_i4f/_diploms/KRAVCHENKO.docx · Web view5.3 По мере выполнения программы, она выводит предупреждения в консоль.

<span style="display: table-cell; width: 200px; font-weight: bold">Город</span>

<span style="display: table-cell; width: 200px; font-weight: bold">Страна</span>

</div> <c:forEach var="city" items="${countries}"

varStatus="loop"> <p style="display: table"> <a href="http://google.com/#q=$

{fn:replace(city,' ','+')}" target="_blank" title="Найти город в Google"><label

for="country_${loop.index} " style="di

splay: table-cell; width: 200px; cursor: pointer;">${city}</label></a>

<input name="country_${loop.index}" style="display: table-cell; width: 200px" type="text" required/>

</p> <input name="load_cities" type="hidden"

value="true"/> <input name="cities_size" type="hidden" value="$

{countriesSize}"/> </c:forEach> <input type="submit" value="Загрузить города"></form></body></html>olymp-res-finished.jsp<%@ page contentType="text/html;charset=UTF-8"

language="java" %><html><head> <title>Результаты загружены</title></head><body>

<div>Результаты олимпиады успешно загружены.</div>

<a href="/olymp/result/teamInter.asp" target="_blank">Перейти на страницу олимпиад</a>

</body></html>--Java-файлы--LoadOlympResultsServlet.javapublic class LoadOlympResultsServlet extends HttpServlet {

private static final String LOAD_COUNTRIES_PAGE = "olymp-res-countries.jsp";

private static final String LOAD_DIPLOMS_PAGE = "olymp-res-diploms.jsp";

private static final String FINISHED_PAGE = "olymp-res-finished.jsp";

74

Page 75: gsu.bydl.gsu.by/Images/_i4f/_diploms/KRAVCHENKO.docx · Web view5.3 По мере выполнения программы, она выводит предупреждения в консоль.

private static final String LOAD_RESPUBLICA_PAGE = "olymp-res-respublica.jsp";

private List<String> citiesWithNoCountries = null; private int year = 0; private OlympType olympType = null; private String startDate = null; private String endDate = null; private List<String> teamsWithNoDiploms = null;

@Override protected void doPost(final HttpServletRequest request,

final HttpServletResponse response) throws ServletException, IOException {

String loadRespublicaHid = request.getParameter("load_respublica_hid");

if (loadRespublicaHid != null && Boolean.valueOf(loadRespublicaHid)) {

String hid = request.getParameter("hid"); String year = request.getParameter("year"); String courseID =

request.getParameter("courseID"); try { LoadOlympResultsService.insertIntoResultTabl

esForRespublica(Integer.valueOf(hid), Integer.valueOf(courseID), "Республика " + year, "Republics contest " + year);

} catch (SQLException e) { throw new RuntimeException(e); } request.getRequestDispatcher(FINISHED_PAGE).forw

ard(request, response); return; }

String loadDiploms = request.getParameter("load_diploms");

if (loadDiploms != null && Boolean.valueOf(loadDiploms)) {

try { loadDiplomsAndResults(request, response); } catch (SQLException e) { throw new RuntimeException(e); } return; }

String loadCities = request.getParameter("load_cities");

75

Page 76: gsu.bydl.gsu.by/Images/_i4f/_diploms/KRAVCHENKO.docx · Web view5.3 По мере выполнения программы, она выводит предупреждения в консоль.

if (loadCities != null && Boolean.valueOf(loadCities) && citiesWithNoCountries != null) {

try { loadCountriesForCities(request, response); } catch (SQLException e) { throw new RuntimeException(e); } return; }

startDate = request.getParameter("startDate"); endDate = request.getParameter("endDate");

int olympTypeInt = Integer.valueOf(request.getParameter("ot"));

int year = Integer.valueOf(request.getParameter("y"));

OlympType olympType = olympTypeInt == 0 ? OlympType.VKOSHP : olympTypeInt == 1 ? OlympType.Respublica : OlympType.undefined;

if (olympType == OlympType.Respublica) { try { Long id =

LoadOlympResultsService.getMaxCalendarID() + 1; int month =

Integer.valueOf(startDate.split("\\.")[1]); int dayStart =

Integer.valueOf(startDate.split("\\.")[0]); int dayEnd =

Integer.valueOf(endDate.split("\\.")[0]); String place =

request.getParameter("place");

LoadOlympResultsService.insertIntoCalendar( id, year, month, year + "-" + month + "-" + dayStart, year + "-" + month + "-" + dayEnd, 17L, place, 1L); int courseID =

LoadOlympResultsService.createCourse( year, 2, "Республиканская олимпиада по

информатике " + year, "Republics contest " + year, year + "-" + month + "-" + dayStart, year + "-" + month + "-" + dayEnd,

76

Page 77: gsu.bydl.gsu.by/Images/_i4f/_diploms/KRAVCHENKO.docx · Web view5.3 По мере выполнения программы, она выводит предупреждения в консоль.

29L); request.setAttribute("year", year); request.setAttribute("courseID", courseID); request.getRequestDispatcher(LOAD_RESPUBLICA

_PAGE).forward(request, response); } catch (SQLException e) { throw new RuntimeException(e); } } else { String result; try { result =

LoadOlympResultsService.loadOlympResults(olympType, year); } catch (SQLException e) { throw new RuntimeException(e); }

this.year = year; this.olympType = olympType;

ResultContainer res = LoadOlympResultsService.generateResult(result);

List<String> countriesNotFound = res.getCountriesNotFound();

if (countriesNotFound.isEmpty()) { if (res.getGomelTeamNames().isEmpty()) { createCourseAndFinish(res, new

HashMap<String, Integer>(), request, response); } else { forwardToDiploms(res.getGomelTeamNames()

, request, response); } return; }

List<String> parsedResult = new ArrayList<String>();

for (String c : countriesNotFound) { parsedResult.add(c.split(",")[0]); } citiesWithNoCountries = parsedResult;

request.setAttribute("countries", parsedResult); request.setAttribute("countriesSize",

parsedResult.size()); request.getRequestDispatcher(LOAD_COUNTRIES_PAGE

).forward(request, response); } }

private void loadCountriesForCities(HttpServletRequest request, final HttpServletResponse response)

77

Page 78: gsu.bydl.gsu.by/Images/_i4f/_diploms/KRAVCHENKO.docx · Web view5.3 По мере выполнения программы, она выводит предупреждения в консоль.

throws ServletException, IOException, SQLException {

Map<String, String> cityToCountry = new HashMap<String, String>();

for (int i = 0; i < citiesWithNoCountries.size(); i++) {

cityToCountry.put(citiesWithNoCountries.get(i), request.getParameter("country_" + i));

} LoadOlympResultsService.loadMissingCountriesForCitie

s(cityToCountry); String result =

LoadOlympResultsService.loadOlympResults(olympType, year); ResultContainer res =

LoadOlympResultsService.generateResult(result); if (!res.getGomelTeamNames().isEmpty()) { forwardToDiploms(res.getGomelTeamNames(),

request, response); return; } createCourseAndFinish(res, new HashMap<String,

Integer>(), request, response); }

private void loadDiplomsAndResults(HttpServletRequest request, final HttpServletResponse response)

throws ServletException, IOException, SQLException {

Map<String, Integer> teamNameToDiplom = new HashMap<String, Integer>();

for (int i = 0; i < teamsWithNoDiploms.size(); i++) {

teamNameToDiplom.put(teamsWithNoDiploms.get(i), Integer.valueOf(request.getParameter("team_" + i)));

} String result =

LoadOlympResultsService.loadOlympResults(olympType, year); ResultContainer res =

LoadOlympResultsService.generateResult(result); createCourseAndFinish(res, teamNameToDiplom,

request, response); }

private void forwardToDiploms(List<String> gomelTeamNames, HttpServletRequest request, final HttpServletResponse response)

throws ServletException, IOException {

teamsWithNoDiploms = gomelTeamNames; request.setAttribute("year", year); request.setAttribute("teams", teamsWithNoDiploms);

78

Page 79: gsu.bydl.gsu.by/Images/_i4f/_diploms/KRAVCHENKO.docx · Web view5.3 По мере выполнения программы, она выводит предупреждения в консоль.

request.setAttribute("teamsSize", teamsWithNoDiploms.size());

request.getRequestDispatcher(LOAD_DIPLOMS_PAGE).forward(request, response);

}

private void createCourseAndFinish(ResultContainer result, Map<String, Integer> teamNameToDiplom,

HttpServletRequest request, final HttpServletResponse response)

throws ServletException, IOException {

/* if (!result.getCountriesNotFound().isEmpty()) { throw new IllegalStateException("Found

unregistered countries or cities: " + Joiner.on(",

").join(result.getCountriesNotFound())); }*/ try { LoadOlympResultsService.createCourseAndLoadResul

ts( year, startDate, endDate,

result.getResult(), teamNameToDiplom); } catch (RuntimeException e) { throw e; } catch (Exception e) { throw new ServletException(e); } request.getRequestDispatcher(FINISHED_PAGE).forward(

request, response); }

}LoadOlympResultsService.javapackage olymp.rimport.service;

import olymp.City;import olymp.Country;import olymp.db.DBUtil;import olymp.rimport.enums.OlympType;import olymp.rimport.results.ParserException;import olymp.rimport.type.Olympiad;import olymp.rimport.type.VKOSHP;import olymp.rimport.xml.LoadXMLtoDB;import olymp.rimport.xml.ResultContainer;import olymp.rimport.xml.TextToXML2;import org.slf4j.Logger;import org.slf4j.LoggerFactory;import org.springframework.web.util.HtmlUtils;

import java.io.BufferedReader;79

Page 80: gsu.bydl.gsu.by/Images/_i4f/_diploms/KRAVCHENKO.docx · Web view5.3 По мере выполнения программы, она выводит предупреждения в консоль.

import java.io.IOException;import java.io.InputStreamReader;import java.net.URL;import java.net.URLConnection;import java.sql.ResultSet;import java.sql.SQLException;import java.util.*;

import static olymp.rimport.enums.OlympType.Respublica;

public class LoadOlympResultsService {

private static final Logger log = LoggerFactory.getLogger(LoadOlympResultsService.class);

private static final Map<OlympType, Olympiad> olymps = new HashMap<OlympType, Olympiad>();

private static Olympiad currentOlymp = null;

static { olymps.put(OlympType.VKOSHP, new VKOSHP()); }

public static String loadOlympResults(OlympType olympType, int year) throws SQLException, IOException {

currentOlymp = olymps.get(olympType); if (currentOlymp == null) { throw new RuntimeException("Olymp type not

found: " + olympType); } currentOlymp.init(year); Long courseId =

getCourseID(currentOlymp.getParentID(), year); if (courseId > -1) { currentOlymp.removeResults(courseId); } String url = currentOlymp.getResultsURL(); return

currentOlymp.parseResults(loadContentsFromURL(url)); }

public static Long getMaxCalendarID() throws SQLException {

DBUtil dbUtil = null; try { dbUtil = DBUtil.getInstance(); ResultSet rs = dbUtil.executeQuery("SELECT

TOP(1) ID FROM Calendar ORDER BY ID DESC"); if (rs.next()) { return rs.getLong(1); } return -1L; } finally {

80

Page 81: gsu.bydl.gsu.by/Images/_i4f/_diploms/KRAVCHENKO.docx · Web view5.3 По мере выполнения программы, она выводит предупреждения в консоль.

if (dbUtil != null) { dbUtil.close(); } } }

public static void insertIntoCalendar(Long id, int year, int month, String dayStart, String dayEnd, Long NameID, String place, Long contestant) throws SQLException {

DBUtil dbUtil = null; try { dbUtil = DBUtil.getInstance(); String queryBuilder = "INSERT INTO Calendar (ID,

Year, Month, DayStart, DayEnd, NameID, Place, Contestant, URLResult) VALUES (" + id + ", " +

year + ", " + month + ", " + "'" + dayStart + "'" + ", " + "'" + dayEnd + "'" + ", " + NameID + ", " + "'" + place + "'" + ", " + contestant + ", " + "'showRes.asp?id=" + id + "'" + ");"; dbUtil.executeSqlUpdate(queryBuilder); } finally { if (dbUtil != null) { dbUtil.close(); } } }

private static Long getCourseID(Long parentID, int year) throws SQLException {

DBUtil dbUtil = null; try { dbUtil = DBUtil.getInstance(); ResultSet rs = dbUtil.executeQuery("SELECT ID

FROM Courses WHERE ParentID = " + parentID + " AND ShortName = 'C" + (year % 100) + "'");

if (rs.next()) { return rs.getLong(1); } return -1L; } finally { if (dbUtil != null) { dbUtil.close(); } } }

81

Page 82: gsu.bydl.gsu.by/Images/_i4f/_diploms/KRAVCHENKO.docx · Web view5.3 По мере выполнения программы, она выводит предупреждения в консоль.

public static void createCourseAndLoadResults(int year, String startDate, String endDate, String res, Map<String, Integer> teamNameToDiplom) throws Exception {

int courseID = createCourse( year, 3, currentOlymp.getTitle(), currentOlymp.getShortTitleEN(), currentOlymp.getFullStartDate(startDate), currentOlymp.getFullEndDate(endDate), currentOlymp.getParentID()); String newRes = res .replace("name=\"Set name\"",

"name=\"" + currentOlymp.getShortTitleRU() + "\"") .replace("courseID=\"XX\"",

"courseID=\"" + courseID + "\"") .replace("openDate=\"XX.XX.XXXX\"",

"openDate=\"" + startDate + "." + year + "\"") .replace("collapseDate=\"XX.XX.XXXX\

"", "collapseDate=\"" + endDate + "." + year + "\""); String finalRes = putDiplomasForTeams(newRes,

teamNameToDiplom); int hid = LoadXMLtoDB.loadResults(finalRes); loadTeamResults( hid, courseID, currentOlymp.getTitle(), currentOlymp.getShortTitleEN()); }

private static String putDiplomasForTeams(String res, Map<String, Integer> teamNameToDiploma) {

String newRes = res; Set<Map.Entry<String, Integer>> entries =

teamNameToDiploma.entrySet(); for (Map.Entry<String, Integer> entry : entries) { if (entry.getValue() == 0) { continue; } int ind = newRes.indexOf(entry.getKey()); if (ind == -1) { continue; } int ind2 = newRes.indexOf("totalResult", ind); int end = newRes.indexOf("/>", ind2); String firstPart = newRes.substring(0, end); String secondPart = newRes.substring(end,

newRes.length()); newRes = firstPart + " diplom=\"" +

entry.getValue() + "\"" + secondPart; } return newRes;

82

Page 83: gsu.bydl.gsu.by/Images/_i4f/_diploms/KRAVCHENKO.docx · Web view5.3 По мере выполнения программы, она выводит предупреждения в консоль.

}

public static ResultContainer generateResult(String input) throws IOException {

try { return TextToXML2.getXMLAsString(input); } catch (ParserException e) { throw new IOException(e); } }

private static String loadContentsFromURL(String url) throws IOException {

URL website = new URL(url); URLConnection connection = website.openConnection(); BufferedReader in = new BufferedReader(new

InputStreamReader(connection.getInputStream())); StringBuilder response; try { response = new StringBuilder(); String inputLine; while ((inputLine = in.readLine()) != null) { response.append(inputLine); } } finally { in.close(); } return HtmlUtils.htmlUnescape(response.toString()); }

public static int loadMissingCountriesForCities(Map<String, String> citiesToCountries) {

List<Country> countries = Arrays.asList(Country.getAllCountries());

Map<String, Country> countryNameToCountry = new HashMap<String, Country>();

for (Country c : countries) { countryNameToCountry.put(c.getName(0).toLowerCas

e(), c); } Map<String, Country> citiesToCountriesObject = new

HashMap<String, Country>(); for (Map.Entry<String, String> entry :

citiesToCountries.entrySet()) { citiesToCountriesObject.put(entry.getKey(),

countryNameToCountry.get(entry.getValue().toLowerCase())); } for (Map.Entry<String, Country> entry :

citiesToCountriesObject.entrySet()) { if (entry.getValue() != null) { City.registerCity(entry.getKey(), 0,

entry.getValue());83

Page 84: gsu.bydl.gsu.by/Images/_i4f/_diploms/KRAVCHENKO.docx · Web view5.3 По мере выполнения программы, она выводит предупреждения в консоль.

} } return 0; }

public static int createCourse(int year, int type, String title, String shortTitle, String startDate, String endDate, Long parentID) throws SQLException {

DBUtil dbUtil = DBUtil.getInstance(); try { String sqlQuery = "INSERT INTO Courses(Name, EName,

ShortName, AwardType, Active, Type, Accept, TimeBegin, TimeEnd, DefaultTaskHiLevel, DefaultTheoryLevel, " +

"RealtimeResults, PublicDetails, TableType, ParentID, Num, TasksViewType, CanGetSolution, Hidden, CanGetTest) VALUES ('" + title + "', '" + shortTitle + "'," +

"'C" + String.valueOf(year).substring(2) + "',1,1," + type + ",3,'" + startDate + "','" + endDate + "',10000, 10000, 1,1,5," + parentID + "," +

"1,1,1,0,0)"; dbUtil.executeSqlUpdate(sqlQuery); ResultSet rs = dbUtil.executeQuery("SELECT

TOP(1) ID FROM Courses ORDER BY ID DESC"); rs.next(); return rs.getInt("ID"); } finally { dbUtil.close(); } }

private static int loadTeamResults(int hid, int courseID, String title, String shortTitle) throws SQLException {

DBUtil dbUtil = null; try { dbUtil = DBUtil.getInstance(); String sqlQuery = "INSERT INTO

resulttables(CourseID, Title, ETitle, URL, EURL) VALUES " + "(" + courseID + ", '" + title + "', '"

+ shortTitle + "','xrestable.jsp?hd=2&hid=" + hid + "&pi=6&pi=7&u.c=" + courseID + "&lng=rus&u.a&c.l=4&c.n=2&c.s=2&c.s=7', " +

"'xrestable.jsp?hd=2&hid=" + hid + "&pi=6&pi=7&u.c=" + courseID + "&lng=eng&u.a&c.l=4&c.n=2&c.s=2&c.s=7');";

dbUtil.executeSqlUpdate(sqlQuery); } finally { if (dbUtil != null) { dbUtil.close(); } }

84

Page 85: gsu.bydl.gsu.by/Images/_i4f/_diploms/KRAVCHENKO.docx · Web view5.3 По мере выполнения программы, она выводит предупреждения в консоль.

return 0; }

public static void insertIntoResultTablesForRespublica(int hid, int courseID, String title, String ETitle) throws SQLException {

DBUtil dbUtil = null; try { dbUtil = DBUtil.getInstance(); String sqlQuery = "INSERT INTO

resulttables(CourseID, Title, ETitle, URL, EURL) VALUES (" + courseID + ", '" + title + "', '" +

ETitle + "', 'xrestable.jsp?hd=2&hid=" + hid + "&u.c=" + courseID + "&pi=11&pi=3&c.s=1&c.s=9&lng=rus', " +

"'xrestable.jsp?hd=2&hid=" + hid + "&u.c=" + courseID + "&pi=11&pi=3&c.s=1&c.s=9&lng=eng')";

dbUtil.executeSqlUpdate(sqlQuery); } finally { if (dbUtil != null) { dbUtil.close(); } } }}

TextToXML2.javapackage olymp.rimport.xml;

import olymp.City;import olymp.rimport.results.ParserException;import olymp.rimport.results.entity.ResultRecord;import olymp.rimport.results.parser.TeamResult;import org.apache.velocity.Template;import org.apache.velocity.VelocityContext;import org.apache.velocity.app.Velocity;import org.apache.velocity.runtime.RuntimeConstants;import

org.apache.velocity.runtime.resource.loader.ClasspathResourceLoader;

import org.slf4j.Logger;import org.slf4j.LoggerFactory;import org.springframework.context.ApplicationContext;import

org.springframework.context.support.ClassPathXmlApplicationContext;

import java.io.*;import java.util.ArrayList;import java.util.List;

public class TextToXML2 {

static {85

Page 86: gsu.bydl.gsu.by/Images/_i4f/_diploms/KRAVCHENKO.docx · Web view5.3 По мере выполнения программы, она выводит предупреждения в консоль.

try { Velocity.setProperty(Velocity.COUNTER_INITIAL_VA

LUE, 0); Velocity.setProperty(Velocity.INPUT_ENCODING,

"Cp1251"); Velocity.setProperty(Velocity.OUTPUT_ENCODING,

"Cp1251"); Velocity.setProperty(RuntimeConstants.RESOURCE_L

OADER, "classpath"); Velocity.setProperty("classpath.resource.loader.

class", ClasspathResourceLoader.class.getName()); Velocity.init(); } catch (Exception e) { throw new IllegalStateException(e); } }

private static final Logger log = LoggerFactory.getLogger(TextToXML2.class);

private ApplicationContext context = new ClassPathXmlApplicationContext("olymp/rimport/r-import.xml");

public static ResultContainer getXMLAsString(String txtContents) throws IOException, ParserException {

TextToXML2 converter = new TextToXML2(); return converter.buildXMLFromFile(txtContents); }

private ResultContainer buildXMLFromFile(String inputFileContents) throws IOException, ParserException {

int gomelTeamCount = 0; ArrayList<ResultRecord> resultRecordList = new

ArrayList<ResultRecord>(100); TeamResult parser; BufferedReader fin = new BufferedReader(new InputStreamReader(new

ByteArrayInputStream(inputFileContents.getBytes())));

final String lang = "rus";

String taskName = fin.readLine(); String header = fin.readLine(); parser = (TeamResult) context.getBean("teamParser"); parser.init(header, taskName,

System.getProperty("lang", lang)); String str = fin.readLine();

while (str != null) { str = str.replaceAll("\\*", "

").replaceAll("\'", " ").replaceAll("\"", ""); parser.setData(str); resultRecordList.add(parser.getResultRecord());

86

Page 87: gsu.bydl.gsu.by/Images/_i4f/_diploms/KRAVCHENKO.docx · Web view5.3 По мере выполнения программы, она выводит предупреждения в консоль.

str = fin.readLine(); }

List<String> countriesNotFound = new ArrayList<String>();

List<String> gomelTeamNames = new ArrayList<String>();

for (ResultRecord result : resultRecordList) { if (result.getCountry().trim().isEmpty()) { String name = result.getName(); if (name.contains("+")) { int langKey = 0; City c =

City.findByName(name.substring(0, name.indexOf('+')).trim(), langKey);

if (c == null) { countriesNotFound.add(name); } else { String cityName;

if (name.contains(",")) cityName = name.substring(0,

name.indexOf(',')); else cityName = name;

City.registerCity(cityName, langKey, c.getCountry());

result.setCountry(c.getCountry().getName(langKey));

} } else { countriesNotFound.add(result.getName()); } } if

(result.getName().toLowerCase().contains("гомель")) { gomelTeamCount++; result.setName("Гомель-" + gomelTeamCount); gomelTeamNames.add(result.getName()); } if

(result.getName().toLowerCase().contains("мозырь")) { gomelTeamNames.add(result.getName()); } }

/* if (!countriesNotFound.isEmpty()) { return new ResultContainer("",

countriesNotFound, gomelTeamNames);87

Page 88: gsu.bydl.gsu.by/Images/_i4f/_diploms/KRAVCHENKO.docx · Web view5.3 По мере выполнения программы, она выводит предупреждения в консоль.

}*/

//Build XML with Velocity try { VelocityContext context = new VelocityContext(); context.put("rList", resultRecordList); context.put("taskNames", parser.getTaskNames()); String templateName = parser.getTemplateName();// InputStream input =

TeamResult.class.getResourceAsStream(templateName); Template template =

Velocity.getTemplate("olymp/rimport/results/parser/" + templateName);

StringWriter sw = new StringWriter();// Velocity.evaluate(context, sw, "", new

InputStreamReader(input)); template.merge(context, sw); String res = sw.toString(); log.debug(res); return new ResultContainer(res,

countriesNotFound, gomelTeamNames); } catch (Exception e) { throw new RuntimeException(e); } }

}ResultContainer.javapackage olymp.rimport.xml;

import java.util.List;

public class ResultContainer {

private String result; private List<String> countriesNotFound; private List<String> gomelTeamNames;

ResultContainer(String result, List<String> countriesNotFound, List<String> gomelTeamNames) {

this.result = result; this.countriesNotFound = countriesNotFound; this.gomelTeamNames = gomelTeamNames; }

public String getResult() { return result; }

public List<String> getCountriesNotFound() { return countriesNotFound; }

88

Page 89: gsu.bydl.gsu.by/Images/_i4f/_diploms/KRAVCHENKO.docx · Web view5.3 По мере выполнения программы, она выводит предупреждения в консоль.

public List<String> getGomelTeamNames() { return gomelTeamNames; }}

LoadXMLToDb.javapublic class LoadXMLtoDB {

public static int loadResults(String inputContents) throws Exception {

ResultXML rXML = new ResultXML(ResultXML.SaveResultInDB);

InputStream s = new BufferedInputStream(new ByteArrayInputStream(inputContents.getBytes()));

List<Long> result = rXML.parseAndGetHeaderIDS(new InputSource(s));

Collections.sort(result); return result.get(0).intValue(); }}ResultXML.javapackage olymp.rimport.resultManager;

import olymp.Course;import olymp.Settings;import olymp.db.DBException;import olymp.users.NewUser;import olymp.users.User;import org.apache.log4j.Logger;import org.xml.sax.*;import org.xml.sax.helpers.DefaultHandler;import org.xml.sax.helpers.XMLReaderFactory;

import java.sql.SQLException;import java.text.SimpleDateFormat;import java.util.ArrayList;import java.util.Date;import java.util.HashMap;import java.util.List;

/** * Класс используется для загрузки результатов соревнования

из XML-файла * Находиться в стадии разработки =), но потестировать можно

=) */public class ResultXML extends DefaultHandler implements

ErrorHandler {

private static Logger logger = Logger.getLogger(ResultXML.class);

89

Page 90: gsu.bydl.gsu.by/Images/_i4f/_diploms/KRAVCHENKO.docx · Web view5.3 По мере выполнения программы, она выводит предупреждения в консоль.

private XMLReader xr; private boolean parseHeader = false; private String tagValue = ""; private long userID; private String[] parametersName = null; // классы для работы с шапкой соревнования private ResMan rm = null; private ResultHeader resultHeader = null; private HeaderItem currentItem = null; // Параметры private boolean loadHeader; private boolean saveResults; private boolean dontSaveHeader; private boolean registerUser; private String lang = "eng"; private int langID; private int userType = NewUser.USER; private List<Long> headerItemIDS = new

ArrayList<Long>();

/** * Сохранять результаты в БД * TODO: thread-unsafe */ public static long SaveResultInDB = 2;

/** * Коснтруктор класса * * @param params параметры, с помощью которых определяем

как будет идти разбор данных * @throws SAXException исключение которое будет

возникать в случае невозможности загрузки класса "org.apache.xerces.parsers.SAXParser"

*/ public ResultXML(long params) throws SAXException { logger.info("Contructor ResultXML");

xr = XMLReaderFactory.createXMLReader("org.apache.xerces.parsers.SAXParser");

xr.setDTDHandler(this); xr.setContentHandler(this); xr.setErrorHandler(this); //

http://stackoverflow.com/questions/4726279/parsing-an-xml-file-with-a-dtd-schema-on-a-relative-path

xr.setEntityResolver(new org.hibernate.util.DTDEntityResolver());

parseParameters(params);90

Page 91: gsu.bydl.gsu.by/Images/_i4f/_diploms/KRAVCHENKO.docx · Web view5.3 По мере выполнения программы, она выводит предупреждения в консоль.

}

private void parseParameters(long params) { /* Загружать шапку из БД */ long loadHeaderFromDB = 1; loadHeader = (params & loadHeaderFromDB) != 0; saveResults = (params & SaveResultInDB) != 0; /* Не сохранять шапку в БД - если нужно что-то отлаживать */ long dontSaveHeader1 = 4; dontSaveHeader = (params & dontSaveHeader1) != 0; /* не регистрировать пользователя */ long dontRegisterUser = 8; registerUser = (params & dontRegisterUser) == 0; }

public void startDocument() { logger.debug("Start document"); }

public void endDocument() { logger.debug("End document"); }

public void startElement(String uri, String name, String qName, Attributes atts)

{ String value; logger.debug("Start element: " + qName); tagValue = ""; if (name.equals("competition")) return; if (name.equals("header")) return; if (name.equals("competitionInfo")) { parseCompetitionInfo(atts); return; } if (parseHeader) { if ((name.equals("day")) ||

(name.equals("task"))) { HeaderItem tempItem; value = atts.getValue("name"); tempItem = new HeaderItem(value,

currentItem); currentItem.addChild(tempItem); if (name.equals("day")) { currentItem = tempItem; } return;

91

Page 92: gsu.bydl.gsu.by/Images/_i4f/_diploms/KRAVCHENKO.docx · Web view5.3 По мере выполнения программы, она выводит предупреждения в консоль.

} } else { if (name.equals("day")) { parseAttributes(atts); return; } if (name.equals("task")) { parseAttributes(atts); return; } } if (name.equals("tableOfScore")) { prepareForTableOfScore(); return; } if (name.equals("recordScore")) { prepareForRecordScore(); return; } if (name.equals("totalResult")) { parseAttributes(atts); return; } if (name.equals("contestant")) { parseUserInfo(atts); } }

private void parseAttributes(Attributes atts) { logger.debug("Current item: " +

currentItem.getName()); boolean noSolve; int iCount = parametersName.length; HashMap<Integer, Float> results = new

HashMap<Integer, Float>(7); //Проверяем sum==-1? noSolve = atts.getValue("sum").equals("-1");

for (int i = 1; i < iCount && !noSolve; i++) { String value = atts.getValue(parametersName[i]); if (value != null) { Float fValue = new Float(value); results.put(i, fValue); } } // Если есть решение по задаче - то сохраняем if (!noSolve) { if (saveResults) { rm.addResult(userID, currentItem, results); headerItemIDS.add(currentItem.getHeaderID())

; } }

92

Page 93: gsu.bydl.gsu.by/Images/_i4f/_diploms/KRAVCHENKO.docx · Web view5.3 По мере выполнения программы, она выводит предупреждения в консоль.

if (currentItem.haveChild()) currentItem = currentItem.getChildItem(0);

}

private void prepareForRecordScore() { currentItem = rm.getHeader().getRootItem(); }

private void prepareForTableOfScore() { if (saveResults) { if (!rm.getHeader().getRootItem().isSaveInDB())

throw new RuntimeException("header not saved"); } }

/** * Метод "разбирает" атрибуты для нового участника и

регистрирует его в БД * * @param atts атрибуты участника */ private void parseUserInfo(Attributes atts) { HashMap<String, String> userInfo = new

HashMap<String, String>(10); String[] supportFields; NewUser nu = new NewUser(lang, userType); // Получаем список полей, которые поддреживаются для

ползователя или команды supportFields = nu.getSupportedFieldNames(); // По имени поля получаем значение атрибута String value; if (userType == NewUser.TEAM) { value = atts.getValue("name"); userInfo.put("name", value); } for (String supportField : supportFields) { value =

atts.getValue(supportField.toLowerCase()); // Если данный атрибут есть вносим его в

пользовательску информацию if (value != null) userInfo.put(supportField, value); } nu.setUserData(userInfo); if (registerUser) { userID =

nu.Register(rm.getHeader().getOpenDate()); rm.subscribeUser(userID); logger.debug("Registered or found user: " +

userID); logger.debug(userInfo.toString()); } else userID = 200000;

93

Page 94: gsu.bydl.gsu.by/Images/_i4f/_diploms/KRAVCHENKO.docx · Web view5.3 По мере выполнения программы, она выводит предупреждения в консоль.

}

private void prepareHeader(long CourseID, String CourseName, Date oDate, Date cDate) //throws SQLException

{ rm = new ResMan(CourseID, oDate, cDate, langID); resultHeader = rm.getHeader(); resultHeader.getRootItem().setName(CourseName); currentItem = resultHeader.getRootItem(); parametersName = resultHeader.getSupportedFields(); }

public void endElement(String uri, String name, String qName) {

logger.debug("Tag Value: " + tagValue); logger.debug("End element: " + qName); if (name.equals("competitionInfo")) { if (currentItem.getParent() == null) { if (loadHeader) { if (!resultHeader.loadFromDB()) { throw new

RuntimeException(this.getClass().getName() + ".endElement: Can\'t load header from database");

} currentItem =

resultHeader.getRootItem(); } else { resultHeader.setRootItem(currentItem); if (!dontSaveHeader) resultHeader.saveInDB(); } } else throw new RuntimeException("Ошибка при

разборе файла: не достигнут корневой элемент ");

logger.debug("\n" + currentItem.toString());

if (rm != null) rm.setHeader(resultHeader); parseHeader = false; return; } if (parseHeader) { if (name.equals("day")) currentItem =

currentItem.getParent(); } else { if ((name.equals("task")) ||

(name.equals("day"))) { if (currentItem.getNext() != null)

currentItem = currentItem.getNext(); else currentItem = currentItem.getParent(); } } }

94

Page 95: gsu.bydl.gsu.by/Images/_i4f/_diploms/KRAVCHENKO.docx · Web view5.3 По мере выполнения программы, она выводит предупреждения в консоль.

/** * метод обрабатывает символы которые находятся между

тегами &lt;tag&gt;chars&lt;/tag&gt; * * @param ch символы между тегами * @param start где они начинаються * @param length и сколько их */ public void characters(char ch[], int start, int length)

{ for (int i = start; i < start + length; i++) { switch (ch[i]) { case '\\': tagValue = tagValue + "\\\\"; break; case '"': tagValue = tagValue + "\\\""; break; case '\n': tagValue = tagValue + "\\n"; break; case '\r': tagValue = tagValue + "\\r"; break; case '\t': tagValue = tagValue + "\\t"; break; default: tagValue = tagValue + ch[i]; break; } } }

public void fatalError(SAXParseException e) throws SAXException {

logger.fatal(e); super.error(e); }

public void error(SAXParseException e) throws SAXException {

logger.fatal(e); super.error(e); }

private void parseCompetitionInfo(Attributes atts) { String tmp; String oDateStr; String cDateStr; tmp = atts.getValue("language"); if (tmp != null) lang = tmp;

95

Page 96: gsu.bydl.gsu.by/Images/_i4f/_diploms/KRAVCHENKO.docx · Web view5.3 По мере выполнения программы, она выводит предупреждения в консоль.

langID = (lang.equalsIgnoreCase("rus") ? Settings.LANG_RU : Settings.LANG_EN);

tmp = atts.getValue("contestType"); userType = tmp.equalsIgnoreCase("team") ?

NewUser.TEAM : NewUser.USER; long CourseID = 0; String courseIDStr = atts.getValue("courseID"); if (!courseIDStr.equals("") && !

courseIDStr.equalsIgnoreCase("XX")) { CourseID = Long.parseLong(courseIDStr); } String nameContest = atts.getValue("name"); SimpleDateFormat df = new

SimpleDateFormat("dd.MM.yyyy"); oDateStr = atts.getValue("openDate"); cDateStr = atts.getValue("collapseDate"); if (cDateStr == null) cDateStr = oDateStr; Date oDate = df.parse(oDateStr, new

java.text.ParsePosition(0)); Date cDate = df.parse(cDateStr, new

java.text.ParsePosition(0)); if (CourseID == 0) { logger.info("CourseID is 0 - Reqister new

course"); Course newCourse = new

Course(User.findByID(100145)); if (lang.equals("eng")) { newCourse.eName = nameContest; newCourse.name = ""; } else { newCourse.name = nameContest; newCourse.eName = ""; } newCourse.setBegin(oDate); newCourse.setEnd(cDate); newCourse.setType(userType == NewUser.TEAM ?

Course.TEAM_COMPETITION : Course.OWN_COMPETITION); newCourse.setAccept(3); newCourse.setHidden(false); newCourse.save(); CourseID = newCourse.ID; logger.info("New Course was created. ID:" +

CourseID); } prepareHeader(CourseID, nameContest, oDate, cDate); parseHeader = true; }

public List<Long> parseAndGetHeaderIDS(InputSource src) {

try { xr.parse(src); } catch (SAXParseException e) {

96

Page 97: gsu.bydl.gsu.by/Images/_i4f/_diploms/KRAVCHENKO.docx · Web view5.3 По мере выполнения программы, она выводит предупреждения в консоль.

/* The processing instruction target matching "[xX]

[mM][lL]" is not allowed Вылетает после того как результаты загружены,

поэтому только логируется.*/// logger.warn("", e); throw new RuntimeException(e); } catch (Exception e) { throw new RuntimeException(e); } return headerItemIDS; }}VKOSHP.javapackage olymp.rimport.type;

import olymp.db.DBUtil;import olymp.rimport.parser.OlympResultParser;import olymp.rimport.parser.VKOSHPResultParser;

import java.sql.ResultSet;import java.sql.SQLException;import java.util.*;

public class VKOSHP implements Olympiad {

private static final Map<Integer, String> VKOSHPYearToNumber = new HashMap<Integer, String>();

private static final Long parentID = 26L; private OlympResultParser parser = null; private int year;

static { VKOSHPYearToNumber.put(2012, "Тринадцатая"); VKOSHPYearToNumber.put(2013, "Четырнадцатая"); VKOSHPYearToNumber.put(2014, "Пятнадцатая"); VKOSHPYearToNumber.put(2015, "Шестнадцатая"); VKOSHPYearToNumber.put(2016, "Семнадцатая"); VKOSHPYearToNumber.put(2017, "Восемнадцатая"); VKOSHPYearToNumber.put(2018, "Девятнадцатая"); VKOSHPYearToNumber.put(2019, "Двадцатая"); VKOSHPYearToNumber.put(2020, "Двадцать первая"); VKOSHPYearToNumber.put(2021, "Двадцать вторая"); VKOSHPYearToNumber.put(2022, "Двадцать третья"); VKOSHPYearToNumber.put(2023, "Двадцать четвертая"); VKOSHPYearToNumber.put(2024, "Двадцать пятая"); VKOSHPYearToNumber.put(2025, "Двадцать шестая"); VKOSHPYearToNumber.put(2026, "Двадцать седьмая"); VKOSHPYearToNumber.put(2027, "Двадцать восьмая"); VKOSHPYearToNumber.put(2028, "Двадцать девятая"); VKOSHPYearToNumber.put(2029, "Тридцатая"); VKOSHPYearToNumber.put(2030, "Тридцать первая");

97

Page 98: gsu.bydl.gsu.by/Images/_i4f/_diploms/KRAVCHENKO.docx · Web view5.3 По мере выполнения программы, она выводит предупреждения в консоль.

}

public VKOSHP() { }

@Override public void init(int year) { this.year = year; this.parser = new VKOSHPResultParser(); }

@Override public String parseResults(String results) { return this.parser.parseResults(results); }

@Override public String getTitle() { return VKOSHPYearToNumber.get(year) + "

Всероссийская командная олимпиада школьников по программированию";

}

@Override public String getShortTitleEN() { return "Russia " + year; }

@Override public String getShortTitleRU() { return "Россия " + year; }

@Override public String getFullStartDate(String startDate) { String[] startDayAndMonth = startDate.split("\\."); int startDay = Integer.valueOf(startDayAndMonth[0]); int startMonth =

Integer.valueOf(startDayAndMonth[1]); return year + "-" + startMonth + "-" + startDay; }

@Override public String getFullEndDate(String endDate) { String[] endDayAndMonth = endDate.split("\\."); int endDay = Integer.valueOf(endDayAndMonth[0]); int endMonth = Integer.valueOf(endDayAndMonth[1]); return year + "-" + endMonth + "-" + endDay; }

@Override public Long getParentID() { return parentID;

98

Page 99: gsu.bydl.gsu.by/Images/_i4f/_diploms/KRAVCHENKO.docx · Web view5.3 По мере выполнения программы, она выводит предупреждения в консоль.

}

@Override public String getResultsURL() { return "http://neerc.ifmo.ru/school/archive/" + year + "-" + (year + 1) + "/ru-olymp-team-russia-" + year + "-standings.html"; }

@Override public void removeResults(Long courseId) throws

SQLException { List<Long> headerItemIds =

getHeaderItemIds(courseId); String hids = listToSQLString(headerItemIds); List<Long> userIds = getUserIds(hids); Date regDate = getRegDate(courseId); deleteCourseAndRelatedData(courseId, hids, userIds,

regDate); }

private String listToSQLString(List<Long> list) { StringBuilder hidsBuilder = new StringBuilder("("); for (Long id : list) { hidsBuilder.append(id).append(", "); }

hidsBuilder.delete(hidsBuilder.length() - 2, hidsBuilder.length() - 1);

hidsBuilder.append(")"); return hidsBuilder.toString(); }

private void deleteCourseAndRelatedData(Long courseId, String headerItemIds, List<Long> userIds, Date regDate) throws SQLException {

String startTransaction = "BEGIN TRANSACTION TRANS1";

String deleteFromResultTables = " DELETE FROM RESULTTABLES WHERE COURSEID = " + courseId;

String userIdsString = listToSQLString(userIds); String regDateString = DBUtil.wrapDate(regDate);

String beginTry = " BEGIN TRY"; String deleteFromDL2ResultTables = " DELETE FROM

dl2ResultsCell WHERE headerItemId IN " + headerItemIds;

99

Page 100: gsu.bydl.gsu.by/Images/_i4f/_diploms/KRAVCHENKO.docx · Web view5.3 По мере выполнения программы, она выводит предупреждения в консоль.

String deleteFromDL2ResultsHeaderItemMapping = " DELETE FROM dl2ResultsHeaderItemMapping WHERE headerItemId IN " + headerItemIds;

String deleteFromDL2ResultsHeaderItem = " DELETE FROM dl2ResultsHeaderItem WHERE itemId IN " + headerItemIds;

String deleteFromUsersHistory = " DELETE FROM UsersHistory WHERE ID in " + userIdsString + " AND Date = " + regDateString;

String deleteFromUserCourses = " DELETE FROM UsersCourses WHERE CourseID = " + courseId;

String deleteFromCourses = " DELETE FROM Courses WHERE ID = " + courseId;

String deleteFromDL2ResultsIndex = " DELETE FROM dl2ResultsIndex WHERE CourseID = " + courseId;

String endTransaction = " COMMIT TRANSACTION TRANS1 END TRY BEGIN CATCH ROLLBACK TRANSACTION TRANS1 END CATCH";

String sqlDeleteQuery = startTransaction + beginTry + deleteFromResultTables + deleteFromDL2ResultTables + deleteFromDL2ResultsHeaderItemMappin

g + deleteFromDL2ResultsHeaderItem + deleteFromUsersHistory + deleteFromUserCourses + deleteFromCourses + deleteFromDL2ResultsIndex + endTransaction;

DBUtil dbUtil = null; try { dbUtil = DBUtil.getInstance(); dbUtil.executeSqlUpdate(sqlDeleteQuery); } finally { if (dbUtil != null) { dbUtil.close(); } }

}

private List<Long> getHeaderItemIds(Long courseId) throws SQLException {

DBUtil dbUtil = null; try { dbUtil = DBUtil.getInstance(); String query = "SELECT headerItemId FROM

dl2ResultsHeaderItemMapping WHERE courseId = " + courseId; ResultSet rs = dbUtil.executeQuery(query); List<Long> ids = new ArrayList<Long>();

100

Page 101: gsu.bydl.gsu.by/Images/_i4f/_diploms/KRAVCHENKO.docx · Web view5.3 По мере выполнения программы, она выводит предупреждения в консоль.

while (rs.next()) { ids.add(rs.getLong(1)); } return ids; } finally { if (dbUtil != null) { dbUtil.close(); } } }

private List<Long> getUserIds(String headerItemIds) throws SQLException {

DBUtil dbUtil = null; try { dbUtil = DBUtil.getInstance(); String query = "SELECT userId FROM

dl2ResultsCell WHERE headerItemId IN " + headerItemIds; ResultSet rs = dbUtil.executeQuery(query); List<Long> ids = new ArrayList<Long>(); while (rs.next()) { ids.add(rs.getLong(1)); } return ids; } finally { if (dbUtil != null) { dbUtil.close(); } } }

private Date getRegDate(Long courseId) throws SQLException {

DBUtil dbUtil = null; try { dbUtil = DBUtil.getInstance(); String query = "SELECT TimeBegin FROM Courses

WHERE ID = " + courseId; ResultSet rs = dbUtil.executeQuery(query); if (rs.next()) { return getDateDayBefore(rs.getDate(1)); } return null; } finally { if (dbUtil != null) { dbUtil.close(); } } }

private Date getDateDayBefore(Date date) { Calendar newDate = Calendar.getInstance(); newDate.setTime(date);

101

Page 102: gsu.bydl.gsu.by/Images/_i4f/_diploms/KRAVCHENKO.docx · Web view5.3 По мере выполнения программы, она выводит предупреждения в консоль.

newDate.add(Calendar.DATE, -1); return newDate.getTime(); }}

102

Page 103: gsu.bydl.gsu.by/Images/_i4f/_diploms/KRAVCHENKO.docx · Web view5.3 По мере выполнения программы, она выводит предупреждения в консоль.

103