Skip to content

Commit b503c24

Browse files
committed
show reasons for each student
1 parent 7d0d05e commit b503c24

File tree

1 file changed

+109
-64
lines changed

1 file changed

+109
-64
lines changed

src/index.ts

+109-64
Original file line numberDiff line numberDiff line change
@@ -12,9 +12,18 @@ function mustGetElementById(id: string): HTMLElement {
1212
return e;
1313
}
1414

15-
type In1 = [string, string][];
16-
type In2 = [string][];
17-
type In3 = [string, string, string][];
15+
declare const nominalIdentifier: unique symbol;
16+
type Nominal<T, Identifier> = T & { [nominalIdentifier]: Identifier };
17+
18+
type StudentId = Nominal<string, "StudentId">;
19+
type CourseId = Nominal<string, "CourseId">;
20+
type Email = Nominal<string, "Email">;
21+
22+
type StudentContact = { schoolEmail: Email; personalEmail: Email };
23+
24+
type In1 = Map<StudentId, CourseId>;
25+
type In2 = Map<StudentId, true>;
26+
type In3 = Map<StudentId, StudentContact>;
1827

1928
function parseIn1(s: string): In1 | undefined {
2029
const rows = parse(s);
@@ -33,7 +42,12 @@ function parseIn1(s: string): In1 | undefined {
3342
return undefined;
3443
}
3544
}
36-
return rows;
45+
46+
const in1: In1 = new Map();
47+
for (const [studentId, courseId] of rows) {
48+
in1.set(studentId, courseId);
49+
}
50+
return in1;
3751
}
3852

3953
function parseIn2(s: string): In2 | undefined {
@@ -48,7 +62,12 @@ function parseIn2(s: string): In2 | undefined {
4862
return undefined;
4963
}
5064
}
51-
return rows;
65+
66+
const in2: In2 = new Map();
67+
for (const [studentId] of rows) {
68+
in2.set(studentId, true);
69+
}
70+
return in2;
5271
}
5372

5473
function parseIn3(s: string): In3 | undefined {
@@ -69,23 +88,78 @@ function parseIn3(s: string): In3 | undefined {
6988
return undefined;
7089
}
7190
}
72-
return rows;
91+
92+
const in3: In3 = new Map();
93+
for (const [studentId, schoolEmail, personalEmail] of rows) {
94+
in3.set(studentId, { schoolEmail, personalEmail });
95+
}
96+
return in3;
7397
}
7498

75-
function displayStudents(
76-
studentIds: string[],
77-
studentIdToEmail: Map<string, [string, string]>,
78-
): string {
79-
return studentIds
80-
.map((id) => {
81-
const email = studentIdToEmail.get(id);
82-
if (email === undefined) {
83-
return `${id} (email unknown)`;
84-
} else {
85-
return `${id} ${email[0]} ${email[1]}`;
86-
}
87-
})
88-
.join("\n");
99+
type MissingStudent = {
100+
id: StudentId;
101+
contact: StudentContact | undefined;
102+
wrongCourseId: CourseId | undefined;
103+
};
104+
type SuperfluousStudent = {
105+
id: StudentId;
106+
contact: StudentContact | undefined;
107+
};
108+
type VerifyResult = {
109+
missingStudents: MissingStudent[];
110+
superfluousStudents: SuperfluousStudent[];
111+
};
112+
113+
function verify(
114+
in1: In1,
115+
in2: In2,
116+
in3: In3,
117+
courseId: CourseId,
118+
): VerifyResult {
119+
const missingStudents: MissingStudent[] = [];
120+
const superfluousStudents: SuperfluousStudent[] = [];
121+
122+
for (const studentId of in2.keys()) {
123+
const actualTakenCourseId = in1.get(studentId);
124+
if (actualTakenCourseId === undefined) {
125+
// Student hasn't registered any course
126+
missingStudents.push({
127+
id: studentId,
128+
contact: in3.get(studentId),
129+
wrongCourseId: undefined,
130+
});
131+
} else if (actualTakenCourseId !== courseId) {
132+
// Student has registered the wrong course
133+
missingStudents.push({
134+
id: studentId,
135+
contact: in3.get(studentId),
136+
wrongCourseId: actualTakenCourseId,
137+
});
138+
}
139+
}
140+
141+
for (const [studentId, actualTakenCourseId] of in1.entries()) {
142+
// Student took the `courseId` course even though they don't have to
143+
if (actualTakenCourseId === courseId && !in2.has(studentId)) {
144+
superfluousStudents.push({
145+
id: studentId,
146+
contact: in3.get(studentId),
147+
});
148+
}
149+
}
150+
151+
return {
152+
missingStudents,
153+
superfluousStudents,
154+
};
155+
}
156+
157+
function displayMaybeStudentContact(c: StudentContact | undefined): string {
158+
if (c === undefined) {
159+
return "(メアド不明)";
160+
} else {
161+
return `学校: ${c.schoolEmail} 個人: ${c.personalEmail}`;
162+
}
89163
}
90164

91165
function main() {
@@ -112,53 +186,24 @@ function main() {
112186
const courseId = courseIdElement.value;
113187
assert(in1 !== undefined && in2 !== undefined && in3 !== undefined);
114188

115-
const studentIdToEmail = new Map<string, [string, string]>();
116-
for (const [studentId, schoolEmail, personalEmail] of in3) {
117-
studentIdToEmail.set(studentId, [schoolEmail, personalEmail]);
118-
}
119-
120-
const studentIdToCourseId = new Map<string, string>();
121-
for (const [studentId, courseId] of in1) {
122-
studentIdToCourseId.set(studentId, courseId);
123-
}
124-
125-
const shouldTakeCourseStudentIds = new Map<string, true>();
126-
for (const [studentId] of in2) {
127-
shouldTakeCourseStudentIds.set(studentId, true);
128-
}
129-
130-
const mistakeIds: string[] = [];
131-
const unnecessaryIds: string[] = [];
132-
133-
for (const studentId of shouldTakeCourseStudentIds.keys()) {
134-
const actualTakenCourseId = studentIdToCourseId.get(studentId);
135-
if (actualTakenCourseId === undefined) {
136-
// NOTE: student hasn't registered a course
137-
mistakeIds.push(studentId);
138-
continue;
139-
}
140-
if (actualTakenCourseId !== courseId) {
141-
mistakeIds.push(studentId);
142-
}
143-
}
144-
145-
for (const [
146-
studentId,
147-
actualTakenCourseId,
148-
] of studentIdToCourseId.entries()) {
149-
if (
150-
actualTakenCourseId === courseId &&
151-
!shouldTakeCourseStudentIds.has(studentId)
152-
) {
153-
unnecessaryIds.push(studentId);
154-
}
155-
}
156-
189+
const result = verify(in1, in2, in3, courseId as CourseId);
157190
outElement.innerHTML = `この授業を取らなくていいのに取っている学生:
158-
${displayStudents(unnecessaryIds, studentIdToEmail)}
191+
${result.superfluousStudents
192+
.map((s) => `${s.id} ${displayMaybeStudentContact(s.contact)}`)
193+
.join("\n")}
159194
160195
この授業を取らないといけないのに取っていない学生:
161-
${displayStudents(mistakeIds, studentIdToEmail)}
196+
${result.missingStudents
197+
.map((s) => {
198+
let reason: string;
199+
if (s.wrongCourseId === undefined) {
200+
reason = "履修登録なし";
201+
} else {
202+
reason = `${s.wrongCourseId}を誤登録`;
203+
}
204+
return `${s.id} 理由: ${reason} ${displayMaybeStudentContact(s.contact)}`;
205+
})
206+
.join("\n")}
162207
`;
163208
});
164209
}

0 commit comments

Comments
 (0)