getStudentProfile method
Fetches student status (學籍基本資料) from the basis data page.
Extracts personal information including bilingual names, DOB, program, and department. Handles specific formatting for mixed Chinese/English strings.
Implementation
Future<StudentProfileDto> getStudentProfile() async {
final response = await _studentQueryDio.get('QryBasisData.jsp');
final document = parse(response.data);
final table = document.querySelector('table');
if (table == null) {
throw FormatException('No table found in QryBasisData.jsp');
}
// Build a map from English header text to the cell value.
// Data rows have 2 TH (Chinese label, English label) + 1 TD (value).
final fields = <String, String?>{};
for (final row in table.querySelectorAll('tr')) {
final ths = row.querySelectorAll('th');
final tds = row.querySelectorAll('td');
if (ths.length != 2 || tds.length != 1) continue;
final key = ths[1].text.trim();
// English Name has an inline <div> note; extract the first text node.
if (key == 'English Name') {
fields[key] = tds[0].nodes
.where((node) => node.nodeType == Node.TEXT_NODE)
.firstOrNull
?.text
?.trim();
} else {
fields[key] = _parseCellText(tds[0]);
}
}
// Date of Birth: "92年05月12日 2003/5/12" — extract Western date.
final dobMatch = RegExp(
r'(\d{4})/(\d{1,2})/(\d{1,2})',
).firstMatch(fields['Date of Birth'] ?? '');
final dateOfBirth = dobMatch != null
? DateTime(
int.parse(dobMatch.group(1)!),
int.parse(dobMatch.group(2)!),
int.parse(dobMatch.group(3)!),
)
: null;
// Split mixed Chinese+English text at the first Latin character.
// e.g. "四年制大學部Four-Year Program" → ("四年制大學部", "Four-Year Program")
(String?, String?) splitZhEn(String? text) {
if (text == null) return (null, null);
final i = text.indexOf(RegExp(r'[A-Za-z]'));
if (i <= 0) return (text, null);
return (text.substring(0, i).trim(), text.substring(i).trim());
}
final (programZh, programEn) = splitZhEn(fields['Program']);
final (departmentZh, departmentEn) = splitZhEn(
fields['Department/Graduate Institute'],
);
return (
chineseName: fields['Chinese Name'],
englishName: fields['English Name'],
dateOfBirth: dateOfBirth,
programZh: programZh,
programEn: programEn,
departmentZh: departmentZh,
departmentEn: departmentEn,
);
}