kgtt-cliの開発ログ
CLIでそういう環境を整えるっていうのもいいかもな - 17:15
目標
p.icon - 14:30 テストを通す。; 14:21
p.icon-15:00 command.jsを使ってヘルプを出せるようにする。
到達点が曖昧だった。
p.icon- 15:30 全ての機能をasync fucntion化する。
p.icon 15:30 ヘルプを整備する。
p.icon - 15:55
15:30 実際に動くか確かめる。
履修登録してきた(16:50締切)
16:50
20:00 -
p.iconissue 教職他の学年・学科課程に対応できていない
教職他が入力された時とそうでない時で挙動を切り替えよう。
あれ...?切り替わらない...
と思ったけど単純にjsonの方向へ出力してないだけだった.
p.iconissue CSV出力で、列がおかしい。
JSONだとその限りでもない。
code:ts
この配列通りの出力順になってない。なんでだ
code:ts
let csv = Object.keys(講義項目群0).join(",") + "\n"; headersとは違うものをヘッダ行にしてたわ
16:33 -
p.iconissue 時間割行リストの値が設定されているはずのキーが存在していない
前処理が行われていないことが原因だった。
ただしく置換されるように、CRLF\r\nとLF\nを入力した。 文字列リテラルにCRLFとLFの混同問題がまぜこぜにならないように...。
p.iconissue学年・学科課程に中点の・がありません。:1年
「学年と学科課程」の欄に・がない行があった。
このような行を見つけてもエラーを出さず、学科課程を空白のままにするようにしよう。
p.iconissue Cannot read properties of undefined (reading 'indexOf')
また前処理が正しく行われていないのが原因
春学期を基準にヘッダー置換していたけど、これではだめだ。
先頭N行を置換みたいなやり方の方がいいかもしれない。
(.*\r\n){4}で置き換えるのはどうか...?
一番楽
ExcelのCSV出力の仕様が変わったら死にそう。
だめだった なんでだろう
\r\nが検出されてない...
(.*\n){6}がうまくいく。
ただし、ヘッダが今後変わったらその度に対処しなくちゃならない。
最短検索は*?、なるほど。
/"(.*?\n)*?.*?"/
いや、"以外の文字を全て通せばいいのだから
/"([^"]*\n)*[^"]*"/とすれば、""の内部の文字にヒットさせられる?
いや、もっと単純化できる。改行も中に入れられると考えれば...
/"([^"]|\n)*"/
いった。
おお〜〜
https://gyazo.com/c3c562aaf67cc40dfb503c8051c1c986
これを組み込めば...
/(("([^"]|\n)*"|[."]*)\n){4}/
これで、CSV上で先頭4行を捉えることができるぞ!
だめでした。
これってChatGPTに頼んだら書いてくれるか?
^(?:(?:"(?:[^"\n\r]|""|\\\n)*"\n)|(?:[^\n\r]*\n)){3}
任意の3行マッチ
これ?:を取り除いたらうまくうごく?
^(("([^"\n\r]|""|\n)*"\n)|([^\n\r]*\n)){3}
^((("[^"]*")?[^",\n]*)+,?\n){0,3}((("[^"]*")?[^",\n]*)+,?\n)?
((("^"*")?^",\n*)+,?\n): CSVファイルの1行にマッチします。このグループには、カンマで区切られた値、またはダブルクォーテーションで囲まれた値が含まれます。ダブルクォーテーションで囲まれた値には、改行文字が含まれることができます。 ((("^"*")?^",\n*)+,?\n){0,3}: 最初の3行にマッチするように、1行を最大3回繰り返します。 ((("^"*")?^",\n*)+,?\n)?: 4番目の行にマッチするように、1行を0回または1回繰り返します。 ^: 文字列の先頭にマッチします。
難読化待ったなし!!正規表現でやるのやめた
先頭から一文字づつ読んでいくか。
15:12 -
全ての機能を関数にした。
リソース読み込みなどの機能も極力index側に分離。
処理本体の依存モジュールが減った。
よし、とりあえず仕様は全部書いたぞ...。
ただ、系列検索時にデータベースファイルとしてJSONしか受け付けないのは不便だ。
CSVでもJSONでも読めるようにしておくか。
や、ちょっとめんどくさい
やめた。
14:28 - 15:12
npm install commander
なんともまあ雰囲気でわかりやすい...。
よし、とりあえずざっくりとした使い方は掴めた。
コードがわかりやすい!
おぉ...ちゃんとヘルプが表示されている。
とりあえず暫定的にタイトルはkgtt(KwaseiGakuin -- TimeTable)で...
...なんかもっといい名前ないか。
略字に母音を加えたくないか...?
- 14:21
学年と学科課程に複数の・が含まれていた場合に、正しく学年と学科課程へ分割されない問題を修正
単純にsplitしていたが、そうすると学科課程の区切りで変に分割される。
VとⅤは違う文字....??
https://gyazo.com/eb75aedade2737f7ab84c2905bb9568e
ターミナル上だと明らかにわかるんだけど、エディタ上だと表示に差がなさすぎる
https://gyazo.com/aec4aa2840805f3ae0e72dc445b226c6
()と()も違う文字だったりします...?
流石にそんなことはなかった。
単純に全角数字が変換されてなかっただけ。
でも全角()よりも半角()の方が慣れてるからな....
よし!半角に変換しておこう。(あとで恨まれそう)
これのせいで通ってなかった。
いよし!
https://gyazo.com/9039e4625de9e4ad89a4c2fccc2f81d8
学んだ
解決
サンドボックス作って実験すると解決が早まるな...。
21:00 -
問題解決
To enable this you don’t need to do anything special. Write your test file as an ES module. In Node.js this means either ending the file with a .mjs extension, or, if you want to use the regular .js extension, by adding "type": "module" to your package.json. More information can be found in the Node.js documentation.
現状
esm形式に則って書くと全てts-node上では正しく実行される。
esm形式に則って書くと全てts-mocha上ではエラーが出る。
❯ npx mocha -r ts-node/register src/**.test.ts
❯ npx ts-node src/**.test.ts
ReferenceError: describe is not defined
うーん
整理
❯ npx ts-node src/parseTimeTable.ts \n Error: Cannot find module './sorting.js'
neat-csvを使うのにESMは必要 (types:"module"で、index.jsがindex.mjsとみなされる)
全てのファイル形式をESM形式にしなければならない
---> あるいはdynamic importを使うか
❯ npx ts-node src/parseTimeTable.ts TypeError \n [ERR_UNKNOWN_FILE_EXTENSION]: Unknown file extension ".ts" for /Users/AppleBird/Downloads/timetable/src/parseTimeTable.ts
これnodeに直接tsファイルが渡されてる...!?
nodeはjsしか読めないから、確かにtsがわけわからんと言ってもおかしくはない
19:02 - 20:16
これまでに作った機能はちゃんと動くのか?テストする。
ちょっと外部環境(ファイルなど)が影響しないように分離。
文字列からの入力として純粋にテストできるように修正。
「時間割の記述されたcsv文字列をパースする」の参照透過性を確保。 「時間割CSVのパース」に名前変更
p.iconテストを書く。
春期と秋期に対してそれぞれ2行程度を抽出。
それらに対して期待する出力を書く。
あかん、思ったよりめんどくさい
できた!でも合ってるかな...。
テストを通す。
Stucked: TypeError: Unknown file extension ".ts"とは
症状
npx ts-mocha -p tsconfig.json src/**.test.tsを実行する。
parse_timetable.test.tsのテストでそのエラーが出る。
preprocess.test.tsのテストではエラーが出ない
--esmオプションをつける...。
前に通したファイルではしっかり実行されている。
[]
句読点「。」って関数名変数名では無効な文字なのか....。
15:47 - 16:57
一瞬開発ログでページ分離してたけどやめた
前処理を挟む
いちいち一時ファイルを作る必要があるのかな...?
APIを覗き見てる限りこれ以外の手段はなさそう...?
ただし、csv-parserのAPIの様子と、これがwrapperであることを考慮すると、一度データの内容を書き込んでるんかな...?
コードをみないとわからんね。
cat 2023spring_test.csv | npx csv-parser
秋学期の時間も読み込ませて、タームに対応させる。
TimeTableRowからの講義基本情報の抽出に、タームの情報も渡す。
やった。
行内改行は\r\nに置き換えられる。
15:27 - 15:46
通した。
https://gyazo.com/16aa31b5494b2544e4c84e479e154f5d
15:22 - 15:27
多分必要なさそう。
CSVの書式の中に、セル内改行のルールが含まれている。
もっとも、標準ではなさそうだが。
p.icon 必要な前処理
p.icon これらをバッチ処理にできないだろうか...?appbird.icon 日本語(Windows, DOS) --> utf-8へ変換 どうやらExcelでcsvによって保存すると
csvとしての改行はCRLFで表されるらしい。
適宜LFの改行を消す必要がある。
時間割のタイトル行にあたる。
3行目を削除する。
この表は3行目と4行目にヘッダが分布している。
しかし、解析に3行目はあまり必要ないので解析から飛ばす。
4行目のヘッダ名が一意になるように修正する。
code:line4.csv
,,授業コード,講義名,担当者名,,,授業コード,講義名,担当者名,,授業コード,講義名,担当者名,,授業コード,講義名,担当者名,,授業コード,講義名,担当者名,
しかし、4行目には同一ヘッダ名が含まれる。
それでは困るので、それぞれに時限の情報を付記していく。 このままではデータを解析する際に面倒臭い。
適当にヘッダ名を補っておく。
要するに、4行目は以下の通り置き換えられたらいい
code:csv
曜日,学年・学科課程,1授業コード,1十字,1講義名,1担当者名,1教室,,2授業コード,2十字,2講義名,2担当者名,2教室,3授業コード,3十字,3講義名,3担当者名,3教室,4授業コード,4十字,4講義名,4担当者名,4教室,5授業コード,5十字,5講義名,5担当者名,5教室
p.iconというわけで、JSONとCSVに変換してみる。
次の形式に変換する。
code:typescript
{
"学年": string,
"学科課程": string,
"曜日": string,
"時限": string,
"授業コード": string,
"十字": string,
"講義名": string,
"担当者名": string,
"教室": string
}[]
できた。
p.iconサンプル通りに実行してみる。
実行形態
tsc && node index.js timetable.csv
型ObjectTypeはキーが文字列、値が文字列であるようなオブジェクトである。 code:ts
import csv from "csv-parser";
import {createReadStream} from "fs";
import { argv } from "process";
const result:ObjectType[] = [];
console.log(param)
createReadStream(param)
.pipe(csv())
.on('data', (data:ObjectType) => result.push(data))
.on('end', () => console.log(result));
以下のような配列型に沿ったデータを得ることができる。 tsc && node index.js timetable.csv > out.txt
実際の中身は伏せる。
code:ts
{
'曜日': string,
'学年・学科課程': string,
'1授業コード': string,'1十字': string,'1講義名': string,'1担当者名': string,'1教室': string,
'': string,
'2授業コード': string,'2十字': string,'2講義名': string,'2担当者名': string,'2教室': string,
'3授業コード': string,'3十字': string,'3講義名': string,'3担当者名': string,'3教室': string,
'4授業コード': string,'4十字': string,'4講義名': string,'4担当者名': string,'4教室': string,
'5授業コード': string,'5十字': string,'5講義名': string,'5担当者名': string,'5教室': string
}[]