1
1
import { Lecture , Day , Module } from './types'
2
2
import * as parseCsv from 'csv-parse/lib/sync'
3
3
import * as _cliProgress from 'cli-progress'
4
+ import { read as readXLSX , utils } from 'xlsx'
4
5
5
6
/**
6
7
* '月1,2' 等の曜日と時限の文字列を解析し、分解する
@@ -10,7 +11,7 @@ import * as _cliProgress from 'cli-progress'
10
11
const analyzeDayAndPeriod = ( str : string ) : { day : Day ; period : number } [ ] => {
11
12
const result : { day : Day ; period : number } [ ] = [ ]
12
13
//全ての曜日に対して
13
- Object . entries ( Day ) . forEach ( k => {
14
+ Object . entries ( Day ) . forEach ( ( k ) => {
14
15
const day = k [ 1 ] as Day //月, 火 , .... , 日 のどれか
15
16
// 1から6限について
16
17
for ( let i = 1 ; i <= 6 ; i ++ ) {
@@ -23,18 +24,18 @@ const analyzeDayAndPeriod = (str: string): { day: Day; period: number }[] => {
23
24
if ( new RegExp ( `${ day } .*${ i } ` ) . test ( str ) ) {
24
25
result . push ( {
25
26
day : day ,
26
- period : i
27
+ period : i ,
27
28
} )
28
29
}
29
30
}
30
31
// 月1-4 のようなハイフン表記のテスト
31
32
const longTermTest = new RegExp ( `([${ day } ]).*(\\d)-(\\d)` ) . exec ( str )
32
33
if ( longTermTest ) {
33
34
for ( let i = Number ( longTermTest [ 2 ] ) ; i <= Number ( longTermTest [ 3 ] ) ; i ++ ) {
34
- if ( ! result . find ( el => el . day === day && el . period === i ) )
35
+ if ( ! result . find ( ( el ) => el . day === day && el . period === i ) )
35
36
result . push ( {
36
37
day : day ,
37
- period : i
38
+ period : i ,
38
39
} )
39
40
}
40
41
}
@@ -43,7 +44,7 @@ const analyzeDayAndPeriod = (str: string): { day: Day; period: number }[] => {
43
44
if ( / 集 中 / gm. test ( str ) )
44
45
result . push ( {
45
46
day : Day . Intensive ,
46
- period : 0
47
+ period : 0 ,
47
48
} )
48
49
49
50
//どのテストにも合格しなかったが空文字でなければ仮にunknownとする
@@ -61,7 +62,6 @@ const analyzeDayAndPeriod = (str: string): { day: Day; period: number }[] => {
61
62
const analyzeModule = ( str : string ) : Module [ ] => {
62
63
const result : Module [ ] = [ ]
63
64
64
-
65
65
/*
66
66
/春[ABC]*A/は春A 春AB 春ABCに
67
67
/春[ABC]*B/は春B 春AB 春BCに
@@ -70,14 +70,14 @@ const analyzeModule = (str: string): Module[] => {
70
70
if ( / 春 [ A B C ] * A / gm. test ( str ) ) result . push ( Module . SpringA )
71
71
if ( / 春 [ A B C ] * B / gm. test ( str ) ) result . push ( Module . SpringB )
72
72
if ( / 春 [ A B C ] * C / gm. test ( str ) ) result . push ( Module . SpringC )
73
-
73
+
74
74
// 夏季休業中、通年のマッチング
75
75
if ( str . includes ( Module . SummerVacation ) ) result . push ( Module . SummerVacation )
76
76
77
77
if ( / 秋 [ A B C ] * A / gm. test ( str ) ) result . push ( Module . FallA )
78
78
if ( / 秋 [ A B C ] * B / gm. test ( str ) ) result . push ( Module . FallB )
79
79
if ( / 秋 [ A B C ] * C / gm. test ( str ) ) result . push ( Module . FallC )
80
-
80
+
81
81
// 春季休業中のマッチング
82
82
if ( str . includes ( Module . SpringVacation ) ) result . push ( Module . SpringVacation )
83
83
@@ -104,78 +104,86 @@ const analyzeYear = (str: string): number[] => {
104
104
res . push ( i )
105
105
}
106
106
} else if ( / ・ / . test ( str ) ) {
107
- res . push ( ...str . split ( '・' ) . map ( e => Number ( e ) ) )
107
+ res . push ( ...str . split ( '・' ) . map ( ( e ) => Number ( e ) ) )
108
108
}
109
109
return res
110
110
}
111
111
112
- /**
113
- * CSVをパースする
114
- * @param csv KDBからダウンロードしたcsv文字列
115
- */
116
- export default ( csv : string ) : Lecture [ ] => {
117
- //コンソールの進捗バー
118
- const bar = new _cliProgress . Bar ( { } , _cliProgress . Presets . shades_classic )
119
-
120
- const rows = parseCsv ( csv )
121
-
122
- ////// コンソール表示
123
- console . log ( '● Parsing' . green . bold )
124
- bar . start ( rows . length , 0 )
125
- let done = 0
126
- //////
127
-
128
- const classes = rows . map ( columns => {
129
- const classData : Lecture = {
130
- lectureCode : columns [ 0 ] ,
131
- name : columns [ 1 ] ,
132
- credits : Number ( columns [ 3 ] ) ,
133
- type : Number ( columns [ 2 ] ) ,
134
- overview : columns [ 9 ] ,
135
- remarks : columns [ 10 ] ,
136
- year : analyzeYear ( columns [ 4 ] ) ,
137
- details : [ ] ,
138
- instructor : columns [ 8 ]
139
- }
140
-
141
- const moduleString = columns [ 5 ]
142
- const periodString = columns [ 6 ]
143
- const roomString = columns [ 7 ]
144
-
145
- // 空文字は省く
146
- const moduleArray = moduleString . split ( '\n' )
147
- const periodArray = periodString . split ( '\n' )
148
- const roomArray = roomString . split ( '\n' )
112
+ const analyzeRow = ( columns : string [ ] ) => {
113
+ const classData : Lecture = {
114
+ lectureCode : columns [ 0 ] ,
115
+ name : columns [ 1 ] ,
116
+ credits : Number ( columns [ 3 ] ) ,
117
+ type : Number ( columns [ 2 ] ) ,
118
+ overview : columns [ 9 ] ,
119
+ remarks : columns [ 10 ] ,
120
+ year : analyzeYear ( columns [ 4 ] ) ,
121
+ details : [ ] ,
122
+ instructor : columns [ 8 ] ,
123
+ }
149
124
150
- const count = Math . max (
151
- moduleArray . length ,
152
- Math . max ( periodArray . length , roomArray . length )
125
+ const moduleString = columns [ 5 ]
126
+ const periodString = columns [ 6 ]
127
+ const roomString = columns [ 7 ]
128
+
129
+ // 空文字は省く
130
+ const moduleArray = moduleString . split ( '\r\n' )
131
+ const periodArray = periodString . split ( '\r\n' )
132
+ const roomArray = roomString . split ( '\r\n' )
133
+
134
+ const count = Math . max (
135
+ moduleArray . length ,
136
+ Math . max ( periodArray . length , roomArray . length )
137
+ )
138
+
139
+ if (
140
+ ! (
141
+ ( moduleArray . length === count || moduleArray . length === 1 ) &&
142
+ ( periodArray . length === count || periodArray . length === 1 ) &&
143
+ ( roomArray . length === count || roomArray . length === 1 )
153
144
)
145
+ )
146
+ console . log ( 'Warning!' )
154
147
155
- for ( let i = 0 ; i < count ; i ++ ) {
156
- const modules = analyzeModule (
157
- moduleArray . length === 1 ? moduleArray [ 0 ] : moduleArray [ i ]
158
- )
159
- const when = analyzeDayAndPeriod (
160
- periodArray . length === 1 ? periodArray [ 0 ] : periodArray [ i ]
161
- )
162
- modules . forEach ( mod =>
163
- when . forEach ( w =>
164
- classData . details . push ( {
165
- module : mod ,
166
- period : w . period ,
167
- day : w . day ,
168
- room : roomArray . length === 1 ? roomArray [ 0 ] : roomArray [ i ]
169
- } )
170
- )
148
+ for ( let i = 0 ; i < count ; i ++ ) {
149
+ const modules = analyzeModule (
150
+ moduleArray . length === 1 ? moduleArray [ 0 ] : moduleArray [ i ] || ''
151
+ )
152
+ const when = analyzeDayAndPeriod (
153
+ periodArray . length === 1 ? periodArray [ 0 ] : periodArray [ i ] || ''
154
+ )
155
+ modules . forEach ( ( mod ) =>
156
+ when . forEach ( ( w ) =>
157
+ classData . details . push ( {
158
+ module : mod ,
159
+ period : w . period ,
160
+ day : w . day ,
161
+ room : roomArray . length === 1 ? roomArray [ 0 ] : roomArray [ i ] || '' ,
162
+ } )
171
163
)
172
- }
173
- done ++
174
- bar . update ( done )
175
- return classData
176
- } )
164
+ )
165
+ }
166
+ return classData
167
+ }
177
168
178
- bar . stop ( )
179
- console . log ( '✔ Done' . green . bold )
169
+ /**
170
+ * CSVをパースする
171
+ * @param csv KDBからダウンロードしたcsv文字列
172
+ */
173
+ export default ( data : Buffer ) : Lecture [ ] => {
174
+ const sheet = readXLSX ( data ) . Sheets [ '開設科目一覧' ]
175
+
176
+ const classes : Lecture [ ] = [ ]
177
+
178
+ console . log ( '● Parsing' )
179
+ for ( let r = 5 ; ; r ++ ) {
180
+ const columns : string [ ] = [ ]
181
+ for ( let c = 0 ; c < 16 ; c ++ )
182
+ columns . push ( sheet [ utils . encode_cell ( { r, c } ) ] . v )
183
+ if ( columns [ 0 ] === '' ) break
184
+ // console.log(r)
185
+ classes . push ( analyzeRow ( columns ) )
186
+ }
187
+ console . log ( '✔ Done' )
180
188
return classes
181
189
}
0 commit comments