import NUSModerator from 'nusmoderator' ; import { RawLesson , Weeks , Module , SemesterData , Semester } from '../types/modules' ; import { V1Module , V1RawLesson , V1SemesterData } from '../types/v1' ; import { AcademicGrp , AcademicOrg } from '../types/api' ; import { getLessonCovidZones , parseWorkload } from './GetSemesterData' ; import BaseTask from './BaseTask' ; import { Task } from '../types/tasks' ; import V1DataReader from '../services/io/v1-io' ; import { Logger } from '../services/logger' ; interface Input { departments : AcademicOrg [ ] ; faculties : AcademicGrp [ ] ; } type Output = Module [ ] ; function buildFacultyMap ( departments , faculties ) { const departmentFaculty = { } ; for ( const department of departments ) { for ( const faculty of faculties ) { if ( department . AcademicOrganisation . startsWith ( faculty . AcademicGroup ) ) { departmentFaculty [ department . Description ] = faculty . Description ; } } } return departmentFaculty ; } export default class MigrateV1ToV2 extends BaseTask implements Task < Input , Output > { name = 'Convert v1 modules to v2 data' ; logger = this . rootLogger . child ( { task : MigrateV1ToV2 . name , year : this . academicYear , } ) ; private v1DataReader : V1DataReader ; constructor ( academicYear ) { super ( academicYear ) ; this . v1DataReader = new V1DataReader ( academicYear ) ; } async run ( input ) { const modules = await this . v1DataReader . listModules ( ) ; const departmentFaculty = buildFacultyMap ( input . departments , input . faculties ) ; const convertedModules = await Promise . all ( modules . map ( async ( moduleCode ) => { const v1Module = await this . v1DataReader . getModule ( moduleCode ) ; const v2Module = this . convertModule ( v1Module , departmentFaculty , this . logger . child ( { moduleCode } ) ) ; await this . io . module ( moduleCode , v2Module ) ; return v2Module ; } ) ) ; return convertedModules ; } private convertWeekText = ( weekText , semester , logger ) : Weeks => { const cleanWeekText = weekText . replace ( /\s+/g , ' ' ) ; switch ( cleanWeekText ) { case 'Every Week' : return [ 1 , 2 , 3 , 4 , 5 , 6 , 7 , 8 , 9 , 10 , 11 , 12 , 13 ] ; case 'Odd Week' : return [ 3 , 5 , 7 , 9 , 11 , 13 ] ; case 'Even Week' : return [ 2 , 4 , 6 , 8 , 10 , 12 ] ; case 'Orientation Week' : { if ( semester !== 1 ) { logger . warn ( 'Orientation week weekText found for module in semester 2' ) ; return [ ] ; } const date = NUSModerator . academicCalendar . getAcadYearStartDate ( this . academicYear ) ; return { start : date . toISOString ( ) , end : date . toISOString ( ) , } ; } default : { const weeks = weekText . split ( /,\s*/ ) . map ( ( week ) => parseInt ( week , 10 ) ) ; const filteredWeeks = weeks . filter ( ( week ) => ! Number . isNaN ( week ) ) ; if ( filteredWeeks . length !== weeks . length ) { logger . warn ( 'Invalid week text found' , { weekText } ) ; } return filteredWeeks ; } } } ; private convertLesson = ( { ClassNo , LessonType , DayText , StartTime , EndTime , Venue , WeekText } , semester , logger ) : RawLesson => ( { classNo : ClassNo , lessonType : LessonType , day : DayText , startTime : StartTime , endTime : EndTime , weeks : this . convertWeekText ( WeekText , semester , logger ) , venue : Venue , size : 0 , covidZone : 'Unknown' , } ) ; private convertSemesterData = ( { ExamDate : examDate , Semester : semester , Timetable = [ ] } , logger ) : SemesterData => { const timetable = Timetable . map ( ( lesson ) => this . convertLesson ( lesson , semester , logger ) ) ; return { examDate , semester , timetable , covidZones : getLessonCovidZones ( timetable ) , } ; } ; private convertModule = ( { AcadYear , ModuleCode , ModuleCredit , ModuleTitle , History = [ ] , Workload , Department , Prerequisite , Corequisite , Preclusion , } , departmentFaculty , logger ) : Module => ( { acadYear : AcadYear , moduleCredit : ModuleCredit , moduleCode : ModuleCode , title : ModuleTitle , department : Department , faculty : departmentFaculty [ Department ] || '' , semesterData : History . map ( ( semester ) => this . convertSemesterData ( semester , logger ) ) , corequisite : Corequisite , prerequisite : Prerequisite , preclusion : Preclusion , workload : Workload ? parseWorkload ( Workload ) : undefined , } ) ; }