1
+ import * as fs from 'fs' ;
2
+ import { writeFileSync } from 'fs' ;
3
+ import { sort } from "fast-sort" ;
4
+
5
+ let work = [ '2024_4' , '2025_1' ]
6
+
7
+ if ( true ) {
8
+ work = [ ]
9
+ for ( let year = 2012 ; year <= 2024 ; year ++ ) {
10
+ for ( let term = 1 ; term <= 4 ; term ++ ) {
11
+ work . push ( `${ year } _${ term } ` )
12
+ }
13
+ }
14
+ }
15
+
16
+ function parseTime ( times ) {
17
+ return ( times || '' ) . split ( '\n' ) . map ( s => {
18
+ s = s . trim ( ) ;
19
+ if ( ! s ) return null ;
20
+ try {
21
+ let date = [ 'Mon' , 'Tue' , 'Wed' , 'Thu' , 'Fri' , 'Sat' , 'Sun' ] . indexOf ( s . slice ( 0 , 3 ) ) ;
22
+ if ( date === - 1 ) date = [ '월' , '화' , '수' , '목' , '금' , '토' , '일' ] . indexOf ( s . slice ( 0 , 1 ) )
23
+ const sh = s && + s . split ( ' ' ) [ 1 ] . split ( ':' ) [ 0 ] ;
24
+ const sm = s && + s . split ( ' ' ) [ 1 ] . split ( ':' ) [ 1 ] . split ( '~' ) [ 0 ] ;
25
+ const eh = s && + s . split ( ' ' ) [ 1 ] . split ( ':' ) [ 1 ] . split ( '~' ) [ 1 ] . split ( ':' ) [ 0 ] ;
26
+ const em = s && + s . split ( ' ' ) [ 1 ] . split ( ':' ) [ 2 ] ;
27
+ return { date, sh, sm, eh, em}
28
+ } catch ( e ) {
29
+ return null ;
30
+ }
31
+ } ) . filter ( x => x )
32
+ }
33
+
34
+ async function main ( year = 2024 , term = 4 , file = `static/result_${ year } _${ term } .json` ) {
35
+ const raw = Object . values ( await fetch ( 'https://erp.kaist.ac.kr/sch/sles/SlesseCtr/findAllEstblSubjtList.do' , {
36
+ body : `_menuId=MTI0ODU1MjEwNTgwMTA3ODAwMDA%3D&_menuNm=%EC%A0%84%EC%B2%B4%EA%B0%9C%EC%84%A4%EA%B5%90%EA%B3%BC%EB%AA%A9%EC%A1%B0%ED%9A%8C&_pgmId=NzU0MzkyMTUwMjY%3D&%40d1%23syy=${ year } &%40d1%23smtDivCd=${ term } &%40d1%23deptCd=806&%40d1%23lwprtInclsYn=1&%40d1%23subjtCrseDivCd=&%40d1%23subjcDivCd=%2C13%2C32%2C12%2C75%2C30%2C31%2C76%2C73%2C74%2C10%2C70%2C71%2C11%2C77%2C34%2C72%2C35%2C36%2C37%2C38%2C39%2C40%2C41%2C42%2C43%2C33%2C78%2C96%2C95%2C93%2C94%2C92%2C90%2C91%2CZM%2CZN%2CZQ%2CZR%2CZW%2CZJ%2CZV%2CZZ%2CZL%2CZS%2CZY%2CZX%2CZO%2CZP%2CZT%2CZU%2CZK&%40d1%23subjtNm=&%40d1%23fromCdt=&%40d1%23toCdt=&%40d1%23englSubjtYn=&%40d1%23subjtCd=&%40d1%23chrgNm=&%40d1%23fromAtnlcPercpCnt=&%40d1%23toAtnlcPercpCnt=&%40d%23=%40d1%23&%40d1%23=dmCond&%40d1%23tp=dm&` ,
37
+ method : 'POST' ,
38
+ headers : {
39
+ 'Content-Type' : 'application/x-www-form-urlencoded; charset=UTF-8'
40
+ }
41
+ } ) . then ( r => r . json ( ) ) ) [ 0 ]
42
+
43
+ console . log ( raw )
44
+
45
+ const data = raw . map ( r => {
46
+ const dept = + r . deprtCd
47
+ const type = r . subjcDivNm
48
+ const code = r . subjtCd
49
+ const old = r . subjtNo
50
+ const title = r . subjtNm
51
+ const group = ( r . corseDvclsNo || '' ) . trim ( ) || null
52
+ const prof = ( r . chrgInstrNmLisup || '' ) . split ( ',' ) . map ( p => p . trim ( ) )
53
+ const where = r . lecrmNm
54
+ const credit = r . cdt
55
+ const kcode = r . osysCmptCd
56
+ const au = r . actvtUnitHrs || 0
57
+ const cap = r . atnlcPercpCnt || 0
58
+ const reg = r . atnlcPcnt || 0
59
+ const time = parseTime ( r . lctreTm )
60
+ const exam = parseTime ( r . examTm )
61
+
62
+ return { dept, type, code, old, title, group, prof, where, time, exam, credit, kcode, au, cap, reg}
63
+ } ) . filter ( x => x )
64
+
65
+ try {
66
+ const addl = `./static/add_${ year } _${ term } .json`
67
+ const add = fs . readFileSync ( addl )
68
+ const addJson = JSON . parse ( add )
69
+ data . push ( ...addJson )
70
+ } catch ( e ) {
71
+ }
72
+
73
+ const deptMap = { "833" : "수리과학과" } ;
74
+ raw . forEach ( r => deptMap [ r . deprtCd ] = r . deprtNm )
75
+
76
+ const res = {
77
+ data, version : Date . now ( ) , deptMap,
78
+ }
79
+
80
+ writeFileSync ( file , JSON . stringify ( res ) )
81
+ }
82
+
83
+ function other ( ) {
84
+ const fileNames = fs . readdirSync ( 'static' )
85
+ const files = fileNames . filter ( name => name . startsWith ( 'result_' ) ) . map ( name => {
86
+ const li = name . split ( '_' )
87
+ return { year : + li [ 1 ] , term : + li [ 2 ] . split ( '.' ) [ 0 ] , name}
88
+ } )
89
+ const subjects = { } , titles = { }
90
+ files . forEach ( ( { year, term, name} ) => {
91
+ const data = fs . readFileSync ( `static/${ name } ` )
92
+ const json = JSON . parse ( data )
93
+ json . data . forEach ( subject => {
94
+ if ( subject . code . includes ( 'URP' ) ) return
95
+ if ( ! subjects [ subject . code ] ) {
96
+ subjects [ subject . code ] = [ '' , { } ]
97
+ titles [ subject . code ] = [ ]
98
+ }
99
+ titles [ subject . code ] . push ( subject . title )
100
+
101
+ const key = ( ( year - 2000 ) * 10 + term ) + ''
102
+ if ( ! subjects [ subject . code ] [ 1 ] [ key ] ) subjects [ subject . code ] [ 1 ] [ key ] = [ ]
103
+ subjects [ subject . code ] [ 1 ] [ key ] . push ( [ subject . group , subject . prof . length === 1 ? subject . prof [ 0 ] : subject . prof , subject . title ] )
104
+ } )
105
+ } )
106
+
107
+ const ignoreSets = [ '졸업연구' , '개별연구' , 'URP' , '논문연구' ] ;
108
+ for ( const code in subjects ) {
109
+ const titleCnt = titles [ code ] . reduce ( ( obj , item ) => {
110
+ obj [ item ] = ( obj [ item ] || 0 ) + 1
111
+ return obj
112
+ } , { } )
113
+
114
+ const title = Object . keys ( titleCnt ) . sort ( ( a , b ) => titleCnt [ b ] - titleCnt [ a ] ) [ 0 ]
115
+ if ( ignoreSets . some ( ignore => title . includes ( ignore ) ) ) {
116
+ delete subjects [ code ]
117
+ continue
118
+ }
119
+ subjects [ code ] [ 0 ] = title
120
+
121
+ const li = [ ]
122
+ for ( const key in subjects [ code ] [ 1 ] ) {
123
+ for ( const s of subjects [ code ] [ 1 ] [ key ] ) {
124
+ if ( s [ 2 ] === title ) s . pop ( )
125
+ }
126
+ li . push ( [ + key , subjects [ code ] [ 1 ] [ key ] ] )
127
+ }
128
+ subjects [ code ] [ 1 ] = sort ( li ) . desc ( [ '0' ] )
129
+ }
130
+ writeFileSync ( 'static/other.json' , JSON . stringify ( subjects ) )
131
+ }
132
+
133
+ Promise . all ( work . map ( w => {
134
+ const li = w . split ( '_' )
135
+ return main ( + li [ 0 ] , + li [ 1 ] , `static/result_${ w } .json` )
136
+ } ) ) . then ( ( ) => {
137
+ other ( )
138
+ console . log ( 'done' )
139
+ } )
0 commit comments