// ==UserScript==
// @name 清华本科生选课系统-课程时间冲突提示
// @version 1.0
// @namespace http://tampermonkey.net/
// @author Siyuan
// @description 将课表保存到本地,检测课程时间冲突
// @match https://zhjwxk.cic.tsinghua.edu.cn/xkBks.vxkBksXkbBs.do?m=kbSearch*
// @match https://zhjwxk.cic.tsinghua.edu.cn/xkBks.vxkBksJxjhBs.do
// @match https://zhjwxk.cic.tsinghua.edu.cn/xkBks.vxkBksJxjhBs.do?m=kkxxSearch*
// @match https://zhjwxk.cic.tsinghua.edu.cn/xkBks.vxkBksXkbBs.do?m=xkqkSearch*
// @match https://zhjwxk.cic.tsinghua.edu.cn/xkBks.vxkBksXkbBs.do?m=bxSearch*
// @match https://zhjwxk.cic.tsinghua.edu.cn/xkBks.vxkBksXkbBs.do?m=xxSearch*
// @match https://zhjwxk.cic.tsinghua.edu.cn/xkBks.vxkBksXkbBs.do?m=rxSearch*
// @match https://zhjwxk.cic.tsinghua.edu.cn/xkBks.vxkBksXkbBs.do?m=tySearch*
// @match https://zhjwxk.cic.tsinghua.edu.cn/xkBks.vxkBksXkbBs.do
// @grant none
// @license MIT
// @downloadURL none
// ==/UserScript==
function get_child_2_layers(node) {
return node.firstElementChild.firstElementChild;
}
function get_child_1_layer(node) {
return node.firstElementChild;
}
function set_page_attr(type, attr) {
switch (type) {
case 'bxr':
attr.start_row = 0;
attr.target_column = 6;
attr.get_child = get_child_1_layer;
break;
case 'sports':
attr.start_row = 0;
attr.target_column = 5;
attr.get_child = get_child_1_layer;
break;
case 'primary':
attr.start_row = 1;
attr.target_column = 10;
attr.get_child = get_child_2_layers;
break;
case 'spare':
attr.start_row = 0;
attr.target_column = 7;
attr.get_child = get_child_1_layer;
break;
}
}
function switch_table(type, table) {
if (type == 'bxr') {
return document.querySelector("#table_t");
} else if (type == 'sports') {
return document.querySelector('#content_1 > table');
} else if (type == 'spare') {
return document.querySelector('#content_1 > table');
} else {
return table;
}
}
function conflict_courses() {
if (localStorage.getItem('courses') == undefined) {
console.log('courses not found in localStorage');
return;
}
let courses = JSON.parse(localStorage.getItem('courses'));
console.log(courses);
let table = document.querySelector('#table_sy > table') ??
document.querySelector("#a > div > div > div.keH.clearfix > div.tabdiv > div:nth-child(1) > table.table1") ??
document.querySelector('#table_h') ??
document.querySelector("#pathTd > div.window_neirong > div > form > div > div > div > div > div > div.tabdiv > div:nth-child(1) > table");
if (table == undefined) {
console.log('error: no table found');
return;
}
//console.log(table.ownerDocument.URL);
let type = '';
console.log(table);
if (table.rows[0].cells[0].innerText == '开课院系') {
type = 'primary';
} else if (table.rows[0].cells[0].innerText == '课程号') {
type = 'spare';
} else if (table.rows[0].cells[5].innerText == '上课时间') {
type = 'sports';
} else if (table.rows[0].cells[6].innerText == '上课时间') {
type = 'bxr';
} else {
console.log('error: cannot recognize page type');
return;
}
console.log('page type:', type);
let attr = {};
set_page_attr(type, attr);
table = switch_table(type, table);
if (table == undefined) {
return;
}
let size = table.rows.length;
//console.log(col);
for (let i = attr.start_row; i < size; i++) {
let cell = attr.get_child(table.rows[i].cells[attr.target_column]);
//console.log(cell);
let time_str = cell.title == '' ? cell.innerText : cell.title;
let times = time_str.replaceAll(/\([^\(\)]+\)/g, '').split(',');
let conflict = [];
for (let j = 0; j < times.length; j++) {
times[j] = trim(times[j]);
if (times[j].length >= 3) {
//console.log(times[j]);
let p = parseInt(times[j][0]);
let q = parseInt(times[j][2]);
conflict = conflict.concat(courses[p][q]);
}
}
function onlyUnique(value, index, array) {
return array.indexOf(value) === index;
}
conflict = conflict.filter(onlyUnique);
if (conflict.length > 0) {
let waiting = true;
for (let j = 0; j < conflict.length; j++) {
if (!conflict[j].startsWith('候选:')) {
waiting = false;
break;
}
}
cell.style.color = waiting ? 'blue' : 'red';
cell.title += (cell.title == '' ? '' : ', ');
//console.log(times, conflict);
cell.title += conflict.join(', ');
}
}
}
function add_courses() {
let courses = [];
for (let i = 1; i <= 7; i++) {
courses[i] = [null, [], [], [], [], [], []];
}
for (let i = 1; i <= 7; i++) {
for (let j = 1; j <= 6; j++) {
let cell = document.querySelector('body > div > form > div > div > div > div > div:nth-child(3) > table').rows[j].cells[i];
for (let k = 0; k < cell.childNodes.length; k++) {
if (cell.childNodes[k].nodeName == 'A') {
courses[i][j].push(cell.childNodes[k].innerText);
}
}
//let name = cell.innerText;
//name = trim(name);
//if (name != '') {
// courses[i][j] = cell.firstElementChild.innerText;
//}
}
}
console.log(courses);
console.log('all courses added into localStorage');
localStorage.setItem('courses',JSON.stringify(courses));
window.alert('课表信息已保存');
}
function del_courses() {
console.log('all courses removed from localStorage');
localStorage.removeItem('courses');
window.alert('本地存储已清除');
}
(function() {
'use strict';
if (document.URL.startsWith('https://zhjwxk.cic.tsinghua.edu.cn/xkBks.vxkBksXkbBs.do?m=kbSearch')) {
let add = document.createElement('div');
add.innerHTML = '';
let del = document.createElement('div');
del.innerHTML = '';
let div = document.querySelector('body > div > form > div > div > div > div > div:nth-child(2)');
div.insertBefore(add, div.lastElementChild);
div.insertBefore(del, div.lastElementChild);
add.children[0].onclick = add_courses;
del.children[0].onclick = del_courses;
} else {
conflict_courses();
}
})();