1
+ package main.java.parser
2
+
3
+ import bean.Course
4
+ import org.jsoup.Jsoup
5
+ import parser.Parser
6
+
7
+ /* *
8
+ * Created by [YenalyLiew](https://github.com/YenalyLiew)
9
+ *
10
+ * 重庆邮电大学本科生课表
11
+ *
12
+ * 不是所有类型课表全部适配,比如4节课连上的情况可能有BUG,可以在Github联系我。
13
+ */
14
+
15
+ class CQUPTParser (source : String ) : Parser(source) {
16
+
17
+ companion object {
18
+ // 我这里课程列表在程序里进行修正后长度就是8,
19
+ // 如果你的课表不是很幸运,可能导入就没用或者全乱了。
20
+ private const val COURSE_INFO_SIZE = 8
21
+
22
+ // 通常课程的节数是2。
23
+ private const val GENERAL_CLASS_LENGTH = 2
24
+
25
+ private val indexWithClassStart = mapOf (0 to 1 , 1 to 3 , 3 to 5 , 4 to 7 , 6 to 9 , 7 to 11 )
26
+ private val indexWithClassEnd = mapOf (0 to 2 , 1 to 4 , 3 to 6 , 4 to 8 , 6 to 10 , 7 to 12 )
27
+ }
28
+
29
+ override fun generateCourseList (): List <Course > {
30
+ val doc = Jsoup .parse(source)
31
+ val classesLine = doc.getElementById(" stuPanel" ).select(" tr[style=text-align:center]" )
32
+ val courseList = ArrayList <Course >()
33
+ // 最寄O(n^4)复杂度,哈哈了。
34
+ // 最外层循环,是先一行一行扫一遍,得到每行的数据。
35
+ // 第二层循环,一行内每个框扫一遍,因为index=0的元素正好没用,所以扫到的索引数值正好对应当前星期数值。
36
+ // 第三层循环,为了防止有的行内的框内有好几个课只能取到第一个,只能循环全取。
37
+ // 最内层循环,有的周是一个周,有的周是好多周,又有的周用逗号隔开,只能靠循环把他们分开。
38
+ classesLine.forEachIndexed { classIndex, classLine ->
39
+ classLine.select(" td" ).forEachIndexed { dayWeek, courses ->
40
+ val coursesInfo = courses.text().replace(" -" , " -" ).split(" " )
41
+ if (coursesInfo.size >= COURSE_INFO_SIZE ) {
42
+ val courseInfoNumber: Int = coursesInfo.size / COURSE_INFO_SIZE
43
+ for (i in 0 until courseInfoNumber) {
44
+ val name = coursesInfo[1 + i * COURSE_INFO_SIZE ].run { substring(indexOf(" -" ) + 1 ) }
45
+ val room = coursesInfo[2 + i * COURSE_INFO_SIZE ].run { substring(indexOf(" :" ) + 1 ) }
46
+ val teacher = coursesInfo[4 + i * COURSE_INFO_SIZE ]
47
+ val credit = coursesInfo[6 + i * COURSE_INFO_SIZE ].run { substring(0 , indexOf(" 学分" )).toFloat() }
48
+ val startNode = indexWithClassStart[classIndex] ? : 1
49
+ val endNode = indexWithClassEnd[classIndex] ? : 2
50
+ coursesInfo[3 + i * COURSE_INFO_SIZE ].split(" ," ).forEach { weeks ->
51
+ val startWeek: Int
52
+ val endWeek: Int
53
+ val type = if (weeks.contains(" 单周" )) 1 else if (weeks.contains(" 双周" )) 2 else 0
54
+ val classInRow = if (weeks.contains(" 节连上" )) {
55
+ weeks.run { substring(indexOf(" 周" ) + 1 , indexOf(" 节连上" )).toInt() }
56
+ } else 0
57
+ val realEndNode = if (classInRow != 0 ) {
58
+ endNode + classInRow - GENERAL_CLASS_LENGTH
59
+ } else endNode
60
+ if (weeks.contains(" -" )) {
61
+ startWeek = weeks.run { substring(0 , indexOf(" -" )).toInt() }
62
+ endWeek = weeks.run { substring(indexOf(" -" ) + 1 , indexOf(" 周" )).toInt() }
63
+ } else {
64
+ startWeek = weeks.run { substring(0 , indexOf(" 周" )).toInt() }
65
+ endWeek = startWeek
66
+ }
67
+ val course = Course (
68
+ name = name,
69
+ room = room,
70
+ teacher = teacher,
71
+ credit = credit,
72
+ day = dayWeek, // dayWeek 代表星期X
73
+ startNode = startNode,
74
+ endNode = realEndNode,
75
+ type = type,
76
+ startWeek = startWeek, // startWeek-endWeek 代表 x周-y周
77
+ endWeek = endWeek
78
+ )
79
+ courseList.add(course)
80
+ }
81
+ }
82
+ }
83
+ }
84
+ }
85
+ return courseList
86
+ }
87
+ }
0 commit comments