modules_academic_yy-smr-wrapper.ts
/**
* 학기 코드와 명칭을 정의하는 인터페이스
*/
export interface SmrConfig {
cd: string;
nm: string;
order: number;
}
export const DEFAULT_SMR_CONFIGS: SmrConfig[] = [
{ cd: "10540010", nm: "1학기", order: 1 },
{ cd: "10540011", nm: "여름학기", order: 2 },
{ cd: "10540020", nm: "2학기", order: 3 },
{ cd: "10540021", nm: "겨울학기", order: 4 },
];
/**
* 연도와 학기를 연산하고 관리하기 위한 래퍼 클래스
*
* @access private
*/
export class YySmr {
private _yy: number;
private _smr: string;
private _configs: SmrConfig[];
/**
* @param yy 연도 (숫자 또는 숫자형 문자열)
* @param smr 학기 코드
* @param configs 커스텀 학기 설정 (선택 사항)
*/
constructor(
yy: number | string,
smr: string,
configs: SmrConfig[] = DEFAULT_SMR_CONFIGS,
) {
this._yy = typeof yy === "string" ? parseInt(yy, 10) : yy;
this._smr = smr;
this._configs = [...configs].sort((a, b) => a.order - b.order);
if (isNaN(this._yy)) {
throw new Error(`Invalid year: ${yy}`);
}
}
get yy(): number {
return this._yy;
}
get smr(): string {
return this._smr;
}
get smrNm(): string {
const config = this._configs.find((c) => c.cd === this._smr);
return config ? config.nm : "";
}
/**
* 다음 학기를 반환합니다.
*
* @returns {YySmr}
*/
next(): YySmr {
const currentIndex = this._configs.findIndex((c) => c.cd === this._smr);
if (currentIndex === -1) {
throw new Error(
`Cannot calculate next semester: Current semester code ${this._smr} is not in configs.`,
);
}
if (currentIndex === this._configs.length - 1) {
// 마지막 학기인 경우 다음 연도의 첫 학기로
return new YySmr(this._yy + 1, this._configs[0].cd, this._configs);
} else {
return new YySmr(
this._yy,
this._configs[currentIndex + 1].cd,
this._configs,
);
}
}
/**
* 이전 학기를 반환합니다.
*
* @returns {YySmr}
*/
prev(): YySmr {
const currentIndex = this._configs.findIndex((c) => c.cd === this._smr);
if (currentIndex === -1) {
throw new Error(
`Cannot calculate previous semester: Current semester code ${this._smr} is not in configs.`,
);
}
if (currentIndex === 0) {
// 첫 학기인 경우 이전 연도의 마지막 학기로
return new YySmr(
this._yy - 1,
this._configs[this._configs.length - 1].cd,
this._configs,
);
} else {
return new YySmr(
this._yy,
this._configs[currentIndex - 1].cd,
this._configs,
);
}
}
/**
* 특정 학기만큼 이동한 결과를 반환합니다.
*
* @param offset 양수면 미래, 음수면 과거
*/
add(offset: number): YySmr {
let result: YySmr = new YySmr(this._yy, this._smr, this._configs);
if (offset > 0) {
for (let i = 0; i < offset; i++) {
result = result.next();
}
} else if (offset < 0) {
for (let i = 0; i > offset; i--) {
result = result.prev();
}
}
return result;
}
/**
* 연도와 학기를 문자열로 반환합니다.
*
* @param separator 구분자 (기본값: '-')
*/
toString(separator: string = "-"): string {
return `${this._yy}${separator}${this._smr}`;
}
/**
* 다른 YySmr 객체와 비교합니다.
*
* @param other
* @returns {number} 0 이면 같음, 1 이면 본인이 큼, -1 이면 작음
*/
compare(other: YySmr): number {
if (this._yy !== other._yy) {
return this._yy > other._yy ? 1 : -1;
}
const thisIdx = this._configs.findIndex((c) => c.cd === this._smr);
const otherIdx = this._configs.findIndex((c) => c.cd === other._smr);
if (thisIdx === otherIdx) return 0;
return thisIdx > otherIdx ? 1 : -1;
}
}