├── README.md └── gpa_calc.js /README.md: -------------------------------------------------------------------------------- 1 | # UCAS本科生GPA、加权平均分实时计算器 2 | 3 | ## 前言 4 | 5 | 写这个脚本纯属是闲的蛋疼。。。新学期上课之前没有什么事情。宿舍三个人闲聊的时候发现我们三个人的GPA都没变,排名也没有变,就怀疑是GPA始终没有刷新,我的两个室友就开始用自己的方法把GPA重算了一遍(好像用的是Excel),结果是GPA确实没有变,而且SEP网站也确实是刷新了。我自己也是学了一个假期的JS,正好用这个机会练练手,写个脚本帮着自动计算一下GPA。 6 | 7 | ## 脚本受众 8 | 9 | 比较关心自己的GPA和成绩,且无法忍受SEP长期不刷新GPA的UCAS**本科生**, 10 | 11 | ## 脚本功能: 12 | 13 | * 实时计算GPA(包括每个特定学期和全部学期) 14 | * 实时计算加权平均分(包括每个特定学期和全部学期) 15 | 16 | * 局限:无法实时刷新自己的GPA排名(不黑学校服务器,我怎么可能知道别人的成绩来给你刷新排名?) 17 | 18 | 当浏览器打开所有成绩页面时,显示的是全部学期的GPA和加权平均分;当浏览器打开某个学期的成绩页面时,显示的是当前学期的GPA和加权平均分。 19 | 20 | ## 使用方法 21 | 22 | 脚本需要挂在在**油猴脚本(Tampermonkey)插件**上才能正常运行。 23 | 24 | 浏览器插件油猴脚本的安装教程参见[这里](https://zhuanlan.zhihu.com/p/387251122) 25 | 26 | 注:不推荐使用Chrome、Edge、Firefox之外的浏览器运行该脚本。 27 | 28 | 安装好之后,点击目录中的`gpa_calc.js`,便可看到全部代码。在油猴脚本插件的选项中找到新添加脚本,将默认脚本内容删除后,将文件`gpa_calc.js`中的**所有代码**(注意是所有!包含注释!)复制到网页代码编辑器中,按`Ctrl+S`保存即可。 29 | 30 | 再次打开SEP的成绩查询页面后,会发现GPA一栏多出`(实时)`字样。 31 | 32 | 如果在使用过程中遇到问题,可以使用Google或Baidu搜索相关问题。 33 | 34 | ## 更新 35 | 36 | * 2022.9.5:由于学校课程网站更新,未评估的课程成绩一栏显示为空,导致不能正常计算绩点,显示NaN,目前该bug已经修复。 37 | * 2023.1.20:设置小于60分的分数的GPA为0;将GPA显示的位数从2变为3. 38 | 39 | ## 改进 40 | 41 | 如果您发现脚本存在bug或者您有对脚本更好的改进意见,请联系`anwentao1@gmail.com`。 42 | 43 | 如果您对脚本还算满意,请帮我点亮一颗star。 -------------------------------------------------------------------------------- /gpa_calc.js: -------------------------------------------------------------------------------- 1 | // ==UserScript== 2 | // @name Real Time GPA Calculator UCAS 3 | // @namespace https://github.com/TimeSea05/gpa-calc-ucas 4 | // @version 0.2 5 | // @description calculate your gpa in real time 6 | // @author Avalanche 7 | // @match https://xkcts.ucas.ac.cn/score/bks/* 8 | // @icon data:image/gif;base64,R0lGODlhAQABAAAAACH5BAEKAAEALAAAAAABAAEAAAICTAEAOw== 9 | // @grant none 10 | // ==/UserScript== 11 | 12 | (function() { 13 | 'use strict'; 14 | const userInfoTable = document.querySelectorAll('table')[0]; 15 | const scoreTable = document.querySelectorAll('table')[1]; 16 | 17 | let totalCredits = 0, totalScore = 0, totalGradePoints = 0; 18 | let gradePointAverage = 0, scoreAverage = 0; 19 | 20 | function getGradePoint(score) { 21 | // 分数和GPA的对应表 22 | const scoreGPAObj = { 23 | 90: 4.0, 89: 3.9, 88: 3.9, 87: 3.9, 86: 3.8, 24 | 85: 3.8, 84: 3.7, 83: 3.7, 82: 3.6, 81: 3.5, 25 | 80: 3.5, 79: 3.4, 78: 3.4, 77: 3.3, 76: 3.3, 26 | 75: 3.2, 74: 3.1, 73: 3.0, 72: 2.9, 71: 2.8, 27 | 70: 2.7, 69: 2.7, 68: 2.6, 67: 2.5, 66: 2.4, 28 | 65: 2.3, 64: 2.3, 63: 2.2, 62: 2.1, 61: 1.8, 29 | 60: 1.6 30 | }; 31 | 32 | if (score >= 90) return scoreGPAObj[90]; 33 | else if (score >= 60 && score < 90) return scoreGPAObj[score]; 34 | else return 0; 35 | } 36 | 37 | for (let i = 1; i < scoreTable.rows.length; i++) { 38 | // 第一行是表头, 跳过 39 | // 在每一行中, 表格的第四列和第五列分别是学分和成绩 40 | 41 | const credit = Number(scoreTable.rows[i].cells[3].innerHTML); 42 | const scoreString = scoreTable.rows[i].cells[4].innerHTML; 43 | const score = Number(scoreString); 44 | 45 | // 如果分数一栏是"合格", "不合格"等非数字字样,那么跳过 46 | // 课程未评估,分数一栏显示未空,同样也跳过 47 | if (scoreString === '' || Number.isNaN(score)) continue; 48 | 49 | totalCredits += credit; 50 | totalScore += credit * score; 51 | totalGradePoints += credit * getGradePoint(score); 52 | } 53 | 54 | if (totalScore === 0) { 55 | const courseResult = document.querySelectorAll('h5')[document.querySelectorAll('h5').length - 1]; 56 | courseResult.innerHTML += '(脚本未生效)'; 57 | return; 58 | } 59 | 60 | gradePointAverage = (totalGradePoints / totalCredits).toFixed(3); 61 | scoreAverage = (totalScore / totalCredits).toFixed(2); 62 | 63 | const currentURL = document.URL; 64 | let gpaProp = null; 65 | if (currentURL.includes('all')) gpaProp = '所有学期'; 66 | else gpaProp = '当前学期'; 67 | 68 | // 更改个人信息栏中的GPA等信息 69 | userInfoTable.rows[2].cells[0].innerHTML = gpaProp + `GPA(实时): ${gradePointAverage}`; 70 | userInfoTable.rows[2].cells[1].innerHTML += '(非实时)'; 71 | 72 | // 增加平均分信息 73 | const tr = document.createElement('tr'); 74 | const gradePointAverageTd = document.createElement('td'); 75 | gradePointAverageTd.innerHTML = `加权平均分(实时): ${scoreAverage}`; 76 | tr.append(gradePointAverageTd); 77 | tr.append(document.createElement('td')); // 添加空栏 78 | userInfoTable.append(tr); 79 | })(); 80 | --------------------------------------------------------------------------------