2.2 Проектирование изменений в ядре системы
Согласно выставленным требованиям, система должна поддерживать обработку решений участника турнира с помощью различных групп тестов, причем каждая группа должна быть оценена определенным баллом.
Нужно определить формат для работы с наборами тестов.
Помимо самих тестов, необходимо сформировать конфигурационный файл, пример
такого файла представлен на рисунке 2.1.
Рисунок 2.1- Содержимое конфигурационного файла.
Первая цифра в каждой строке обозначает количество
баллов, которое получить пользователь при удачном прохождении определенного
набора тестов. Набор тестов идет сразу после количества баллов. К примеру, из
указанного рисунка выше следует, что если программа участника турнира пройдет
тесты с 1 по 5, то он получит 20 баллов, если удачно будут пройдены тесты с 6
по 10, то к имеющимся 20 баллам прибавятся еще 30.
.3 Проектирование изменений в базе данных системы
Концептуальная схема базы данных дистанционного практикума ВоГУ была представлена в первой главе. Исходя из требований предметно-методической комиссии, участник турнира может запросить не более десяти отчетов с результатами проверки по каждой задаче. Потребуется хранить количество запросов в базе данных. Для этого достаточно ввести новое поле REPORT_VIEWED в таблицу STATUS, таблица хранит статистику проверяемых задач. При каждом вызове статистики это поле будет равно единице.
Исходная система поддерживает, только один тип турнира - ACM, для ввода
нового типа турнира потребуются ввести дополнительную информацию в таблицу
TYPENAMES, там потребуется указать название нового типа турнира на русском и
английском языках, в таблицу CONTTYPES потребуется добавить идентификатор
нового типа турнира.
.4 Проектирование изменений в веб-интерфейсе пользователя
Личная страница участника турнира показана на рисунке 2.2.
Рисунок 2.1- Личная страница участника турнира.
Для соответствия требованиям предметно-методической комиссии, участник турнира должен иметь возможность вызвать отчет с детальными результатами проверки. Потребуется ввести дополнительную кнопку для вызова результатов проверки. Кнопка должна быть активной, только после того, как будут пройден набор тестов из условия задачи. Причем количество вывозов по каждой задаче не должно превышать 10 раз, значит, помимо кнопки, участнику турнира нужно сообщить какое количество запросов на вывод у него осталось в распоряжении.
Страница с детальными результатами проверки должна отображать список подзадач, результат тестирования, количество баллов за каждый набор тестов и итоговый балл.
Форма для организации нового турнира представлена на рисунке 2.3.
Рисунок 2.3- Форма для организации нового турнира.
Данная форма поддерживает только один тип турнира - ACM, потребуются
ввести дополнительный тип « Всероссийская олимпиада школьников». Страница с
итоговыми результатами турнира должна содержать таблицу с результатами, должна
содержать имена участников, список задач, баллы за каждую задачу, итоговый
суммарный балл, место в турнире
.1 Программная реализация изменений в ядре системы
Изначально для обработки тестов в режиме ACM турнира было достаточно обработать конфигурационный
файл index.lst в котором находились номера тестов. Эта обработка не
подразумевала обработку групп тестов, тесты проверялись индивидуально и если
один из них будет провален, то обработка на этом закончится. Для обработки
решений в режиме школьных олимпиад разработан файл points.lst,
его формат указан в предыдущей главе. Алгоритм работы представлен в Приложении
3. Суть алгоритма сводится к тому, что в обрабатывающая процедура принимает
параметры задачи, под параметрами понимаются: путь к тестам, лимит времени,
ограничение памяти, число баллов за решение и др. Затем нужно проверить, есть в
этом наборе параметров файл points.lst, если да, то это школьная олимпиада,
в противном случае это будет ACM
турнир. В случае школьной олимпиады, идет проверка групп тестов, при
прохождении каждой группы начисляется определенное количество баллов. Результат
тестирования отправляется пользователю.
.2 Программная реализация изменений в базе данных системы
Для ввода изменений в базу данных, будем использовать IBExpert - это СУБД, имеющая графическую оболочку [9]. Для начала выполним регистрацию существующей базы данных в СУБД IBExpert, окно регистрации представлено на рисунке 3.1
Рисунок 3.1- Окно регистрации новой БД.
Далее внесем изменения в таблицу STATUS, нам потребуется новое поле
REPORT_VIEWED для подсчета количества запросов на вывод результата
тестирования. Окно ввода нового поля представлено на рисунке 3.2.
Рисунок 3.2- Ввод нового поля в таблицу STATUS.
В таблице TYPENAMES, нужно указать новый тип турнира. Для этого в поле TP_NAME
добавим две новых строки - Всероссийская олимпиада школьников для русской
версии сайта и All-Russian school olympiad для английской. Окно ввода новых
значений поля TP_NAME показано на рисунке 3.3.
Рисунок 3.3- Ввод новых строк в таблицу TP_NAME.
Аналогично, в таблицу CONTTYPES потребуется добавить идентификатор нового
типа турнира, это отображено на рисунке 3.4.
Рисунок 3.4- Добавление нового идентификатора в таблицу CONTTYPES.
Дальнейшие изменения в базе данных не требуется.
.3 Программная реализация изменений в веб-интерфейсе пользователя
Для формирования турнирной таблицы реализовано отдельное приложение на
языке JAVA. Алгоритм работы в программы показан в обобщенном виде (см.
Приложение 1). Суть работы алгоритма сводится к следующему, для начала
администратору турнира необходимо сформировать два конфигурационных файла - problems.txt,
в котором будут указаны идентификаторы решаемых задач, на рисунке 3.5 показан
формат файла.
Рисунок 3.5- Формат файла problems.txt.
Второй конфигурационный файл - schoolkid.txt, в нем необходимо указать идентификаторы участников
турнира, фамилию и имя. Формат файла представлен на рисунке 3.6.
Рисунок 3.6- Формат файла schoolkid.txt.
Программа считывает эти файлы и инициализирует внутренние переменные, после этого программа делает запрос к базе данных по идентификатору задачи и идентификатору участника олимпиады, на получение количества баллов у всех школьников. На основании полученных данных формируется и выводится турнирная таблица в формате html. В таблице указаны имена участников, номера олимпиадных задач, количество набранных баллов за эти задачи, суммарное количество баллов и места в турнирной таблице. Код программы показан в Приложении 2.
После всех изменений в базе данных, на странице добавления нового турнира
появился вариант для школьной олимпиады, страница администратора показана на
рисунке 3.7.
Рисунок 3.7- Страница добавления нового турнира после изменений в БД.
Проведем тестовый турнир для проверки корректности вывода турнирной
таблицы. В систему было загружено шесть тестовых задач с номерами 1630-1636
(номера будут указаны в турнирной таблице), для каждой задачи был составлено
два конфигурационных файла - index.lst и points.lst. В index.lst указываются
номера тестов, пример файла представлен на рисунке 4.1, в нем указано 8 тестов.
Рисунок 4.1 - формат файла index.lst.
В points.lst указываются баллы, которые получит
участник олимпиады, если его программа корректно пройдет определенные тестовые
наборы, на рисунке 4.2. показан пример такого файла, участник может получить 30
баллов за пройденные тесты, начиная с 1 по 5 и еще 70 баллов за тесты, начиная
с 6 по 8.
Рисунок
4.2 - формат файла points.lst.
Благодаря этим конфигурационным файлам можно будет узнать, корректно ли работает ядро системы в случае, если задача будет иметь бальную систему с подгруппами тестов, что соответствует школьной олимпиаде. Для эксперимента не все задачи будут решены идеально.
В турнире приняли участие шесть виртуальных
участников, результат турнира показан на рисунке 4.3.
Рисунок 4.3 - Турнирная таблица.
По этой турнирной таблице можно сделать вывод, что
ядро корректно обрабатывает конфигурационные файлы, связанные с обработкой
подгрупп тестов, использующих бальную систему. Как видно, на некоторых задачах
было засчитано лишь часть от полных 100 баллов. Помимо этого корректно
рассчитываются суммарные баллы и места в турнире. Корректно обработан случай,
если пользователь ничего не решил в период турнира. Программа для вывода
турнирной таблицы работает исправно.
.1 Разработка инструкции для участника олимпиад
Для участия в олимпиаде, пользователю рекомендуется выполнить нижеперечисленные шаги:
Нажать на вкладку «Турниры», расположенной в шапке сайта.
Пройти регистрацию нового участника турнира, кнопка для регистрации расположена в верхней правой части страницы.
Авторизоваться в системе, введя логин и пароль. Авторизация проходится в верхней правой части страницы.
Просмотреть список ожидаемых олимпиад и выбрать нужную, кликнув на кнопку «Register».
Когда олимпиада будет запущена, появится кнопка «Private page», для входа на персональную страницу участника олимпиада.
Выбрать задачу из предложенного списка заданий, при клике на неё будет совершен переход на страницу описания условий выбранной задачи.
После прочтения и написания варианта решения, в меню «Послать на проверку» из выпадающего списка задач необходимо выбрать нужную. Так же необходимо определиться с выбором компилятора кода. Текст задачи можно вставить в текстовое поле или прикрепить отдельным файлом.
После отправки нужно обновить страницу, появится таблица с результатами проверки.
.2 Разработка инструкции для членов жюри
В школьной олимпиаде используется бальная система оценки решения задач.
За выполнение задачи участник может получить определенное количество баллов (обычно от 0 до 100). Количество набранных баллов зависит от качества написанного решения. Это определяется количеством тестовых подгрупп, которая прошла программа участника олимпиады.
Для оценки результата проведения олимпиады используется программа вывода
турнирной таблицы. Для запуска достаточно запустить файл jrun.bat, в результате
в папке появится html файл с турнирной таблицей.
.3 Разработка инструкции для администратора
Для модифицирования существующей системы, необходимо выполнить следующие действия.
В ядре системы заменить файл testing.cpp на предложенный новый, с последующей перекомпиляцией ядра.
В базе данных необходимо редактировать некоторые таблицы.
В таблицу STATUS добавить новое поле REPORT_VIEWED, тип CHAR(1).
Таблица TYPENAMES, в поле TP_NAME создать две новые строки «All-Russian school olympiad» для английского языка (en) и «Всероссийская олимпиада школьников» для русского языка (ru).
В таблице CONTTYPES добавить строку с новым id = 2.
Программа для вывода турнирной таблицы состоит из файлов: problems.txt, schoolkid.txt, Score.java, jrun.bat.
Problems.txt - должен хранить номера олимпиадных задач.
Schoolkid.txt - должен хранить id участника олимпиады, имя и фамилию. .java - программа для вывода турнирной таблицы.
Jrun.bat
- для запуска программы.
В ходе выполнения выпускной квалификационной работы была реализована модернизация существующего дистанционного практикума по программированию, кафедры АВТ. Модернизация была сделана с целью поддержки новых правил проведения олимпиад школьников.
В ходе модернизации удалось реализовать:
· Ввод нового типа турнира в интерфейсе пользователя.
· Отдельную программу для вывода турнирной таблицы.
· Модернизировать ядро системы для работы с новым конфигурационным файлом, с помощью которого можно проверять решение задачи на различных тестовых группах с конкретной разбалловкой.
Модернизация системы выполнена частично и пока не удовлетворяет всем требованиям проведения олимпиад по информатике среди школьников.
Не удалось реализовать следующие элементы:
· Детализированный вывод результатов по тестированию на каждой тестовой подгруппе.
· Ограничение на количество запрашиваемых детализированных отчетов.
· Формирование турнирной таблицы с учетом запроса участника олимпиады на вывод детализированного отчета по результату проверки задачи.
В дальнейшем, потребуется доработка указанных выше недостатков.
практикум программирование модернизация олимпиада
import java.sql.*;java.io.*;java.util.*;org.jsoup.*;org.jsoup.nodes.*;org.jsoup.select.*;class Score {
static class Schoolkid {
int id;
String name;
int solved;
Schoolkid(int id, String name) {
this.id = id;
this.name = name;
solved = 0;
}
static final Comparator<Schoolkid> mainComparator = new Comparator<Schoolkid>() {
@Override
public int compare(Schoolkid left, Schoolkid right) {
if (left.solved > right.solved) return -1;
if (left.solved < right.solved) return 1;
return left.name.compareTo(right.name);
}
};
};
public static void main(String[] args) throws Exception {
new Score().run();
}
void run() throws Exception {
// problems
Scanner in = new Scanner(new File("problems.txt"));
ArrayList<String> problems = new ArrayList<>();
StringBuilder prbList = new StringBuilder();
prbList.append('(');
while (in.hasNextInt()) {
String p = in.next();
problems.add(p);
if (p.charAt(0)>='0' && p.charAt(0)<='9') {
prbList.append(p);
prbList.append(',');
}
}
prbList.setCharAt(prbList.length() - 1, ')');
in.close();
// schoolkid -> names
in = new Scanner(new File("schoolkid.txt"));
ArrayList<Schoolkid> Schoolkids = new ArrayList<>();
StringBuilder schoolList = new StringBuilder();
schoolList.append('(');
while (in.hasNextInt()) {
int schoolId = in.nextInt();
String schoolName = in.nextLine();
Schoolkids.add(new Schoolkid(schoolId, schoolName));
schoolList.append(schoolId);
schoolList.append(',');
}
in.close();
schoolList.setCharAt(schoolList.length() - 1, ')');
// number of attempts
TreeMap<String, Integer> schoolPrb = new TreeMap<>();
Class.forName("org.firebirdsql.jdbc.FBDriver");
java.sql.Connection connection = DriverManager.getConnection("jdbc:firebirdsql:localhost/3050:c:/acm/db/acm.gdb", "SYSDBA", "masterkey");
Statement stmt = connection.createStatement();
try {
String query = "SELECT id_publ, id_prb, max(points) as score from status where id_publ in " +
schoolList + " and id_prb in " + prbList + " group by id_publ, id_prb";
ResultSet rs = stmt.executeQuery(query);
while (rs.next()) {
int id_publ = rs.getInt(1);
int id_prb = rs.getInt(2);
int score = rs.getInt(3);
String sp = id_publ + "|" + id_prb;
schoolPrb.put(sp, score);
}
} finally {
stmt.close();
// calculate solved for every Schoolkid
for (Schoolkid s : Schoolkids) {
for (String p : problems) {
String sp = s.id + "|" + p;
Integer score = schoolPrb.get(sp);
if (score != null && score > 0) {
s.solved += score;
}
}
}
Schoolkids.sort(Schoolkid.mainComparator);
// make result table