Files
psu-schedule/test/formats.test.js

131 lines
10 KiB
JavaScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
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");
});