Greasy Fork is available in English.

SIT上应教务系统选课助手

从选课弹窗中留下能选的课。

// ==UserScript==
// @name        SIT上应教务系统选课助手
// @description 从选课弹窗中留下能选的课。
// @author      RainSlide
// @namespace   RainSlide
// @match       http://ems1.sit.edu.cn:85/student/selCourse/studentSel/teachclasslist.jsp*
// @version     1.0
// @grant       none
// @run-at      document-idle
// ==/UserScript==

if (localStorage && !localStorage.selectedCourse)
    fetch('http://ems1.sit.edu.cn:85/student/selCourse/syllabuslist3.jsp', {
        credentials: 'include',
    })
        .then((response) =>
            new DOMParser().parseFromString(response.text(), 'text/html')
        )
        .then(
            (fetchedDoc) =>
                (localStorage.selectedCourse = Array.from(
                    (() => {
                        const tables = fetchedDoc.getElementsByTagName('table');
                        for (let i = 0; i < tables.length; i++) {
                            if (
                                // 表格首行元素内容为“课程表”
                                tables[i].querySelector('th.list') &&
                                tables[i].querySelector('th.list')
                                    .textContent === '课程表'
                            )
                                return tables[i];
                        }
                        alart('找不到选课课程表,请登录!');
                        return null;
                    })().querySelectorAll('tr')
                )
                    .slice(2)
                    .map((tr) =>
                        Array.from(tr.querySelectorAll('td[rowspan]')).map(
                            (td) =>
                                [
                                    td.cellIndex,
                                    +tr.firstElementChild.textContent,
                                    +tr.firstElementChild.textContent +
                                        td.rowSpan -
                                        1,
                                ].join(' ')
                        )
                    )
                    .flat()
                    .join('\n'))
        )
        .then(() => alart('请刷新一次!'));

(() => {
    if (!localStorage) {
        alart('换个浏览器吧');
        return false;
    }

    const style = document.createElement('style');
    style.textContent = '.hidden { display: none; }';
    document.head.appendChild(style);

    // 已选课程上课时间数据
    // "2 1 2\n3 1 2\n5 1 2\n1 3 4\n2 3 4\n3 3 4\n5 3 4\n3 5 6\n4 5 6\n1 7 8\n2 7 8\n1 9 11\n2 9 11\n3 9 11"
    const selectedCourse = localStorage.selectedCourse.split('\n').map((str) =>
        str.replace(
            // 1 2 3 => 周1,第2-3节
            /(\d+) (\d+) (\d+)/g,
            (match, p1, p2, p3) => `周${p1},第${p2}-${p3}节`
        )
    );

    // 隐藏课程并格式化打印内容
    const hideAndLog = (tr, str) => {
        tr.classList.add('hidden');
        const strArray = tr.textContent
            .trim()
            .replace(/\s*选择$/g, '')
            .replace(/\s*\n\s*/g, '\n')
            .split('\n');

        if (strArray[1].length < 3)
            strArray[1] += ' '.repeat(3 - strArray[1].length);
        if (strArray[2].length < 3)
            strArray[2] += ' '.repeat(3 - strArray[2].length);
        if (strArray[3].length < 3)
            strArray[3] += ' '.repeat(3 - strArray[3].length);

        console.log(str + ':' + strArray.join(' | '));
    };

    Array.from(document.body.querySelectorAll('tr[style][onclick]')).forEach(
        (tr) => {
            // 从指定索引的 <td> 子元素中获取字符串
            const getStringFromTd = (nthIndex) =>
                tr.querySelector(':scope > td:nth-of-type(' + nthIndex + ')')
                    .textContent;

            // 从指定索引的 <td> 子元素中获取数字
            const getNumberFromTd = (nthIndex) => +getStringFromTd(nthIndex);

            // 已选人数 >= 最大人数
            getNumberFromTd(3) >= getNumberFromTd(2) &&
                hideAndLog(tr, '选满了');

            // 检查上课时间
            selectedCourse.some((course) =>
                getStringFromTd(5).includes(course)
            ) && hideAndLog(tr, '有冲突');
        }
    );
})();