feat: interactive School class

This commit is contained in:
Starcea 2024-06-28 16:34:37 +09:00
commit 1671dda26e
No known key found for this signature in database
GPG key ID: B7A77E32374911E1
6 changed files with 130 additions and 43 deletions

View file

@ -1,8 +1,7 @@
import { BASE_URL, USER_AGENT } from './constants' import { BASE_URL, USER_AGENT } from './constants'
import DataManager from './data' import DataManager from './data'
import type { School } from './models/School' import School from './models/School'
import type { Timetable } from './models/Timetable' import type Timetable from './models/Timetable'
import { TimetableManager } from './models/Timetable'
import { encodeBase64, encodeEUCKR } from './utils/encode' import { encodeBase64, encodeEUCKR } from './utils/encode'
import { log10int } from './utils/math' import { log10int } from './utils/math'
import { parseResponse } from './utils/parse' import { parseResponse } from './utils/parse'
@ -28,17 +27,27 @@ export default class Comcigan {
: [number, string, string, number][] : [number, string, string, number][]
}>(res.data) }>(res.data)
return data.map(([regionCode, regionName, schoolName, schoolCode]) => ({ return data.map(
code: schoolCode, ([regionCode, regionName, schoolName, schoolCode]) =>
name: schoolName, new School(this, {
region: { code: regionCode, name: regionName }, code: schoolCode,
})) name: schoolName,
region: { code: regionCode, name: regionName },
}),
)
} }
/** 학교 코드를 이용해 학교 시간표를 불러옵니다. */ private async getRawTimetable(
async getRawTimetable(schoolCode: number): Promise<Timetable[][][][]> { schoolCode: number,
const { mainRoute, timetableRoute, teacherCode, dayCode, subjectCode } = ): Promise<Timetable[][][][]> {
await this.dataManager.getData() const {
mainRoute,
timetableRoute,
teacherCode,
originalCode,
dayCode,
subjectCode,
} = await this.dataManager.getData()
const res = await this.rest.get( const res = await this.rest.get(
`${mainRoute}_T?${encodeBase64(`${timetableRoute}_${schoolCode}_0_1`)}`, `${mainRoute}_T?${encodeBase64(`${timetableRoute}_${schoolCode}_0_1`)}`,
) )
@ -64,8 +73,43 @@ export default class Comcigan {
) )
} }
/** 학교 코드를 이용해 학교 시간표를 불러오고, `TimetableManager`로 변환해 사용할 수 있는 형태로 제공합니다. */ async getTimetable(schoolCode: number): Promise<Timetable[][][][]>
async getTimetable(schoolCode: number) { async getTimetable(
return new TimetableManager(await this.getRawTimetable(schoolCode)) schoolCode: number,
grade: number,
): Promise<Timetable[][][]>
async getTimetable(
schoolCode: number,
grade: number,
cls: number,
): Promise<Timetable[][]>
async getTimetable(
schoolCode: number,
grade: number,
cls: number,
day: number,
): Promise<Timetable[]>
async getTimetable(
schoolCode: number,
grade: number,
cls: number,
day: number,
period: number,
): Promise<Timetable>
/** 학교 코드를 이용해 학교 시간표를 불러옵니다. */
async getTimetable(
schoolCode: number,
grade?: number,
cls?: number,
day?: number,
period?: number,
) {
const raw = await this.getRawTimetable(schoolCode)
if (grade === undefined) return raw
if (cls === undefined) return raw[grade - 1]
if (day === undefined) return raw[grade - 1][cls - 1]
if (period === undefined) return raw[grade - 1][cls - 1][day - 1]
return raw[grade - 1][cls - 1][day - 1][period - 1]
} }
} }

View file

@ -1,7 +1,9 @@
import Comcigan from './client' import Comcigan from './client'
import School from './models/School'
export default Comcigan export default Comcigan
export { School }
export * from './models/Region' export * from './models/Region'
export * from './models/School' export * from './models/School'
export * from './models/Timetable' export * from './models/Timetable'

9
src/models/Fetcher.ts Normal file
View file

@ -0,0 +1,9 @@
import type Comcigan from '../client'
export default class Fetcher {
protected client!: Comcigan
constructor(client: Comcigan) {
Object.defineProperty(this, 'client', { value: client, enumerable: false })
}
}

View file

@ -1,4 +1,4 @@
export interface Region { export default interface Region {
/** 지역 코드 // TODO: 지역 코드가 아닌 것으로 보임 */ /** 지역 코드 // TODO: 지역 코드가 아닌 것으로 보임 */
code: number code: number
/** 지역 이름 */ /** 지역 이름 */

View file

@ -1,6 +1,9 @@
import type { Region } from './Region' import Comcigan from '../client'
import Fetcher from './Fetcher'
import type Region from './Region'
import type Timetable from './Timetable'
export interface School { interface ISchool {
/** 학교 코드 */ /** 학교 코드 */
code: number code: number
/** 학교 이름 */ /** 학교 이름 */
@ -8,3 +11,54 @@ export interface School {
/** 학교 지역 */ /** 학교 지역 */
region: Region region: Region
} }
export default class School extends Fetcher implements ISchool {
code: number
name: string
region: Region
constructor(client: Comcigan, data: ISchool) {
super(client)
this.code = data.code
this.name = data.name
this.region = data.region
}
/** 이름으로 학교를 불러옵니다 */
static async fromName(name: string, client?: Comcigan) {
const cls = client ?? new Comcigan()
const res = await cls.searchSchools(name)
return res[0]
}
async getTimetable(): Promise<Timetable[][][][]>
async getTimetable(grade: number): Promise<Timetable[][][]>
async getTimetable(grade: number, cls: number): Promise<Timetable[][]>
async getTimetable(
grade: number,
cls: number,
day: number,
): Promise<Timetable[]>
async getTimetable(
grade: number,
cls: number,
day: number,
period: number,
): Promise<Timetable>
/** 시간표를 불러옵니다. */
async getTimetable(
grade?: number,
cls?: number,
day?: number,
period?: number,
) {
if (grade === undefined) return this.client.getTimetable(this.code)
if (cls === undefined) return this.client.getTimetable(this.code, grade)
if (day === undefined)
return this.client.getTimetable(this.code, grade, cls)
if (period === undefined)
return this.client.getTimetable(this.code, grade, cls, day)
return this.client.getTimetable(this.code, grade, cls, day, period)
}
}

View file

@ -1,30 +1,8 @@
export interface Timetable { export default interface Timetable {
/** 과목 */ /** 과목 */
subject: string subject: string
/** 교사 */ /** 교사 */
teacher: string teacher: string
} /** 변경 여부 */
changed: boolean
export class TimetableManager {
constructor(private readonly timetables: Timetable[][][][]) {}
/** 특정 학년의 시간표를 가져옵니다. */
getByGrade(grade: number) {
return this.timetables[grade - 1]
}
/** 특정 반의 시간표를 가져옵니다. */
getByClass(grade: number, cls: number) {
return this.timetables[grade - 1][cls - 1]
}
/** 특정 반의 특정 요일 시간표를 가져옵니다. */
getByDay(grade: number, cls: number, day: number) {
return this.timetables[grade - 1][cls - 1][day - 1]
}
/** 특정 반의 특정 요일의 특정 교시 시간표를 가져옵니다. */
getByPeriod(grade: number, cls: number, day: number, period: number) {
return this.timetables[grade - 1][cls - 1][day - 1][period - 1]
}
} }