feat: Update parser to handle lesson type after teacher's name and add corresponding tests

This commit is contained in:
2026-10-23 22:14:00 +03:00
parent b9c1f63301
commit 416527fb33
3 changed files with 15 additions and 2 deletions

View File

@@ -158,6 +158,7 @@ npm run sync
- Строка с предметом и аудиторией над строками по видам — заголовок: её аудитория переходит к занятиям под ней.
- **Совмещённый вид.** «(л./п.з.)» и «(л. и п.з.)» — вид «Лекция и практика».
- **Подгруппа в тексте.** «12н.2п/гр. Экономика…» — занятие одной подгруппы.
- **Вид занятия после преподавателя** (парсер 18): «Русский язык как иностранный Козыренко А.Н.(п.з.) ауд.100» — название кончается там, где начинается преподаватель или вид, смотря что раньше. Раньше фамилия попадала в название (25‑ЭПи, 25‑ЭМ).
- **Ячейка из одной точки** — не занятие.
- **Время в начале ячейки:**
- интервал с дефисом «17:00‑17:20‑информационный час»;

View File

@@ -10,7 +10,7 @@ import { parseWeekRanges, parseTextDates, DATE_LIST, weekday } from "../shared/w
import { roomMoves, onlyPlace, weekPlan, partsByWeek } from "./rooms.js";
import { placeNote, lessonPlace, placeOf } from "./places.js";
const run = promisify(execFile);
export const PARSER_VERSION = 17;
export const PARSER_VERSION = 18;
const days = [
"понедельник",
"вторник",
@@ -98,8 +98,11 @@ export function details(text) {
rest.match(/\b(\d{2,3}\s*[А-Яа-я]?)\s*$/u) ||
// A room with a name instead of a number: "ауд.Медиа".
rest.match(/(?:ауд\.\s*)([А-ЯЁ][а-яё]{2,})(?![а-яё])/u);
// "Русский язык как иностранный Козыренко А.Н.(п.з.) ауд.100": the kind may follow the
// teacher, and the name ends where the first of them begins.
const end = [kind?.index, person?.index].filter((i) => i != null);
let subject = (named ? named[1].trim() : rest
.slice(0, kind?.index ?? person?.index ?? room?.index ?? rest.length))
.slice(0, end.length ? Math.min(...end) : room?.index ?? rest.length))
.trim()
.replace(/[–—,\-]+$/, "")
.trim();

View File

@@ -152,6 +152,15 @@ test("Пары для иностранных студентов и для ост
assert.equal(entries("Русский язык как иностранный (для иностранных студентов)\nХаткевич Т.В. ауд. 323н").length, 1);
});
test("Вид занятия после преподавателя: фамилия не входит в название", () => {
const after = details("Русский язык как иностранный Козыренко А.Н.(п.з.) ауд.100");
assert.equal(after.subject, "Русский язык как иностранный");
assert.equal(after.type, "Практика");
assert.equal(details("Русский язык как иностранный\nХаткевич Т.В. (п.з.) ауд.504н").subject, "Русский язык как иностранный");
// No subject at all: the cell's text stays visible.
assert.equal(details("(л.з.) Алексеева Т.А. ауд. 33н").subject, "(л.з.) Алексеева Т.А. ауд. 33н");
});
test("Старое имя разделённой группы: понятная ошибка, другое написание — та же группа", async () => {
const { timetable } = await import("../server/timetable.js");
const schedule = { groups: ["24-ИЯ (РА)и-1", "24-ИЯ (РА)и-2"], lessons: [], notes: [], period: "Осенний семестр", source: {} };