TWINSの科目検索ページにはKdBよりもパースしやすいデータがあります。 このプログラムではダウンロードした科目データを使いやすくパースしています。
このコードは2025年11月のKdBアップデートに対応しています。
実際のデータには以下に加えて差分のデータも含まれます。
type Terms = { text: "春学期"; code: "A" } | { text: "秋学期"; code: "B" };
type DaysOfWeek = "月" | "火" | "水" | "木" | "金" | "土" | "日" | "他";
type Periods = 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8;
type TimeTable = {
day: DaysOfWeek; // 曜日
period: Periods | null; // 時限
} | null;
type Module = "springA" | "springB" | "springC" | "summerVacation" | "fallA" | "fallB" | "fallC" | "springVacation";
type ModuleTimeTable = Record<Module, TimeTable[]>;
type TwinsSubject = {
name: string; // 科目名
code: string; // 科目番号
term: Terms;
moduleTimeTable: ModuleTimeTable;
instructors: string[]; // 担当教員
affiliation: {
name: string; // 開設所属名
code: string; // 開設所属コード
};
year: number[]; // 標準履修年次
raw: [term: string, module: string, code: string, title: { text: string; onclick: string }, instructor: string, affiliation: string, year: string];
};
type Requisite = {
id: string;
name: string;
hasLower: boolean;
} | null;
type InstructionalType =
| { text: "その他"; flags: { 講義: false; 演習: false; "実習・実験・実技": false; "卒業論文・卒業研究等": false; その他: true } }
| { text: "講義"; flags: { 講義: true; 演習: false; "実習・実験・実技": false; "卒業論文・卒業研究等": false; その他: false } }
| { text: "演習"; flags: { 講義: false; 演習: true; "実習・実験・実技": false; "卒業論文・卒業研究等": false; その他: false } }
| { text: "実習・実験・実技"; flags: { 講義: false; 演習: false; "実習・実験・実技": true; "卒業論文・卒業研究等": false; その他: false } }
| { text: "講義及び演習"; flags: { 講義: true; 演習: true; "実習・実験・実技": false; "卒業論文・卒業研究等": false; その他: false } }
| { text: "講義及び実習・実験・実技"; flags: { 講義: true; 演習: false; "実習・実験・実技": true; "卒業論文・卒業研究等": false; その他: false } }
| { text: "演習及び実習・実験・実技"; flags: { 講義: false; 演習: true; "実習・実験・実技": true; "卒業論文・卒業研究等": false; その他: false } }
| { text: "講義、演習及び実習・実験・実技"; flags: { 講義: true; 演習: true; "実習・実験・実技": true; "卒業論文・卒業研究等": false; その他: false } }
| { text: "卒業論文・卒業研究等"; flags: { 講義: false; 演習: false; "実習・実験・実技": false; "卒業論文・卒業研究等": true; その他: false } };
type KdbSubjectRecord = {
courseCode: string; // 科目番号
courseName: string; // 科目名
syllabusLatestLink: null; // シラバス最新リンク
courseType: InstructionalType & {
code: string;
}; // 授業方法
credits: {
text: string;
value: | {
readonly type: "normal";
readonly value: number;
}
| {
readonly type: "none";
}
| {
readonly type: "unknown";
};
}; // 単位数
year: {
text: string;
value:
| {
readonly type: "normal";
readonly value: readonly number[];
}
| {
readonly type: "unknown";
};
}; // 標準履修年次
term: string; // 実施学期
weekdayAndPeriod: string; // 曜時限
classroom: null; // 教室
instructor: string; // 担当教員
overview: string; // 授業概要
remarks: string; // 備考
auditor: string; // 科目等履修生申請可否
conditionsForAuditors: string; // 申請条件
exchangeStudent: string; // 短期留学生申請可否
conditionsForExchangeStudents: string; // 申請条件
JaEnCourseName: string; // 英語(日本語)科目名
parentNumber: string; // 科目コード
parentCourseName: string; // 要件科目名
dataUpdateDate: string; // データ更新日
};
type KdbSubjectRecordWithRequisite = KdbSubjectRecord & { requisite: Requisite[] };
type MergedSubject = {
code: string; // 科目番号
name: string; // 科目名
syllabusLatestLink: string | null; // シラバス最新リンク
instructionalType: {
value: InstructionalType | null;
kdbRaw: string | null;
}; // 授業方法
credits: {
value:
| {
type: "normal";
value: number;
}
| {
type: "none";
}
| {
type: "unknown";
}
| null;
kdbRaw: string | null;
}; // 単位数
year: {
value:
| {
type: "normal";
value: readonly number[];
}
| {
type: "unknown";
};
kdbRaw: string | null;
twinsRaw: string | null;
}; // 標準履修年次
terms: {
term: Terms | null; // 学期
module: string | null; // 実施学期
weekdayAndPeriod: string | null; // 曜時限
moduleTimeTable: ModuleTimeTable | null; // モジュール時間割
twinsRaw: {
term: string;
module: string;
} | null;
};
classroom: null; // 教室
instructor: {
value: string[];
kdbRaw: string | null;
twinsRaw: string | null;
}; // 担当教員
overview: string | null; // 授業概要
remarks: string | null; // 備考
auditor: string | null; // 科目等履修生申請可否
conditionsForAuditors: string | null; // 申請条件
exchangeStudent: string ?? null,
conditionsForExchangeStudents: string ?? null, // 申請条件
JaEnCourseName: string ?? null, // 英語(日本語)科目名
parentNumber: string ?? null, // 科目コード
parentCourseName: string ?? null, // 要件科目名
affiliation: {
name: string | null;
code: string | null;
twinsRaw: {
name: string;
code: string;
} | null;
};
requisite: Requisite[];
};
type SubjectNode = {
type: "subject";
node: Requisite;
subject: KdbSubjectRecord;
children: null;
};
type TreeNode =
| {
type: "internal";
node: Requisite;
children: TreeNode[];
}
| {
type: "leaf";
node: Requisite;
children: SubjectNode[];
};全てを合わせたデータ
型: MergedSubject[]
全てを合わせたデータを科目番号をキーとしたマップの形式にしたもの
型: { [k: string]: MergedSubject; }
KdBから取得した木構造のデータ
型: TreeNode
KdBから取得した木構造のデータをフラットにしたもの
型: KdbSubjectRecordWithRequisite[]
KdBから取得した木構造のデータをフラットにしたものを科目番号をキーとしたマップの形式にしたもの
型: { [k: string]: KdbSubjectRecordWithRequisite; }
KdBから全件取得したデータ
型: KdbSubjectRecord[]
KdBから全件取得したデータを科目番号をキーとしたマップの形式にしたもの
型: { [k: string]: KdbSubjectRecord; }
KdBのhierarchyのデータをテキストで読めるもの
TWINSから持ってきたデータ
型: TwinsSubject[]
TWINSから持ってきたデータを科目番号をキーとしたマップの形式にしたもの
型: { [k: string]: TwinsSubject; }
TWINSとKdBで異なるデータ
以下のスクリプトを実行すると、最新の科目データをsrc/content/subjects.merged.jsonにダウンロードします。
#!/usr/bin/env bash
curl -Lo src/content/subjects.merged.json "https://github.com/until-tsukuba/twins-kdb-fetch/releases/latest/download/subjects.merged.json"$ git clone https://github.com/until-tsukuba/twins-kdb-fetch.git && npm ci$ cp .env_template .env
$ vim .env
$ npm run build && npm run start
または
$ npm run build && UTID_NAME=s******* PASSWORD=******** npm run start