Skip to content

Commit

Permalink
Errors due to closure on search by course id endpoints (#214)
Browse files Browse the repository at this point in the history
* fix semester parsing error

* fix class selection table index

* remove deprecated student node parser

* remove deprecated course extra info parser

* rewrite course extra info parser

* fix course extra href

* remove deprecated course student info layout

* fix course id parsing in getTWCourseMainInfoList

* fix courseInfo display logic

* fix courseInfo display logic

* resolve redundant logic with string filter

* fix unknown characters by changing encryption

* fix unable to fetch score

* dart reformat

* remove unused items

* remove unused package

* fix CourseExtraInfo category symbol

* Update lib/ui/pages/coursetable/course_table_page.dart

Co-authored-by: Chenghsuan Ho <[email protected]>

* use runtime constants

* adding comments for semester parser

* providing meaningful names

* fix un-expected indexing

* resolving unintuitive variable name

Co-authored-by: Tien Yu Lin <[email protected]>

* resolving unintuitive variable name

* unify object names related to studentSemesterDetail

* add RangeError exception throwing logic on studentSemesterDetails

* add StateError exception throwing logic on CourseId not found

* make studentId TextField read-only

* fix application crash on education survay unfinished

* add error throwing logic on education survay unfinished

* Update lib/src/connector/course_connector.dart

Co-authored-by: Chenghsuan Ho <[email protected]>

* Update lib/src/connector/course_connector.dart

Co-authored-by: Chenghsuan Ho <[email protected]>

* Update lib/src/connector/course_connector.dart

Co-authored-by: Chenghsuan Ho <[email protected]>

* Update lib/src/connector/course_connector.dart

Co-authored-by: Chenghsuan Ho <[email protected]>

* change exception type

* set default course category

* filters out credit doubles

* Fix: Score fetch error caused by semester survey

* simplify default course category logic

* add error rethow on task logic

* add error rethow on task logic

* fix: use `i10n` messages upon `FormatException` of `getScoreRankList()`

* chore: remove TODOs

* style: run `dart format`

---------

Co-authored-by: Chenghsuan Ho <[email protected]>
Co-authored-by: Tien Yu Lin <[email protected]>
Co-authored-by: ntut-xuan <[email protected]>
  • Loading branch information
4 people authored Dec 21, 2023
1 parent 115a7af commit 1ee8c73
Show file tree
Hide file tree
Showing 12 changed files with 116 additions and 127 deletions.
14 changes: 7 additions & 7 deletions lib/generated/intl/messages_all.dart
Original file line number Diff line number Diff line change
Expand Up @@ -19,10 +19,10 @@ import 'package:intl/src/intl_helpers.dart';
import 'messages_en.dart' as messages_en;
import 'messages_zh_TW.dart' as messages_zh_tw;

typedef LibraryLoader = Future<dynamic> Function();
typedef Future<dynamic> LibraryLoader();
Map<String, LibraryLoader> _deferredLibraries = {
'en': () => SynchronousFuture(null),
'zh_TW': () => SynchronousFuture(null),
'en': () => new SynchronousFuture(null),
'zh_TW': () => new SynchronousFuture(null),
};

MessageLookupByLibrary? _findExact(String localeName) {
Expand All @@ -41,13 +41,13 @@ Future<bool> initializeMessages(String localeName) {
var availableLocale =
Intl.verifiedLocale(localeName, (locale) => _deferredLibraries[locale] != null, onFailure: (_) => null);
if (availableLocale == null) {
return SynchronousFuture(false);
return new SynchronousFuture(false);
}
var lib = _deferredLibraries[availableLocale];
lib == null ? SynchronousFuture(false) : lib();
initializeInternalMessageLookup(() => CompositeMessageLookup());
lib == null ? new SynchronousFuture(false) : lib();
initializeInternalMessageLookup(() => new CompositeMessageLookup());
messageLookup.addLocale(availableLocale, _findGeneratedMessagesFor);
return SynchronousFuture(true);
return new SynchronousFuture(true);
}

bool _messagesExistFor(String locale) {
Expand Down
10 changes: 6 additions & 4 deletions lib/generated/intl/messages_en.dart
Original file line number Diff line number Diff line change
Expand Up @@ -13,9 +13,9 @@
import 'package:intl/intl.dart';
import 'package:intl/message_lookup_by_library.dart';

final messages = MessageLookup();
final messages = new MessageLookup();

typedef MessageIfAbsent = String Function(String messageStr, List<dynamic> args);
typedef String MessageIfAbsent(String messageStr, List<dynamic> args);

class MessageLookup extends MessageLookupByLibrary {
String get localeName => 'en';
Expand Down Expand Up @@ -139,8 +139,10 @@ class MessageLookup extends MessageLookupByLibrary {
"getISchoolPlusCourseAnnouncementError": MessageLookupByLibrary.simpleMessage("Get course announcement error"),
"getISchoolPlusCourseFile": MessageLookupByLibrary.simpleMessage("Get course files"),
"getISchoolPlusCourseFileError": MessageLookupByLibrary.simpleMessage("Get course files error"),
"getScoreRank": MessageLookupByLibrary.simpleMessage("Getting grade..."),
"getScoreRankError": MessageLookupByLibrary.simpleMessage("Getting grade error"),
"getScoreRank": MessageLookupByLibrary.simpleMessage("Getting the grades..."),
"getScoreRankError": MessageLookupByLibrary.simpleMessage("There\'s an error getting the grades"),
"getScoreRankQuestionnaireError": MessageLookupByLibrary.simpleMessage(
"There\'s an error getting the grades.\nPlease check if the Online Course Evaluation Questionnaire has been completed"),
"github": MessageLookupByLibrary.simpleMessage("Github"),
"graduationSetting": MessageLookupByLibrary.simpleMessage("Graduation credit standard setting"),
"historicalDimension": MessageLookupByLibrary.simpleMessage("Historical dimension"),
Expand Down
5 changes: 3 additions & 2 deletions lib/generated/intl/messages_zh_TW.dart
Original file line number Diff line number Diff line change
Expand Up @@ -13,9 +13,9 @@
import 'package:intl/intl.dart';
import 'package:intl/message_lookup_by_library.dart';

final messages = MessageLookup();
final messages = new MessageLookup();

typedef MessageIfAbsent = String Function(String messageStr, List<dynamic> args);
typedef String MessageIfAbsent(String messageStr, List<dynamic> args);

class MessageLookup extends MessageLookupByLibrary {
String get localeName => 'zh_TW';
Expand Down Expand Up @@ -137,6 +137,7 @@ class MessageLookup extends MessageLookupByLibrary {
"getISchoolPlusCourseFileError": MessageLookupByLibrary.simpleMessage("取得課程檔案錯誤"),
"getScoreRank": MessageLookupByLibrary.simpleMessage("取得成績中..."),
"getScoreRankError": MessageLookupByLibrary.simpleMessage("取得成績錯誤"),
"getScoreRankQuestionnaireError": MessageLookupByLibrary.simpleMessage("取得成績錯誤,請確認期末教學評量是否填寫完成"),
"github": MessageLookupByLibrary.simpleMessage("Github"),
"graduationSetting": MessageLookupByLibrary.simpleMessage("畢業學分標準設定"),
"historicalDimension": MessageLookupByLibrary.simpleMessage("歷史向度"),
Expand Down
18 changes: 14 additions & 4 deletions lib/generated/l10n.dart

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

5 changes: 3 additions & 2 deletions lib/l10n/intl_en.arb
Original file line number Diff line number Diff line change
Expand Up @@ -57,8 +57,9 @@
"getISchoolPlusCourseAnnouncementError": "Get course announcement error",
"getISchoolPlusCourseAnnouncementDetail": "Get course announcement detail...",
"getISchoolPlusCourseAnnouncementDetailError": "Get course announcement detail error",
"getScoreRank": "Getting grade...",
"getScoreRankError": "Getting grade error",
"getScoreRank": "Getting the grades...",
"getScoreRankError": "There's an error getting the grades",
"getScoreRankQuestionnaireError": "There's an error getting the grades.\nPlease check if the Online Course Evaluation Questionnaire has been completed",
"getCalendar": "Getting calendar...",
"getCalendarError": "Getting calendar error",
"deleteMessage": "Deleting message...",
Expand Down
1 change: 1 addition & 0 deletions lib/l10n/intl_zh_TW.arb
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,7 @@
"getISchoolPlusCourseAnnouncementDetailError": "取得公告內容錯誤",
"getScoreRank": "取得成績中...",
"getScoreRankError": "取得成績錯誤",
"getScoreRankQuestionnaireError": "取得成績錯誤,請確認期末教學評量是否填寫完成",
"getCalendar": "取得行事曆中...",
"getCalendarError": "取得行事曆錯誤",
"deleteMessage": "刪除訊息中...",
Expand Down
82 changes: 51 additions & 31 deletions lib/src/connector/course_connector.dart
Original file line number Diff line number Diff line change
Expand Up @@ -85,7 +85,7 @@ class CourseConnector {
ConnectorParameter parameter;
Document tagNode;
Element node;
List<Element> courseNodes, nodes, classmateNodes;
List<Element> courseNodes, nodes, classExtraInfoNodes;
Map<String, String> data = {
"code": courseId,
"format": "-1",
Expand All @@ -101,38 +101,61 @@ class CourseConnector {
//取得學期資料
nodes = courseNodes[0].getElementsByTagName("td");
SemesterJson semester = SemesterJson();
semester.year = nodes[1].text;
semester.semester = nodes[2].text;

// Previously, the title string of the first course table was stored separately in its `<td>` element,
// but it currently stores all the information in a row,
// e.g. "學號:110310144  姓名:xxx  班級:電機三甲    112 學年度 第 1 學期 上課時間表"
// so the RegExp is used to filter out only the number parts
final titleString = nodes[0].text;
final RegExp studentSemesterDetailFilter = RegExp(r'\b\d+\b');
final Iterable<RegExpMatch> studentSemesterDetailMatches = studentSemesterDetailFilter.allMatches(titleString);
// "studentSemesterDetails" should consist of three numerical values
// ex: [110310144, 112, 1]
final List<String> studentSemesterDetails = studentSemesterDetailMatches.map((match) => match.group(0)).toList();
if (studentSemesterDetails.isEmpty) {
throw RangeError("[TAT] course_connector.dart: studentSemesterDetails list is empty");
}
if (studentSemesterDetails.length < 3) {
throw RangeError("[TAT] course_connector.dart: studentSemesterDetails list has range less than 3");
}
semester.year = studentSemesterDetails[1];
semester.semester = studentSemesterDetails[2];

courseExtraInfo.courseSemester = semester;

CourseExtraJson courseExtra = CourseExtraJson();

courseExtra.name = nodes[3].getElementsByTagName("a")[0].text;
if (nodes[3].getElementsByTagName("a")[0].attributes.containsKey("href")) {
courseExtra.href = _courseCNHost + nodes[3].getElementsByTagName("a")[0].attributes["href"];
nodes = courseNodes[1].getElementsByTagName("tr");
final List<String> courseIds = nodes.skip(2).map((node) => node.getElementsByTagName("td")[0].text).toList();
final courseIdPosition = courseIds.indexWhere((element) => element.contains(courseId));
if (courseIdPosition == -1) {
throw StateError('[TAT] course_connector.dart: CourseId not found: $courseId');
} else {
node = nodes[courseIdPosition + 2];
}
classExtraInfoNodes = node.getElementsByTagName("td");
courseExtra.id = strQ2B(classExtraInfoNodes[0].text).replaceAll(RegExp(r"\s"), "");
courseExtra.name = classExtraInfoNodes[1].getElementsByTagName("a")[0].text;
courseExtra.openClass = classExtraInfoNodes[7].getElementsByTagName("a")[0].text;

// if the courseExtraInfo.herf (課程大綱連結) is empty,
// the category of the course will be set to ▲ (校訂專業必修) as default
if (classExtraInfoNodes[18].text.trim() != "" &&
classExtraInfoNodes[18].getElementsByTagName("a")[0].attributes.containsKey("href")) {
courseExtra.href = _courseCNHost + classExtraInfoNodes[18].getElementsByTagName("a")[0].attributes["href"];
parameter = ConnectorParameter(courseExtra.href);
result = await Connector.getDataByPost(parameter);
tagNode = parse(result);
nodes = tagNode.getElementsByTagName("tr");
courseExtra.category = nodes[1].getElementsByTagName("td")[6].text;
} else {
courseExtra.category = constCourseType[4];
}
courseExtra.category = nodes[7].text; // 取得類別
courseExtra.openClass = nodes[9].text;
courseExtra.selectNumber = nodes[11].text;
courseExtra.withdrawNumber = nodes[12].text;
courseExtra.id = courseId;

courseExtraInfo.course = courseExtra;
courseExtra.selectNumber = "s?";
courseExtra.withdrawNumber = "w?";

nodes = courseNodes[2].getElementsByTagName("tr");
for (int i = 1; i < nodes.length; i++) {
node = nodes[i];
classmateNodes = node.getElementsByTagName("td");
ClassmateJson classmate = ClassmateJson();
classmate.className = classmateNodes[0].text;
classmate.studentId = classmateNodes[1].getElementsByTagName("a")[0].text;
classmate.href = _courseCNHost + classmateNodes[1].getElementsByTagName("a")[0].attributes["href"];
classmate.studentName = classmateNodes[2].text;
classmate.studentEnglishName = classmateNodes[3].text;
classmate.isSelect = !classmateNodes[4].text.contains("撤選");
courseExtraInfo.classmate.add(classmate);
}
courseExtraInfo.course = courseExtra;
return courseExtraInfo;
} catch (e, stack) {
Log.eWithStack(e.toString(), stack);
Expand Down Expand Up @@ -202,7 +225,7 @@ class CourseConnector {
};
parameter = ConnectorParameter(_postCourseENUrl);
parameter.data = data;
parameter.charsetName = 'big5';
parameter.charsetName = 'utf-8';
Response response = await Connector.getDataByPostResponse(parameter);
tagNode = parse(response.toString());
nodes = tagNode.getElementsByTagName("table");
Expand Down Expand Up @@ -317,11 +340,8 @@ class CourseConnector {
continue;
}
//取得課號
nodes = nodesOne[0].getElementsByTagName("a"); //確定是否有課號
if (nodes.isNotEmpty) {
courseMain.id = nodes[0].text;
courseMain.href = _courseCNHost + nodes[0].attributes["href"];
}
courseMain.id = strQ2B(nodesOne[0].text).replaceAll(RegExp(r"\s"), "");

//取的課程名稱/課程連結
nodes = nodesOne[1].getElementsByTagName("a"); //確定是否有連結
if (nodes.isNotEmpty) {
Expand Down
16 changes: 13 additions & 3 deletions lib/src/connector/score_connector.dart
Original file line number Diff line number Diff line change
Expand Up @@ -81,9 +81,14 @@ class ScoreConnector {
parameter = ConnectorParameter(_scoreAllScoreUrl);
parameter.data = data;
result = await Connector.getDataByGet(parameter);
final List<String> evalQuestionnaireCheckTexts = ['教學評量', 'Course Evaluation Questionnaire'];
if (evalQuestionnaireCheckTexts.any((text) => result.contains(text))) {
throw const FormatException(
"[TAT] score_connector.dart: evalQuestionnaireCheckTexts was found in request result");
}

tagNode = parse(result);
final h3Nodes = tagNode.getElementsByTagName("h3");

//依照學期取得課程資料
for (final h3Node in h3Nodes) {
final siblingOfH3 = h3Node.nextElementSibling;
Expand Down Expand Up @@ -112,7 +117,12 @@ class ScoreConnector {
score.courseId = scoreNode.getElementsByTagName("th")[0].text.replaceAll(RegExp(r"[\s| ]"), "");
score.nameZh = scoreNode.getElementsByTagName("th")[2].text.replaceAll(RegExp(r"[\s| ]"), "");
score.nameEn = scoreNode.getElementsByTagName("th")[3].text.replaceAll(RegExp("\n"), "");
score.credit = double.parse(scoreNode.getElementsByTagName("th")[6].text);
RegExp creditDoubleFilter = RegExp(r'\d+(\.\d+)?');
final Iterable<RegExpMatch> creditDoubleMatches =
creditDoubleFilter.allMatches(scoreNode.getElementsByTagName("th")[6].text);
final List<String> creditDoubles = creditDoubleMatches.map((match) => match.group(0)).toList();

score.credit = double.parse(creditDoubles[0]);
score.score = scoreNode.getElementsByTagName("th")[7].text.replaceAll(RegExp(r"[\s| ]"), "");
courseScore.courseScoreList.add(score);
}
Expand Down Expand Up @@ -187,7 +197,7 @@ class ScoreConnector {
return courseScoreList;
} catch (e, stack) {
Log.eWithStack(e.toString(), stack);
return null;
rethrow;
}
}

Expand Down
17 changes: 11 additions & 6 deletions lib/src/task/score/score_rank_task.dart
Original file line number Diff line number Diff line change
Expand Up @@ -14,14 +14,19 @@ class ScoreRankTask extends ScoreSystemTask<List<SemesterCourseScoreJson>> {
Future<TaskStatus> execute() async {
final status = await super.execute();
if (status == TaskStatus.success) {
super.onStart(R.current.getScoreRank);
final value = await ScoreConnector.getScoreRankList() as List<SemesterCourseScoreJson>?;
super.onEnd();
if (value != null) {
try {
super.onStart(R.current.getScoreRank);
final value = await ScoreConnector.getScoreRankList() as List<SemesterCourseScoreJson>?;
super.onEnd();

result = value;
return TaskStatus.success;
} else {
return super.onError(R.current.getScoreRankError);
} catch (e) {
if (e is FormatException) {
return super.onError(R.current.getScoreRankQuestionnaireError);
} else {
return super.onError(R.current.getScoreRankError);
}
}
}
return status;
Expand Down
Loading

0 comments on commit 1ee8c73

Please sign in to comment.