Фикс парсинга подгруппы и добавление парсинга пары типа "экзамен".

This commit is contained in:
2024-12-02 11:31:16 +04:00
parent e20fe9745d
commit 38badf3c2f
7 changed files with 159 additions and 53 deletions

View File

@@ -26,10 +26,18 @@ export class LessonDto {
case V2LessonType.INDEPENDENT_WORK:
case V2LessonType.EXAM:
case V2LessonType.EXAM_WITH_GRADE:
case V2LessonType.EXAM_DEFAULT:
return V2LessonType.DEFAULT;
default:
return value;
}
} else if (options?.groups?.includes("v2")) {
switch (value as V2LessonType) {
case V2LessonType.EXAM_DEFAULT:
return V2LessonType.EXAM;
default:
return value;
}
}
return value;
@@ -73,6 +81,8 @@ export class LessonDto {
return `ЗАЧЕТ | ${value}`;
case V2LessonType.EXAM_WITH_GRADE:
return `ЗАЧЕТ С ОЦЕНКОЙ | ${value}`;
case V2LessonType.EXAM_DEFAULT:
return `ЗАЧЕТ С ОЦЕНКОЙ | ${value}`;
default:
return value;
}

View File

@@ -1,9 +1,10 @@
export enum V2LessonType {
DEFAULT = 0,
ADDITIONAL,
BREAK,
CONSULTATION,
INDEPENDENT_WORK,
EXAM,
EXAM_WITH_GRADE,
DEFAULT = 0, // Обычная
ADDITIONAL, // Допы
BREAK, // Перемена
CONSULTATION, // Консультация
INDEPENDENT_WORK, // Самостоятельная работа
EXAM, // Зачёт
EXAM_WITH_GRADE, // Зачет с оценкой
EXAM_DEFAULT, // Экзамен
}

View File

@@ -55,35 +55,13 @@ describe("V2ScheduleParser", () => {
describe("Расписание", () => {
beforeEach(async () => {
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("Название дня не должно быть пустым или 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 () => {
const schedule = await parser.getSchedule().then((v) =>
instanceToInstance2(V2ScheduleParseResult, v, {
@@ -96,24 +74,13 @@ describe("V2ScheduleParser", () => {
schedule.groups.get("ИС-214/23");
expect(group).toBeDefined();
const tuesday = group.days[1];
expect(tuesday).toBeDefined();
const day = group.days[5];
expect(day).toBeDefined();
const oseLesson = tuesday.lessons[6];
expect(oseLesson).toBeDefined();
const lesson = day.lessons[0];
expect(lesson).toBeDefined();
expect(oseLesson.name.startsWith("Операционные")).toBe(true);
expect(oseLesson.type).toBe(V2LessonType.EXAM_WITH_GRADE);
expect(lesson.type).toBe(V2LessonType.EXAM);
});
// 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);
// });
});
});

View File

@@ -229,7 +229,7 @@ export class V2ScheduleParser {
for (const teacherAndSubGroup of all) {
const teacherRegex = /[А-ЯЁ][а-яё]+\s[А-ЯЁ]\.\s?[А-ЯЁ]\./g;
const subGroupRegex = /\([0-9]\s?подгруппа\)/g;
const subGroupRegex = /\([0-9]подгруппа\)/g;
const teacherMatch = teacherRegex.exec(teacherAndSubGroup);
if (teacherMatch === null) throw new Error("Парадокс");
@@ -242,7 +242,9 @@ export class V2ScheduleParser {
teacherFIO = `${teacherFIO.substring(0, teacherSpaceIndex)}${teacherIO}`;
const subGroupMatch = subGroupRegex.exec(teacherAndSubGroup);
const subGroupMatch = subGroupRegex.exec(
teacherAndSubGroup.replaceAll(" ", ""),
);
const subGroup = subGroupMatch
? Number.parseInt(subGroupMatch[0][1])
: 1;
@@ -277,7 +279,10 @@ export class V2ScheduleParser {
}
return {
name: lessonName.substring(0, allMatch.index).trim(),
name: lessonName
.substring(0, allMatch.index)
.replaceAll(".", "")
.trim(),
subGroups: subGroups,
};
}
@@ -645,7 +650,10 @@ export class V2ScheduleParser {
const lesson = new LessonDto();
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;
rawName = trimAll(rawName.replace("ЗАЧЕТ С ОЦЕНКОЙ", ""));
} else if (rawName.includes("ЗАЧЕТ")) {

View File

@@ -7,6 +7,7 @@ import { ScheduleReplacerController } from "./schedule-replacer.controller";
import { ScheduleService } from "./schedule.service";
import { V2ScheduleController } from "./v2-schedule.controller";
import { V3ScheduleController } from "./v3-schedule.controller";
import { V4ScheduleController } from "./v4-schedule.controller";
@Module({
imports: [forwardRef(() => UsersModule), FirebaseAdminModule],
@@ -14,6 +15,7 @@ import { V3ScheduleController } from "./v3-schedule.controller";
controllers: [
V2ScheduleController,
V3ScheduleController,
V4ScheduleController,
ScheduleReplacerController,
],
exports: [ScheduleService],

View File

@@ -25,6 +25,7 @@ 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("v3/schedule")
@ApiBearerAuth()
@@ -49,7 +50,11 @@ export class V3ScheduleController {
@HttpCode(HttpStatus.OK)
@Get()
async getSchedule(): Promise<ScheduleDto> {
return await this.scheduleService.getSchedule();
return await this.scheduleService.getSchedule().then((result) =>
instanceToInstance2(ScheduleDto, result, {
groups: ["v2"],
}),
);
}
@ApiOperation({ summary: "Получение расписания группы" })
@@ -68,7 +73,11 @@ export class V3ScheduleController {
async getGroupSchedule(
@UserToken(UserPipe) user: User,
): 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: "Получение расписания преподавателя" })
@@ -87,6 +96,10 @@ export class V3ScheduleController {
async getTeacherSchedule(
@Param("name") name: string,
): Promise<TeacherScheduleDto> {
return await this.scheduleService.getTeacher(name);
return await this.scheduleService.getTeacher(name).then((result) =>
instanceToInstance2(TeacherScheduleDto, result, {
groups: ["v2"],
}),
);
}
}

View 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"],
}),
);
}
}