Каким может быть расписание ВУЗа

в 6:43, , рубрики: php, Веб-разработка, расписание, метки:

Пользуясь медленными и неудобными информационными ресурсами в сети можно проклинать их создателей и терять время, а можно написать паука, который соберёт и классифицирует информацию нужным образом. Уже обработанная информация будет доступна в любой плоскости и с таким откликом, который требуется. Эта статья об одном из таких опытов. С практическим примером разбора и улучшения расписания НГУ (Новосибирского государственного университета).

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

Идея заключалась в том, чтобы упростить доступ к расписанию. Оригинальное расписание, доступное на сайте НГУ, можно посмотреть здесь. Для того, чтобы найти собственное расписание мне приходилось начинать свой путь с главной страницы сайта, переходить на “старый сайт”, затем “информационные системы”, далее “расписание занятий”, выбрать корпус, факультет, группу, итого — 6 кликов. Большая часть этих переходов казалась вполне осмысленной, кроме выбора корпуса: казалось бы, зачем выбирать корпус, если факультеты всё равно разные, да и общее их число не так велико, чтобы разбивать на две страницы (всего около 10)? Но ситуация становилась немного сложней, если нужно было найти расписание преподавателя или друга. Для преподавателя нужно было в худшем случае проверить оба корпуса, а для друга нужно было найти сначала его в списках групп, узнать номер группы, а потом уже всё остальное. Шаги вполне выполнимые, но не всегда захочется их совершать, а ведь ничего не мешает собрать эту информацию и сделать возможность осуществлять такие выборки просто набрав в строке имя человека, расписание которого требуется узнать — как в поисковых системах, к которым все уже привыкли.

Разбор списков

Начнём со списка студентов: к счастью, он доступен в виде xml, и для каждой группы выглядит следующим образом:

<group name="0502, геолого-геофизический факультет, геология (бакалавриат)">
<student name="Шабалин Сергей Игоревич" status=""/>
<student name="Шелепов Ярослав Юрьевич" status=""/>
<student name="Шепель Яна Евгеньевна" status=""/>
...
</group>

Для того, чтобы экспортировать такие данные, используется следующий код:

public function exportGroup($groupFile, $groupName, $department, $course) {
	$grouplist=file_get_contents($groupFile);
	$dom2 = new domDocument;
	$dom2->loadXML($grouplist);
	$s2 = simplexml_import_dom($dom2);
	for ($k=0;$k<count($s2->student);$k++) {
		$attrs=$s2->student[$k]->attributes();
		$student=new Student();
		$student->name=$attrs["name"];
		$student->group=$groupName;
		$student->department=$department;
		$student->course=$course;
		$student->save();
	}
}

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

Исправление до валидного

Само расписание занятий не доступно в xml, кроме того, html, сгенерированный системой расписаний НГУ, оказался невалидным, что поставило меня перед выбором: преобразовывать его к валидному или разбирать регулярными выражениями. Надо сказать, что как-то уж очень не хотелось прибегать к regexp-ам. Разглядывая html файлы я понял, что не так уж много нужно сделать, чтобы документы стали валидными, а именно, добавить один тег <tr> (отсутствовал) и указать кодировку. Получилось следующее:

$text=file_get_contents($url);
$text = iconv ( "CP1251" , "UTF-8" , $text );

$doc = new DOMDocument();
$doc->loadHTML(str_replace("</HEAD>", '<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
</HEAD>', str_replace("<TH Width=10%>", "<TR><TH Width=10%>", $text)));
$s = simplexml_import_dom($doc);

после этих манипуляций расписание замечательным образом разбиралось. Надо отметить, что можно было не перекодировать в utf, но так как все остальные данные проекта находились в utf, а кодировка в этих файлах не была указана — я предпочёл провести конвертацию на этом шаге.

Поиск

Таким образом у меня получились расписание групп и преподавателей, а также списки студентов.
Расписание в получившейся структуре относится к группе или преподавателю, но не к студенту. Для поиска по студентам, преподавателям, группам и факультетам требовался сложный запрос или несколько запросов к серверу базы данных. Составить такой запрос не проблема, но я опасался за скорость его выполнения. Было решено сделать отдельную таблицу для поиска “searchable”, которая бы содержала в одном столбце псевдонимы, по которым осуществляется поиск, а в другой — адрес документа. В первую очередь — для оптимизации времени доступа. Также это дало возможность обрабатывать запросы вроде “математик василий 1 курс”, но в то же время позволило иметь неконсистентные состояния базы данных, поскольку адрес документа (url) содержится в нескольких различных таблицах. Последнее никак не плюс, но плюсы в данном случае мне виделись гораздо более значительными, чем этот минус.

REST API

Для того чтобы у других не было потребности выполнять всю эту рутину заново я опубликовал открытое REST API, которое уже вроде бы используется в двух сторонних проектах. Запрос к API содержит строку поиска и тип запрашиваемого расписания: на день, на неделю и ближайшая пара. Ответ содержит расписание в формате JSON или возможные названия и адреса соответствующих расписаний, когда заданной строке соответствует несколько расписаний.

Расшифровка сокращений

После публикации довольно много людей говорили, что в расписании используются непонятные сокращения, которые сложно интерпретировать (например, «О.об.химии» это «Основы общей и неорганической химии», а «ТФКП» — «Теория функций комплексного переменного»). Путей решения этой проблемы я видел два: 1. Предоставить студентам возможность самим указывать полные названия и 2. Попытаться каким-то образом их расшифровать. Первый вариант выглядел простым и весёлым, но спорным, поскольку требовалось вводить систему модерации и возможность смотреть без расшифровки, поскольку я сам не мог определить, насколько верное название было предоставлено, а найти экспертов с каждого факультета практически значит попросить нескольких людей расшифровать эти сокращения. Я попытался изыскать возможность автоматической расшифровки, обнаружил списки кафедр и преподавателей с предметами. Списки эти оказались не полными, но, надо сказать, что и списки студентов абсолютной точностью не отличались. Ко всему, имена преподавателей в списке по кафедрам указаны с расшифровкой имени и отчества, а в расписании с инициалами, но это не такая большая проблема. Первая идея была в том, чтобы найти таких преподавателей, которые ведут только один предмет и по ним определить все названия (в НГУ большинство — совмещают преподавание с другой работой и таких, кто ведёт одну дисциплину немало), но этот метод неожиданно провалился и дал неправильные результаты. Возможно, дело в том, что преподаватели с одним предметом не часто входили в те кафедральные списки, которые мне удалось получить. Дальше я пробовал сравнивать по количеству совпадающих букв, но получились тоже довольно странные результаты. Наилучшим оказался метод, который устанавливает соответствие между сокращённым названием и полным только если у этого преподавателя это единственный предмет, начинающийся на эту букву. Таким образом удалось расшифровать большинство предметов.

По аудиториям

Кроме того, у меня очень чесались руки провести статистическое исследование загруженности аудиторий/преподавателей, и мне пришла идея, что можно выводить информацию из расписания на текущий момент: кто и в каких аудиториях сейчас находится, сколько человек, сколько студентов мужского пола, а сколько — женского. Последняя характеристика конечно же была придумана просто для того чтобы сделать проект более весёлым, можно было бы просто вывести все имена, но проблема была в том, что номера групп в расписании не всегда хорошо соответствовали номерам в списках студентов. Например, в расписании могли быть группы 123.1, 123.2, 123.3, а в списках только 123. Таким образом, можно приблизительно сказать сколько человек в каждой группе, но нельзя точно сказать кто именно в какой. Для определения пола я использовал имена студентов. Надо сказать, что определение было настолько точным, насколько я точно могу сам отличить мужское имя от женского, это оказалось не всегда возможно, но в большинстве случаев отлично работает. Исходя из этой информации была построена карта аудиторий, которая обновляется автоматически каждые 10 минут и отображает количество студентов, студенток, количество мест (максимальное число, встречающееся в расписании) и номера групп, которые в данный момент находятся в этой аудитории. Может быть очень полезно если вы ищете пустую аудиторию или потеряли какую-то вещь и хотели бы опросить всех, кто мог её видеть.
Из расписания были выбраны аудитории, разобраны постфиксы, обозначающие корпус, а дальше выведены на странице так, что получился список следующего вида:

Каким может быть расписание ВУЗа

для каждой аудитории/корпуса отображается график загруженности на любой введённый день

Каким может быть расписание ВУЗа

Это график для главного корпуса НГУ на пятницу; сервис позволяет смотреть такие для любой аудитории или корпуса на любой учебный день (на не учебные график пустой). Здесь по Y — количество человек, время — начало пар. Красный столбик — студентки, синий — студенты, серый — сумма. Бросается в глаза дробная шкала по Y, дело в том, что у меня не получилось настроить библиотеку рисования графиков для вывода только целых чисел, но мне кажется это не сильно принципиальным. Да, дробного количества людей не бывает, но столбики и не упираются в нецелые числа.

Перед тем как написать статью я решил посмотреть как же всё устроено в МГУ и нашёл расписание, даже карту пустых аудиторий, но оказалось, что для получения информации нужно запастись терпением; и дело даже не в количестве кликов, которых тоже предостаточно, а в очень медленном отклике. Из появляющихся периодически ошибок SQL можно сделать выводы об использовании СУБД, но, видимо как-то не слишком оптимально всё устроено.

Статистика

Имеющиеся данные позволили также получить некоторые более глобальные цифры.

Средняя загрузка аудиторий с учётом максимальной вместимости — 28% (сумма занимающихся студентов разделенная на суммарную вместимость аудиторий, усреднённая по дням и времени)

Средняя загрузка аудитории в НГУ, если считать её загруженной полностью, когда хотя бы один студент занимается — 60%

Самые женские аудитории — 500, 431 и 608 — около 89% девушек

Самая мужская аудитория — 312, всего 10% девушек

Наиболее женское время — 14:15, 53% девушек

Наиболее мужское время — 19:20, 46.8% девушек

Наиболее женский день — вторник, 52.3% девушек

Наиболее мужской день — понедельник 49.2% девушек

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

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

Ссылки:

оригинальное расписание
www.nsu.ru/education/schedule/
разобранный прототип
nsu-schedule.ru/
карта аудиторий on-line
nsu-schedule.ru/now/
упоминаемое расписание МГУ
cacs.law.msu.ru/

Автор: parsifal

Источник


* - обязательные к заполнению поля


https://ajax.googleapis.com/ajax/libs/jquery/3.4.1/jquery.min.js