131 lines
10 KiB
JavaScript
131 lines
10 KiB
JavaScript
import { test } from "node:test";
|
||
import assert from "node:assert/strict";
|
||
import { groupsIn, alternatives, entries, details, leadingTime } from "../server/parser.js";
|
||
import { roomMoves, weekPlan, onlyPlace } from "../server/rooms.js";
|
||
import { peopleAndRooms, roomsOn, teachersOn, movedOn } from "../server/directory.js";
|
||
|
||
// Cell formats found by the catalog's diagnostics (October 2026).
|
||
|
||
test("Группы с направлением в скобках: 24-ИЯ (РА)и-1 … и-6 — разные группы", () => {
|
||
assert.deepEqual(groupsIn("24-ИЯ (РА)и-1 | 24-ИЯ (РА)и-2 | 24-ИЯ (РА)и-3"), ["24-ИЯ (РА)и-1", "24-ИЯ (РА)и-2", "24-ИЯ (РА)и-3"]);
|
||
assert.deepEqual(groupsIn("25 ИЯ (РА)и-1"), ["25-ИЯ (РА)и-1"]);
|
||
assert.deepEqual(groupsIn("24-РГФи-1 26-ИТ-2"), ["24-РГФи-1", "26-ИТ-2"]);
|
||
});
|
||
|
||
test("Перенос аудитории на дату, и с годом: «412н 26.10.2026-333»", () => {
|
||
assert.deepEqual(roomMoves("Типология (л.) Полякова Г.В. 412н 26.10.2026-333", 2026).moves, [{ date: "2026-10-26", room: "333" }]);
|
||
assert.deepEqual(roomMoves("Язык (п.з.) Горбач М.Н. 510н\n28.10.2026-504н", 2026).moves, [{ date: "2026-10-28", room: "504Н" }]);
|
||
assert.deepEqual(roomMoves("ауд. 432 14.10. -ауд. 333", 2026).moves, [{ date: "2026-10-14", room: "333" }]);
|
||
// The parser keeps the usual room; the move goes to that date only.
|
||
const lesson = { raw: "Типология (л.) Полякова Г.В. 412н 26.10.2026-333", room: "412н", teacher: "Полякова Г.В." };
|
||
const entry = peopleAndRooms(lesson, "2026");
|
||
assert.deepEqual(roomsOn(entry, "2026-10-26"), ["333"]);
|
||
assert.equal(movedOn(entry, "2026-10-26"), true);
|
||
assert.deepEqual(roomsOn(entry, "2026-10-19"), ["412Н"]);
|
||
assert.equal(movedOn(entry, "2026-10-19"), false);
|
||
});
|
||
|
||
test("Строка с аудиторией по неделям продолжает занятие, а не становится новым", () => {
|
||
const [one, ...rest] = entries("Язык профессионального общения (англ) (п.з.) Шабунина О.А.\n1-9н. 502н\nс 10н -359");
|
||
assert.equal(rest.length, 0);
|
||
assert.equal(details(one.main).subject, "Язык профессионального общения (англ)");
|
||
assert.deepEqual(one.plan, [
|
||
{ weeks: [[1, 9]], color: null, rooms: ["502Н"], teachers: [] },
|
||
{ weeks: [[10, null]], color: null, rooms: ["359"], teachers: [] },
|
||
]);
|
||
const entry = peopleAndRooms({ raw: one.text, room: "", teacher: "Шабунина О.А.", plan: one.plan }, "2026");
|
||
assert.deepEqual(roomsOn(entry, "2026-10-20", { n: 8, color: "green" }), ["502Н"]);
|
||
assert.deepEqual(roomsOn(entry, "2026-11-03", { n: 10, color: "green" }), ["359"]);
|
||
});
|
||
|
||
test("Преподаватель по неделям и аудитория по цвету недели", () => {
|
||
const teachers = weekPlan("2-9н.-Клос О.Ю., 10-14н.-Конторов В.Э. 319Д");
|
||
// The room at the end is the room of both parts.
|
||
assert.deepEqual(teachers, [
|
||
{ weeks: [[2, 9]], color: null, rooms: ["319Д"], teachers: ["Клос О.Ю."] },
|
||
{ weeks: [[10, 14]], color: null, rooms: ["319Д"], teachers: ["Конторов В.Э."] },
|
||
]);
|
||
const entry = peopleAndRooms({ raw: "2-14н. История литературы (п.з.)\n2-9н.-Клос О.Ю., 10-14н.-Конторов В.Э. 319Д", room: "", teacher: "", plan: teachers }, "2026");
|
||
assert.deepEqual(teachersOn(entry, { n: 3, color: "white" }), ["Клос О.Ю."]);
|
||
assert.deepEqual(teachersOn(entry, { n: 12, color: "green" }), ["Конторов В.Э."]);
|
||
|
||
const [lesson] = entries("с 10н. Дискурсивная практика (рус) (п.з.) Булах А.С.\nбел.н.504н/зел.н.524н");
|
||
const byColor = peopleAndRooms({ raw: lesson.text, room: "", teacher: "", plan: lesson.plan }, "2026");
|
||
assert.deepEqual(roomsOn(byColor, "2026-11-10", { n: 11, color: "white" }), ["504Н"]);
|
||
assert.deepEqual(roomsOn(byColor, "2026-11-17", { n: 12, color: "green" }), ["524Н"]);
|
||
// The colour after each room (25-ДО): "ауд.533н-б.н.,420н-з.н.".
|
||
const [after] = entries("Теоретические основы воспитания и развития речи детей раннего возраста (п.з.) Савейко В.Л. ауд.533н-б.н.,420н-з.н.");
|
||
assert.deepEqual(after.plan, [
|
||
{ weeks: null, color: "white", rooms: ["533Н"], teachers: ["Савейко В.Л."] },
|
||
{ weeks: null, color: "green", rooms: ["420Н"], teachers: ["Савейко В.Л."] },
|
||
]);
|
||
const roomAfter = peopleAndRooms({ raw: after.text, room: "533н", teacher: "Савейко В.Л.", plan: after.plan }, "2026");
|
||
assert.deepEqual(roomsOn(roomAfter, "2026-10-30", { n: 9, color: "white" }), ["533Н"]);
|
||
assert.deepEqual(roomsOn(roomAfter, "2026-10-23", { n: 8, color: "green" }), ["420Н"]);
|
||
assert.deepEqual(weekPlan("ауд. 420н з.н., 533н б.н.").map((p) => [p.color, p.rooms]), [["white", ["533Н"]], ["green", ["420Н"]]]);
|
||
assert.equal(onlyPlace("533н-б.н.,420н-з.н."), true);
|
||
// "32н" before its colour is a room, not week 32.
|
||
assert.deepEqual(weekPlan("Коррекционная дошкольная педагогика (л.) Остапчук С.В. ауд.64н -б.н., 32н-з.н.").map((p) => [p.color, p.rooms]), [["white", ["64Н"]], ["green", ["32Н"]]]);
|
||
assert.equal(onlyPlace("1-9н. 502н"), true);
|
||
assert.equal(onlyPlace("13,15 н. РБ (л.з) Сивацкий Д.С.209н"), false);
|
||
});
|
||
|
||
test("Строка с видом и неделями без предмета — тот же предмет в другие недели", () => {
|
||
const list = entries("2-6н. Потребительское право (л.) Савицкая К.Д. ауд. А1-06\n7,9,11н. – (п.з.) Савицкая К.Д. ауд. А1-06 8,12,14н. – (п.з.) Савицкая К.Д. ауд. А1-06");
|
||
assert.deepEqual(list.map((e) => [details(e.main).condition, details(e.main).subject, details(e.main).type]), [
|
||
["2-6н.", "Потребительское право", "Лекция"],
|
||
["7,9,11н.", "Потребительское право", "Практика"],
|
||
["8,12,14н.", "Потребительское право", "Практика"],
|
||
]);
|
||
assert.equal(details(list[0].main).room, "А1-06");
|
||
});
|
||
|
||
test("Дисциплины по выбору: заголовок, предмет перед неделями, виды по неделям", () => {
|
||
const read = (raw) => entries(raw).map((e) => ((d) => `${d.condition} ${d.subject} · ${d.type}`)(details(e.main)));
|
||
assert.deepEqual(read("Дисциплины по выбору: 1-16 н. Логика (л./п.з.) Магалинский И.В. ауд. С0-05\nСоциология 1-10 н. (л.) Шидловский С.О. 11-16 н. (п.з.) Лапацуева А.С.С0-03"), [
|
||
"1-16 н. Логика · Лекция и практика",
|
||
"1-10 н. Социология · Лекция",
|
||
"11-16 н. Социология · Практика",
|
||
]);
|
||
assert.deepEqual(read("Дисциплина по выбору: Социология ауд. С0-03\n1-10 н. (л.) Шидловский С.О.\n11-18 н. (п.з.) Лапацуева А.С."), [
|
||
"1-10 н. Социология · Лекция",
|
||
"11-18 н. Социология · Практика",
|
||
]);
|
||
assert.deepEqual(read("Дисциплина сцециализации: 4-14 н. Преступления в сфере информационных технологий (л.) Чижик Е.В. ауд. В0-05"), [
|
||
"4-14 н. Преступления в сфере информационных технологий · Лекция",
|
||
]);
|
||
assert.deepEqual(read("1-11н. - л., 12-14 – п.з. Защита населения Дмитриченко Н.С. ауд. 210м/к"), [
|
||
"1-11н. Защита населения · Лекция",
|
||
"12-14н. Защита населения · Практика",
|
||
]);
|
||
});
|
||
|
||
test("Время в начале ячейки: интервал с дефисом, заголовок со временем", () => {
|
||
assert.deepEqual(leadingTime("17:00-17:20-информационный час-Клос О.Ю. 319Д").starts, ["17:00"]);
|
||
assert.equal(leadingTime("17:00-17:20-информационный час").end, "17:20");
|
||
assert.deepEqual(alternatives("18.35+20.10 Новополоцк:\n1-5 н. Судебно-следственная психология (л.) Колесникова Е.В. ауд. 246"), [
|
||
"18.35+20.10 1-5 н. Судебно-следственная психология (л.) Колесникова Е.В. ауд. 246",
|
||
]);
|
||
});
|
||
|
||
test("Подгруппа в тексте ячейки, точка вместо занятия, заголовок заглавными", () => {
|
||
const own = details("12н.2п/гр. Экономика организаций (л.з.) Лисиченок Е.П. ауд.331");
|
||
assert.equal(own.subject, "Экономика организаций");
|
||
assert.equal(own.ownSubgroup, 2);
|
||
assert.deepEqual(entries("."), []);
|
||
assert.equal(details("ВВЕДЕНИЕ В ВЫСШЕЕ ОБРАЗОВАНИЕ\nг. Полоцк, Полоцкий коллегиум\n26-ГЕО, 26-ИТ-1 Ректорский вход\n26-ИТ-2, 26-СТ обзорная экскурсия").subject, "ВВЕДЕНИЕ В ВЫСШЕЕ ОБРАЗОВАНИЕ");
|
||
// A two-line subject stays whole.
|
||
assert.equal(details("Интеллектуальная собственность - драйвер инновационного развития\nна пространстве Евразии").subject.includes("Евразии"), true);
|
||
});
|
||
|
||
test("Старое имя разделённой группы: понятная ошибка, другое написание — та же группа", async () => {
|
||
const { timetable } = await import("../server/timetable.js");
|
||
const schedule = { groups: ["24-ИЯ (РА)и-1", "24-ИЯ (РА)и-2"], lessons: [], notes: [], period: "Осенний семестр", source: {} };
|
||
const file = { id: "doc", name: "24-ИЯ (РА)и-1_24-ИЯ (РА)и-2.docx" };
|
||
assert.throws(
|
||
() => timetable({ file, schedule, calendar: null, group: "24-ИЯ(РА)", from: "2026-10-19" }),
|
||
(e) => e.code === "group_not_found" && /разделена: 24-ИЯ \(РА\)и-1, 24-ИЯ \(РА\)и-2/.test(e.message),
|
||
);
|
||
assert.equal(timetable({ file, schedule, calendar: null, group: "24-ИЯ(РА)и-1", from: "2026-10-19" }).group, "24-ИЯ (РА)и-1");
|
||
});
|