made android client
This commit is contained in:
101
server/timetable.js
Normal file
101
server/timetable.js
Normal file
@@ -0,0 +1,101 @@
|
||||
// A group's timetable by date, with week numbers already applied. Native and
|
||||
// third-party clients use it instead of re-implementing the white/green week rules.
|
||||
import { semesterView, addDays, weekday, weekIndexOf } from "../shared/weeks.js";
|
||||
import { lessonKey, subgroupsOf } from "../shared/lessons.js";
|
||||
import { occurrence, peopleAndRooms, roomsOn } from "./directory.js";
|
||||
|
||||
const MAX_DAYS = 62;
|
||||
|
||||
function lessonOut(lesson, group, people, date, status, calendar) {
|
||||
const bell = calendar?.bells.find((b) => b.start === lesson.start);
|
||||
const rooms = date ? roomsOn(people, date) : people.rooms;
|
||||
return {
|
||||
key: lessonKey(lesson, group),
|
||||
start: lesson.start,
|
||||
end: lesson.end || bell?.end || null,
|
||||
pair: bell?.pair ?? null,
|
||||
subject: lesson.subject,
|
||||
type: lesson.type,
|
||||
teachers: people.teachers,
|
||||
rooms,
|
||||
roomMoved: Boolean(date && rooms !== people.rooms),
|
||||
distance: people.distance,
|
||||
condition: lesson.condition,
|
||||
variant: lesson.variant,
|
||||
subgroup: lesson.subgroups.find((s) => s.group === group)?.label || null,
|
||||
groups: lesson.groups,
|
||||
uncertain: status === "maybe",
|
||||
raw: lesson.raw,
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* days: one entry per date from `from`, with the lessons that take place that day.
|
||||
* weekly: the Word rows by weekday, for when dates cannot be calculated.
|
||||
*/
|
||||
export function timetable({ file, schedule, calendar, group, from, days }) {
|
||||
if (!schedule.groups.includes(group)) {
|
||||
const error = new Error(`В документе нет группы ${group}.`);
|
||||
error.status = 404;
|
||||
throw error;
|
||||
}
|
||||
const count = Math.min(Math.max(Number(days) || 7, 1), MAX_DAYS);
|
||||
const lessons = schedule.lessons.filter((l) => l.groups.includes(group));
|
||||
const entries = lessons.map((lesson) => ({
|
||||
doc: { id: file.id, schedule },
|
||||
lesson,
|
||||
...peopleAndRooms(lesson, schedule.academicYear),
|
||||
}));
|
||||
const view = semesterView(calendar, schedule, from);
|
||||
const views = new Map();
|
||||
const out = [];
|
||||
for (let i = 0; i < count; i++) {
|
||||
const date = addDays(from, i);
|
||||
const week = view ? view.weeks[weekIndexOf(view, date)] || null : null;
|
||||
const dayLessons = [];
|
||||
if (view)
|
||||
for (const entry of entries) {
|
||||
const status = occurrence(entry, date, calendar, views);
|
||||
if (status === "yes" || status === "maybe")
|
||||
dayLessons.push(lessonOut(entry.lesson, group, entry, date, status, calendar));
|
||||
}
|
||||
dayLessons.sort((a, b) => a.start.localeCompare(b.start));
|
||||
out.push({
|
||||
date,
|
||||
weekday: weekday(date),
|
||||
week: week ? { n: week.n, color: week.color } : null,
|
||||
lessons: dayLessons,
|
||||
});
|
||||
}
|
||||
const weekly = [1, 2, 3, 4, 5, 6, 7]
|
||||
.map((day) => ({
|
||||
day,
|
||||
lessons: entries
|
||||
.filter((e) => e.lesson.day === day && !e.lesson.date)
|
||||
.map((e) => lessonOut(e.lesson, group, e, null, "yes", calendar))
|
||||
.sort((a, b) => a.start.localeCompare(b.start)),
|
||||
}))
|
||||
.filter((d) => d.lessons.length);
|
||||
return {
|
||||
group,
|
||||
document: {
|
||||
id: file.id,
|
||||
name: file.name,
|
||||
faculty: file.faculty || schedule.source.faculty || "",
|
||||
course: file.course || schedule.source.course || "",
|
||||
modified: file.modified || schedule.source.modified || null,
|
||||
},
|
||||
period: schedule.period,
|
||||
semester: view?.semester || null,
|
||||
note: view
|
||||
? null
|
||||
: "Семестр этого расписания не найден в таблице недель: даты не рассчитаны, смотрите строки Word (weekly).",
|
||||
subgroups: subgroupsOf(schedule, group),
|
||||
bells: calendar?.bells || [],
|
||||
from,
|
||||
days: out,
|
||||
weekly,
|
||||
notes: schedule.notes,
|
||||
generatedAt: new Date().toISOString(),
|
||||
};
|
||||
}
|
||||
Reference in New Issue
Block a user