mirror of
https://github.com/n08i40k/schedule-parser-next.git
synced 2025-12-06 09:47:46 +03:00
Фикс парсинга подгруппы и добавление парсинга пары типа "экзамен".
This commit is contained in:
@@ -26,10 +26,18 @@ export class LessonDto {
|
|||||||
case V2LessonType.INDEPENDENT_WORK:
|
case V2LessonType.INDEPENDENT_WORK:
|
||||||
case V2LessonType.EXAM:
|
case V2LessonType.EXAM:
|
||||||
case V2LessonType.EXAM_WITH_GRADE:
|
case V2LessonType.EXAM_WITH_GRADE:
|
||||||
|
case V2LessonType.EXAM_DEFAULT:
|
||||||
return V2LessonType.DEFAULT;
|
return V2LessonType.DEFAULT;
|
||||||
default:
|
default:
|
||||||
return value;
|
return value;
|
||||||
}
|
}
|
||||||
|
} else if (options?.groups?.includes("v2")) {
|
||||||
|
switch (value as V2LessonType) {
|
||||||
|
case V2LessonType.EXAM_DEFAULT:
|
||||||
|
return V2LessonType.EXAM;
|
||||||
|
default:
|
||||||
|
return value;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return value;
|
return value;
|
||||||
@@ -73,6 +81,8 @@ export class LessonDto {
|
|||||||
return `ЗАЧЕТ | ${value}`;
|
return `ЗАЧЕТ | ${value}`;
|
||||||
case V2LessonType.EXAM_WITH_GRADE:
|
case V2LessonType.EXAM_WITH_GRADE:
|
||||||
return `ЗАЧЕТ С ОЦЕНКОЙ | ${value}`;
|
return `ЗАЧЕТ С ОЦЕНКОЙ | ${value}`;
|
||||||
|
case V2LessonType.EXAM_DEFAULT:
|
||||||
|
return `ЗАЧЕТ С ОЦЕНКОЙ | ${value}`;
|
||||||
default:
|
default:
|
||||||
return value;
|
return value;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,9 +1,10 @@
|
|||||||
export enum V2LessonType {
|
export enum V2LessonType {
|
||||||
DEFAULT = 0,
|
DEFAULT = 0, // Обычная
|
||||||
ADDITIONAL,
|
ADDITIONAL, // Допы
|
||||||
BREAK,
|
BREAK, // Перемена
|
||||||
CONSULTATION,
|
CONSULTATION, // Консультация
|
||||||
INDEPENDENT_WORK,
|
INDEPENDENT_WORK, // Самостоятельная работа
|
||||||
EXAM,
|
EXAM, // Зачёт
|
||||||
EXAM_WITH_GRADE,
|
EXAM_WITH_GRADE, // Зачет с оценкой
|
||||||
|
EXAM_DEFAULT, // Экзамен
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -55,35 +55,13 @@ describe("V2ScheduleParser", () => {
|
|||||||
describe("Расписание", () => {
|
describe("Расписание", () => {
|
||||||
beforeEach(async () => {
|
beforeEach(async () => {
|
||||||
await setLink(
|
await setLink(
|
||||||
"https://politehnikum-eng.ru/2024/poltavskaja_12_s_18_po_24_11.xls",
|
"https://politehnikum-eng.ru/2024/poltavskaja_14_s_2_po_8_12.xls",
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
it("Должен вернуть расписание", defaultTest);
|
it("Должен вернуть расписание", defaultTest);
|
||||||
it("Название дня не должно быть пустым или null", nameTest);
|
it("Название дня не должно быть пустым или null", nameTest);
|
||||||
|
|
||||||
it("Зачёт с оценкой v1", async () => {
|
|
||||||
const schedule = await parser.getSchedule().then((v) =>
|
|
||||||
instanceToInstance2(V2ScheduleParseResult, v, {
|
|
||||||
groups: ["v1"],
|
|
||||||
}),
|
|
||||||
);
|
|
||||||
expect(schedule).toBeDefined();
|
|
||||||
|
|
||||||
const group: GroupDto | undefined =
|
|
||||||
schedule.groups.get("ИС-214/23");
|
|
||||||
expect(group).toBeDefined();
|
|
||||||
|
|
||||||
const tuesday = group.days[1];
|
|
||||||
expect(tuesday).toBeDefined();
|
|
||||||
|
|
||||||
const oseLesson = tuesday.lessons[6];
|
|
||||||
expect(oseLesson).toBeDefined();
|
|
||||||
|
|
||||||
expect(oseLesson.name.startsWith("ЗАЧЕТ С ОЦЕНКОЙ | ")).toBe(true);
|
|
||||||
expect(oseLesson.type).toBe(V2LessonType.DEFAULT);
|
|
||||||
});
|
|
||||||
|
|
||||||
it("Зачёт с оценкой v2", async () => {
|
it("Зачёт с оценкой v2", async () => {
|
||||||
const schedule = await parser.getSchedule().then((v) =>
|
const schedule = await parser.getSchedule().then((v) =>
|
||||||
instanceToInstance2(V2ScheduleParseResult, v, {
|
instanceToInstance2(V2ScheduleParseResult, v, {
|
||||||
@@ -96,24 +74,13 @@ describe("V2ScheduleParser", () => {
|
|||||||
schedule.groups.get("ИС-214/23");
|
schedule.groups.get("ИС-214/23");
|
||||||
expect(group).toBeDefined();
|
expect(group).toBeDefined();
|
||||||
|
|
||||||
const tuesday = group.days[1];
|
const day = group.days[5];
|
||||||
expect(tuesday).toBeDefined();
|
expect(day).toBeDefined();
|
||||||
|
|
||||||
const oseLesson = tuesday.lessons[6];
|
const lesson = day.lessons[0];
|
||||||
expect(oseLesson).toBeDefined();
|
expect(lesson).toBeDefined();
|
||||||
|
|
||||||
expect(oseLesson.name.startsWith("Операционные")).toBe(true);
|
expect(lesson.type).toBe(V2LessonType.EXAM);
|
||||||
expect(oseLesson.type).toBe(V2LessonType.EXAM_WITH_GRADE);
|
|
||||||
});
|
});
|
||||||
|
|
||||||
// it("Суббота не должна отсутствовать", async () => {
|
|
||||||
// const schedule = await parser.getSchedule();
|
|
||||||
// expect(schedule).toBeDefined();
|
|
||||||
//
|
|
||||||
// const group: V2GroupDto | undefined = schedule.groups["ИС-214/23"];
|
|
||||||
// expect(group).toBeDefined();
|
|
||||||
//
|
|
||||||
// expect(group.days.length).toBe(6);
|
|
||||||
// });
|
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -229,7 +229,7 @@ export class V2ScheduleParser {
|
|||||||
|
|
||||||
for (const teacherAndSubGroup of all) {
|
for (const teacherAndSubGroup of all) {
|
||||||
const teacherRegex = /[А-ЯЁ][а-яё]+\s[А-ЯЁ]\.\s?[А-ЯЁ]\./g;
|
const teacherRegex = /[А-ЯЁ][а-яё]+\s[А-ЯЁ]\.\s?[А-ЯЁ]\./g;
|
||||||
const subGroupRegex = /\([0-9]\s?подгруппа\)/g;
|
const subGroupRegex = /\([0-9]подгруппа\)/g;
|
||||||
|
|
||||||
const teacherMatch = teacherRegex.exec(teacherAndSubGroup);
|
const teacherMatch = teacherRegex.exec(teacherAndSubGroup);
|
||||||
if (teacherMatch === null) throw new Error("Парадокс");
|
if (teacherMatch === null) throw new Error("Парадокс");
|
||||||
@@ -242,7 +242,9 @@ export class V2ScheduleParser {
|
|||||||
|
|
||||||
teacherFIO = `${teacherFIO.substring(0, teacherSpaceIndex)}${teacherIO}`;
|
teacherFIO = `${teacherFIO.substring(0, teacherSpaceIndex)}${teacherIO}`;
|
||||||
|
|
||||||
const subGroupMatch = subGroupRegex.exec(teacherAndSubGroup);
|
const subGroupMatch = subGroupRegex.exec(
|
||||||
|
teacherAndSubGroup.replaceAll(" ", ""),
|
||||||
|
);
|
||||||
const subGroup = subGroupMatch
|
const subGroup = subGroupMatch
|
||||||
? Number.parseInt(subGroupMatch[0][1])
|
? Number.parseInt(subGroupMatch[0][1])
|
||||||
: 1;
|
: 1;
|
||||||
@@ -277,7 +279,10 @@ export class V2ScheduleParser {
|
|||||||
}
|
}
|
||||||
|
|
||||||
return {
|
return {
|
||||||
name: lessonName.substring(0, allMatch.index).trim(),
|
name: lessonName
|
||||||
|
.substring(0, allMatch.index)
|
||||||
|
.replaceAll(".", "")
|
||||||
|
.trim(),
|
||||||
subGroups: subGroups,
|
subGroups: subGroups,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
@@ -645,7 +650,10 @@ export class V2ScheduleParser {
|
|||||||
const lesson = new LessonDto();
|
const lesson = new LessonDto();
|
||||||
|
|
||||||
if (this.otherStreetRegExp.test(rawName)) return rawName;
|
if (this.otherStreetRegExp.test(rawName)) return rawName;
|
||||||
else if (rawName.includes("ЗАЧЕТ С ОЦЕНКОЙ")) {
|
else if (rawName.includes("ЭКЗАМЕН")) {
|
||||||
|
lesson.type = V2LessonType.EXAM_DEFAULT;
|
||||||
|
rawName = trimAll(rawName.replace("ЭКЗАМЕН", ""));
|
||||||
|
} else if (rawName.includes("ЗАЧЕТ С ОЦЕНКОЙ")) {
|
||||||
lesson.type = V2LessonType.EXAM_WITH_GRADE;
|
lesson.type = V2LessonType.EXAM_WITH_GRADE;
|
||||||
rawName = trimAll(rawName.replace("ЗАЧЕТ С ОЦЕНКОЙ", ""));
|
rawName = trimAll(rawName.replace("ЗАЧЕТ С ОЦЕНКОЙ", ""));
|
||||||
} else if (rawName.includes("ЗАЧЕТ")) {
|
} else if (rawName.includes("ЗАЧЕТ")) {
|
||||||
|
|||||||
@@ -7,6 +7,7 @@ import { ScheduleReplacerController } from "./schedule-replacer.controller";
|
|||||||
import { ScheduleService } from "./schedule.service";
|
import { ScheduleService } from "./schedule.service";
|
||||||
import { V2ScheduleController } from "./v2-schedule.controller";
|
import { V2ScheduleController } from "./v2-schedule.controller";
|
||||||
import { V3ScheduleController } from "./v3-schedule.controller";
|
import { V3ScheduleController } from "./v3-schedule.controller";
|
||||||
|
import { V4ScheduleController } from "./v4-schedule.controller";
|
||||||
|
|
||||||
@Module({
|
@Module({
|
||||||
imports: [forwardRef(() => UsersModule), FirebaseAdminModule],
|
imports: [forwardRef(() => UsersModule), FirebaseAdminModule],
|
||||||
@@ -14,6 +15,7 @@ import { V3ScheduleController } from "./v3-schedule.controller";
|
|||||||
controllers: [
|
controllers: [
|
||||||
V2ScheduleController,
|
V2ScheduleController,
|
||||||
V3ScheduleController,
|
V3ScheduleController,
|
||||||
|
V4ScheduleController,
|
||||||
ScheduleReplacerController,
|
ScheduleReplacerController,
|
||||||
],
|
],
|
||||||
exports: [ScheduleService],
|
exports: [ScheduleService],
|
||||||
|
|||||||
@@ -25,6 +25,7 @@ import { UserRole } from "../users/user-role.enum";
|
|||||||
import { User } from "../users/entity/user.entity";
|
import { User } from "../users/entity/user.entity";
|
||||||
import { GroupScheduleDto } from "./dto/group-schedule.dto";
|
import { GroupScheduleDto } from "./dto/group-schedule.dto";
|
||||||
import { TeacherScheduleDto } from "./dto/teacher-schedule.dto";
|
import { TeacherScheduleDto } from "./dto/teacher-schedule.dto";
|
||||||
|
import instanceToInstance2 from "../utility/class-trasformer/instance-to-instance-2";
|
||||||
|
|
||||||
@ApiTags("v3/schedule")
|
@ApiTags("v3/schedule")
|
||||||
@ApiBearerAuth()
|
@ApiBearerAuth()
|
||||||
@@ -49,7 +50,11 @@ export class V3ScheduleController {
|
|||||||
@HttpCode(HttpStatus.OK)
|
@HttpCode(HttpStatus.OK)
|
||||||
@Get()
|
@Get()
|
||||||
async getSchedule(): Promise<ScheduleDto> {
|
async getSchedule(): Promise<ScheduleDto> {
|
||||||
return await this.scheduleService.getSchedule();
|
return await this.scheduleService.getSchedule().then((result) =>
|
||||||
|
instanceToInstance2(ScheduleDto, result, {
|
||||||
|
groups: ["v2"],
|
||||||
|
}),
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ApiOperation({ summary: "Получение расписания группы" })
|
@ApiOperation({ summary: "Получение расписания группы" })
|
||||||
@@ -68,7 +73,11 @@ export class V3ScheduleController {
|
|||||||
async getGroupSchedule(
|
async getGroupSchedule(
|
||||||
@UserToken(UserPipe) user: User,
|
@UserToken(UserPipe) user: User,
|
||||||
): Promise<GroupScheduleDto> {
|
): Promise<GroupScheduleDto> {
|
||||||
return await this.scheduleService.getGroup(user.group);
|
return await this.scheduleService.getGroup(user.group).then((result) =>
|
||||||
|
instanceToInstance2(GroupScheduleDto, result, {
|
||||||
|
groups: ["v2"],
|
||||||
|
}),
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ApiOperation({ summary: "Получение расписания преподавателя" })
|
@ApiOperation({ summary: "Получение расписания преподавателя" })
|
||||||
@@ -87,6 +96,10 @@ export class V3ScheduleController {
|
|||||||
async getTeacherSchedule(
|
async getTeacherSchedule(
|
||||||
@Param("name") name: string,
|
@Param("name") name: string,
|
||||||
): Promise<TeacherScheduleDto> {
|
): Promise<TeacherScheduleDto> {
|
||||||
return await this.scheduleService.getTeacher(name);
|
return await this.scheduleService.getTeacher(name).then((result) =>
|
||||||
|
instanceToInstance2(TeacherScheduleDto, result, {
|
||||||
|
groups: ["v2"],
|
||||||
|
}),
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
105
src/schedule/v4-schedule.controller.ts
Normal file
105
src/schedule/v4-schedule.controller.ts
Normal file
@@ -0,0 +1,105 @@
|
|||||||
|
import {
|
||||||
|
Controller,
|
||||||
|
Get,
|
||||||
|
HttpCode,
|
||||||
|
HttpStatus,
|
||||||
|
Param,
|
||||||
|
UseGuards,
|
||||||
|
UseInterceptors,
|
||||||
|
} from "@nestjs/common";
|
||||||
|
import { AuthGuard } from "../auth/auth.guard";
|
||||||
|
import { ResultDto } from "../utility/validation/class-validator.interceptor";
|
||||||
|
import {
|
||||||
|
ApiBearerAuth,
|
||||||
|
ApiOperation,
|
||||||
|
ApiResponse,
|
||||||
|
ApiTags,
|
||||||
|
} from "@nestjs/swagger";
|
||||||
|
import { AuthRoles } from "../auth/auth-role.decorator";
|
||||||
|
import { UserToken } from "../auth/auth.decorator";
|
||||||
|
import { UserPipe } from "../auth/auth.pipe";
|
||||||
|
import { ScheduleService } from "./schedule.service";
|
||||||
|
import { ScheduleDto } from "./dto/schedule.dto";
|
||||||
|
import { CacheInterceptor, CacheKey } from "@nestjs/cache-manager";
|
||||||
|
import { UserRole } from "../users/user-role.enum";
|
||||||
|
import { User } from "../users/entity/user.entity";
|
||||||
|
import { GroupScheduleDto } from "./dto/group-schedule.dto";
|
||||||
|
import { TeacherScheduleDto } from "./dto/teacher-schedule.dto";
|
||||||
|
import instanceToInstance2 from "../utility/class-trasformer/instance-to-instance-2";
|
||||||
|
|
||||||
|
@ApiTags("v4/schedule")
|
||||||
|
@ApiBearerAuth()
|
||||||
|
@Controller({ path: "schedule", version: "4" })
|
||||||
|
@UseGuards(AuthGuard)
|
||||||
|
export class V4ScheduleController {
|
||||||
|
constructor(private readonly scheduleService: ScheduleService) {}
|
||||||
|
|
||||||
|
@ApiOperation({
|
||||||
|
summary: "Получение расписания",
|
||||||
|
tags: ["admin"],
|
||||||
|
})
|
||||||
|
@ApiResponse({
|
||||||
|
status: HttpStatus.OK,
|
||||||
|
description: "Расписание получено успешно",
|
||||||
|
type: ScheduleDto,
|
||||||
|
})
|
||||||
|
@ResultDto(ScheduleDto)
|
||||||
|
@AuthRoles([UserRole.ADMIN])
|
||||||
|
@CacheKey("v4-schedule")
|
||||||
|
@UseInterceptors(CacheInterceptor)
|
||||||
|
@HttpCode(HttpStatus.OK)
|
||||||
|
@Get()
|
||||||
|
async getSchedule(): Promise<ScheduleDto> {
|
||||||
|
return await this.scheduleService.getSchedule().then((result) =>
|
||||||
|
instanceToInstance2(ScheduleDto, result, {
|
||||||
|
groups: ["v3"],
|
||||||
|
}),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
@ApiOperation({ summary: "Получение расписания группы" })
|
||||||
|
@ApiResponse({
|
||||||
|
status: HttpStatus.OK,
|
||||||
|
description: "Расписание получено успешно",
|
||||||
|
type: GroupScheduleDto,
|
||||||
|
})
|
||||||
|
@ApiResponse({
|
||||||
|
status: HttpStatus.NOT_FOUND,
|
||||||
|
description: "Требуемая группа не найдена",
|
||||||
|
})
|
||||||
|
@ResultDto(GroupScheduleDto)
|
||||||
|
@HttpCode(HttpStatus.OK)
|
||||||
|
@Get("group")
|
||||||
|
async getGroupSchedule(
|
||||||
|
@UserToken(UserPipe) user: User,
|
||||||
|
): Promise<GroupScheduleDto> {
|
||||||
|
return await this.scheduleService.getGroup(user.group).then((result) =>
|
||||||
|
instanceToInstance2(GroupScheduleDto, result, {
|
||||||
|
groups: ["v3"],
|
||||||
|
}),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
@ApiOperation({ summary: "Получение расписания преподавателя" })
|
||||||
|
@ApiResponse({
|
||||||
|
status: HttpStatus.OK,
|
||||||
|
description: "Расписание получено успешно",
|
||||||
|
type: TeacherScheduleDto,
|
||||||
|
})
|
||||||
|
@ApiResponse({
|
||||||
|
status: HttpStatus.NOT_FOUND,
|
||||||
|
description: "Требуемый преподаватель не найден",
|
||||||
|
})
|
||||||
|
@ResultDto(TeacherScheduleDto)
|
||||||
|
@HttpCode(HttpStatus.OK)
|
||||||
|
@Get("teacher/:name")
|
||||||
|
async getTeacherSchedule(
|
||||||
|
@Param("name") name: string,
|
||||||
|
): Promise<TeacherScheduleDto> {
|
||||||
|
return await this.scheduleService.getTeacher(name).then((result) =>
|
||||||
|
instanceToInstance2(TeacherScheduleDto, result, {
|
||||||
|
groups: ["v3"],
|
||||||
|
}),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user