您需要先安装一个扩展,例如 篡改猴、Greasemonkey 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 Userscripts ,之后才能安装此脚本。
您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey,才能安装此脚本。
您需要先安装用户脚本管理器扩展后才能安装此脚本。
Precisly determine and control the time you can miss.
当前为
// ==UserScript== // @name IVE Att & Abs Calculator // @namespace https://ive.miklet.tk // @version 3.0.0 // @description Precisly determine and control the time you can miss. // @author Miklet // @license MIT // @match *://myportal.vtc.edu.hk/* // @match *://ive.miklet.tk/* // @require https://code.jquery.com/jquery-latest.js // @grant GM_setValue // @grant GM_getValue // @grant GM_registerMenuCommand // @grant GM_xmlhttpRequest // @grant GM_info // @grant unsafeWindow // @supportURL https://ive.miklet.tk/document // @run-at document-end // ==/UserScript== /* global $ */ // Declare gloval variable var data, db_data = null, c_id, c_name, ini = false; // Declarea element variable var calc_btn, sbj_info_div, sbj_info, sbj_edit_time_btn, toggle_btn, sbj_dashboard_div, sbj_dashboard, sbj_select_btn; // Unit of Time const u_hour = 'hr', u_minute = 'min', version = GM_info.script.version; // Run the nessesary function for userscript function initialize() { varUpdate(); addToolbarCommand(); createElement(); GM_info.scriptHandler !== 'Violentmonkey' ? window.alert('WARNING! Since the version 3.0 of IVE att & abs calculator was require Violentmonkey! And your userscript manager was not Violentmonkey.This may cause the userscript not working properly.') : ''; } // Update userscript data variable function varUpdate() { data = GM_getValue(getStuId()) ? JSON.parse(GM_getValue(getStuId())) : setDefault(); } // Get student ID number function getStuId() { return wptheme_QuickLinksShelf.cookieName.substring(0, 9); } function addToolbarCommand() { if (!data.secret) { GM_registerMenuCommand('綁定帳戶', function() { bindAccount(); }); } GM_registerMenuCommand('重設報告表', function() { resetDashboard(); }); GM_registerMenuCommand('重設全部', function() { resetAll(); }); } // Set default value for first use or reset function setDefault() { data = templateData(); dataUpdate(data); return data; } // Only reset dashboard function resetDashboard() { data.dashboard = {}; dataUpdate(data); dashboard(); } // Reset Everything // Reset Everything // Reset Everything function resetAll() { if (window.confirm("確認重設全部資料?這會刪除所有本地數據,包括在網站中已存儲的數據(如果您已鏈結帳戶)")) { if (window.prompt("請輸入您的學生證號碼以便進一步確認。") === data.sys_stu_id) { setDefault(); window.alert("重設完成!請刷新頁面!"); } else { window.alert("學生證號碼錯誤!"); } } } // Reset Everything // Reset Everything // Reset Everything // Update local storage(Set the data to local) function dataUpdate(data) { updateData_db(); GM_setValue(getStuId(), JSON.stringify(data)); varUpdate(); } // Create theobject for new subject function sbjCreate(t_hours) { data.sbj[c_id] = { id: c_id, name: c_name, t_hours: t_hours, att: 0, att_p: 0, abs: 0, abs_p: 0, avg_att: 0, remain: 0, updated_time: Date.now() }; } function time_convert(input_min) { var output_hr = Math.round(Math.floor(input_min / 60)); var output_min = Math.round(input_min % 60); return output_min !== 0 ? output_hr + u_hour + output_min + u_minute : output_hr + u_hour; } // For trturn a template data function templateData(stu_id = null, secret = null, sync_time = 0) { if (data && data.secret) { stu_id = data.stu_id; secret = data.secret; } return { sys_stu_id: getStuId(), stu_id: stu_id, secret: secret, version: version, sbj: {}, dashboard: {}, sync_time: sync_time }; } //=========================================================== Account ================================================================================= // Gather user information function bindAccount() { let u_secret = window.prompt('請輸入密鑰(secret key)'); if (u_secret) { let u_stu_id = window.prompt('請輸入您的學生證號碼'); if (u_stu_id === getStuId()) { dataCombine(u_stu_id, u_secret); } else { window.alert('學生證號碼不正確!'); } } } //Combine user data with db and local function dataCombine(stu_id, secret) { data.stu_id = stu_id; data.secret = secret; dataUpdate(data); getData_db(function() { if (db_data) { if (window.confirm('現在,我們將會把本地和網站的數據結合,並創建同步鏈結,確定繼續?(較新的數據將會覆蓋較舊的數據)')) { let dashboard_num = window.prompt('請選擇您要處理報告表的方式?(請輸入數字)\n1. 本地覆蓋到網站\n2. 網站覆蓋到本地'); let l_data = data; let n_data = templateData(stu_id, secret, Date.now()); // Handle the dashboard data if (dashboard_num === '1') { n_data.dashboard = l_data.dashboard; } else if (dashboard_num === '2') { n_data.dashboard = db_data.dashboard; } else { window.alert('選擇錯誤!'); return; } // Select the newsest subject for (let l_row in l_data.sbj) { if (db_data.sbj[l_row] !== undefined) { if (l_data.sbj[l_row].updated_time > db_data.sbj[l_row].updated_time) { n_data.sbj[l_row] = l_data.sbj[l_row]; } else { n_data.sbj[l_row] = db_data.sbj[l_row]; } } else { n_data.sbj[l_row] = l_data.sbj[l_row]; } } for (let db_row in db_data.sbj) { if (l_data.sbj[db_row] !== undefined) { if (db_data.sbj[db_row].updated_time > l_data.sbj[db_row].updated_time) { n_data.sbj[db_row] = db_data.sbj[db_row]; } else { n_data.sbj[db_row] = l_data.sbj[db_row]; } } else { n_data.sbj[db_row] = db_data.sbj[db_row]; } } dataUpdate(n_data); varUpdate(); window.alert('已經成功同步鏈結!請刷新頁面!'); } } else { window.alert('已經成功同步鏈結!請刷新頁面!'); } }); } //Vertify the user information with the db function getData_db(callback, stu_id = data.stu_id, secret = data.secret) { if (data.secret) { try { GM_xmlhttpRequest({ method: 'POST', synchronous: false, data: $.param({ stu_id: stu_id, secret: secret }), headers: { 'Content-Type': 'application/x-www-form-urlencoded' }, url: 'http://ive.miklet.tk/ajax/get', onload: function(res) { let row = JSON.parse(res.responseText); if (row.status) { db_data = row.data; callback(row.data); } else { console.error('資料不正確,請重試!(Get DB data incorrect! Error301)'); } }, onerror: function() { console.error('** An error occurred during the transaction'); } }); } catch (err) { console.error(err); } } } function updateData_db() { if (data.secret) { try { data.sync_time = Date.now(); GM_xmlhttpRequest({ method: 'POST', synchronous: false, data: $.param({ stu_id: data.stu_id, secret: data.secret, data: data }), headers: { 'Content-Type': 'application/x-www-form-urlencoded' }, url: 'http://ive.miklet.tk/ajax/update', onload: function(res) { let row = JSON.parse(res.responseText); console.log(row.status ? 'Row update success' : 'Update fail. Error302'); }, onerror: function() { console.error('** An error occurred during the transaction'); } }); } catch (err) { console.error(err); } } } function db_sync_chk() { if (data.secret) { getData_db(function() { if (parseInt(db_data.sync_time, 10) > data.sync_time) { data = db_data; dataUpdate(data); } }); } } //=========================================================== End Account ================================================================================= // Create element function createElement() { //calc button if no total hours set calc_btn = document.createElement("button"); calc_btn.setAttribute("style", "width:100%;padding:10px;background-color:#555;color:#fff;border:0;line-height:14px;font-size:13px;"); calc_btn.setAttribute("id", "calcBtn"); calc_btn.innerHTML = "計算出缺率"; //Info, edit time button, and toggle button sbj_info_div = document.createElement("div"); sbj_info_div.setAttribute("style", "width:12vw;position:fixed;right:0;bottom:0;border:0;font-family:'Microsoft jhenghei';z-index:999"); sbj_info_div.setAttribute("id", "sbjDiv"); sbj_info = document.createElement("p"); sbj_info.setAttribute("style", "margin:0;width:100%;background-color:#555;color:#fff;border:0;border-bottom:1px solid #fff;line-height:14px;font-size:13px;"); sbj_info.setAttribute("id", "sbjInfo"); sbj_edit_time_btn = document.createElement("button"); sbj_edit_time_btn.setAttribute("style", "width:85%;padding:10px;background-color:#555;color:#fff;border:0;line-height:14px;font-size:13px;"); sbj_edit_time_btn.setAttribute("id", "editTimeBtn"); sbj_edit_time_btn.innerHTML = "編輯總時數"; toggle_btn = document.createElement("button"); toggle_btn.setAttribute("style", "width:15%;padding:10px;background-color:#555;color:#fff;border:0;line-height:14px;font-size:13px;"); toggle_btn.setAttribute("id", "btnToggle"); toggle_btn.innerHTML = "-"; //Dashboard sbj_dashboard_div = document.createElement("div"); sbj_dashboard_div.setAttribute("style", "min-width:24vw;position:fixed;left:0;bottom:0;border:0;font-family:'Microsoft jhenghei';z-index:999"); sbj_dashboard_div.setAttribute("id", "sbjDashboardDiv"); sbj_dashboard = document.createElement("table"); sbj_dashboard.setAttribute("style", "width:100%;padding:10px;background-color:#555;color:#fff;border:0;line-height:14px;font-size:13px;"); sbj_dashboard.setAttribute("id", "sbjDashboard"); sbj_select_btn = document.createElement("button"); sbj_select_btn.setAttribute("id", "sbjSelectBtn"); sbj_select_btn.setAttribute("style", "width:100%;padding:10px;background-color:#555;color:#fff;border:0;line-height:14px;font-size:13px;border-top: 1px solid #fff;"); } // =================================================================== Event Listener Function =================================================================== // //Update the subject hours function sbjHoursUpdate_Click() { $("#editTimeBtn").click(function() { let t_hours = window.prompt("編輯該單元的總時數", data.sbj[c_id].t_hours); if (t_hours !== "" && t_hours == parseInt(t_hours, 10)) { data.sbj[c_id].t_hours = t_hours; dataUpdate(data); sbj_chk(); } else { window.alert('發生錯誤。Error201'); } }); } //Ask the user to input the total hours of this subject function sbjInputHours_Click() { $("#calcBtn").click(function() { let t_hours = window.prompt("請輸入該單元的總時數"); if (t_hours !== "" && t_hours == parseInt(t_hours, 10)) { sbjCreate(t_hours); sbj_chk(); } else { window.alert('發生錯誤。Error202'); } }); } //Function for toggle button function calcToggle() { $("#btnToggle").click(function() { //$('#btnToggle').html(this.html == "+" ? "-" : "+"); $("#sbjInfo").slideToggle(); $("#sbjDashboardDiv").slideToggle(); document.getElementById("btnToggle").innerHTML = document.getElementById("btnToggle").innerHTML === "+" ? "-" : "+"; }); } // Check is Subject inside array, if NOT push array function sbjDashboardArray_Click() { $("#sbjSelectBtn").click(function() { $('#sbjSelectBtn').text(this.text == "加入" ? "清除" : "加入"); data.dashboard[c_id] ? delete data.dashboard[c_id] : data.dashboard[c_id] = c_id; dataUpdate(data); dashboard(); }); } // =================================================================== End of Event Listener Function =================================================================== // //!!!!!!!!!!!!!!!!!!!!!!!!!!! IMPORTANT FUNCTION !!!!!!!!!!!!!!!!!!!!!!!!!!!// //!!!!!!!!!!!!!!!!!!!!!!!!!!! IMPORTANT FUNCTION !!!!!!!!!!!!!!!!!!!!!!!!!!!// //!!!!!!!!!!!!!!!!!!!!!!!!!!! IMPORTANT FUNCTION !!!!!!!!!!!!!!!!!!!!!!!!!!!// //Check if the subject have record or not, if yes then append and calculate the result function sbj_chk() { if (c_id in data.sbj) { if (!ini) { $("#calcBtn").remove(); document.getElementById("sbjDiv").append(sbj_info); document.getElementById("sbjDiv").append(sbj_edit_time_btn); document.getElementById("sbjDiv").append(toggle_btn); document.getElementById("sbjDashboardDiv").append(sbj_dashboard); document.getElementById("sbjDashboardDiv").append(sbj_select_btn); sbjHoursUpdate_Click(); sbjDashboardArray_Click(); calcToggle(); ini = true; } sbj_calc(); } else { document.getElementById("sbjDiv").append(calc_btn); sbjInputHours_Click(); } } //!!!!!!!!!!!!!!!!!!!!!!!!!!! IMPORTANT FUNCTION !!!!!!!!!!!!!!!!!!!!!!!!!!!// //!!!!!!!!!!!!!!!!!!!!!!!!!!! IMPORTANT FUNCTION !!!!!!!!!!!!!!!!!!!!!!!!!!!// //!!!!!!!!!!!!!!!!!!!!!!!!!!! IMPORTANT FUNCTION !!!!!!!!!!!!!!!!!!!!!!!!!!!// //Calculate the result function sbj_calc() { //Get Table Data to Arrays let tb_array = [], headers = [], sbj_hours = data.sbj[c_id].t_hours; $('table.hkvtcsp_wording th').each(function(index, item) { headers[index] = $(item).text(); }); $('table.hkvtcsp_wording tr').has('td').each(function() { let arrayItem = {}; $('td', $(this)).each(function(index, item) { arrayItem[headers[index]] = $(item).text(); }); tb_array.push(arrayItem); }); let att_lesson = 0, abs_lesson = 0, late_lesson = 0, tt_lesson_time = 0, tt_att_time = 0, tt_abs_time = 0, att_time, abs_time, i = 0; for (i = 0; i < tb_array.length; i++) { let lesson_time_array = tb_array[i]['課堂時間'].split("-"); //Lesson Count switch (tb_array[i]['']) { case 'Present': att_lesson++; break; case 'Late': late_lesson++; break; case 'Absent': abs_lesson++; break; } //ABS & ATT Caculate var arrived_time = tb_array[i]['出席時間']; var row_lesson_time_start = new Date(); var lesson_time_array_0 = lesson_time_array[0].split(':'); row_lesson_time_start.setHours(lesson_time_array_0[0], lesson_time_array_0[1]); var row_lesson_time_end = new Date(); var lesson_time_array_1 = lesson_time_array[1].split(':'); row_lesson_time_end.setHours(lesson_time_array_1[0], lesson_time_array_1[1]); var row_lesson_time_arrived = new Date(); if (arrived_time !== '-') { arrived_time = arrived_time.split(':'); row_lesson_time_arrived.setHours(arrived_time[0], arrived_time[1]); if (row_lesson_time_arrived > row_lesson_time_start.setMinutes(row_lesson_time_start.getMinutes() + 10)) { row_lesson_time_start.setHours(lesson_time_array_0[0], lesson_time_array_0[1]); att_time = (row_lesson_time_end - row_lesson_time_arrived) / 1000 / 60; abs_time = (row_lesson_time_arrived - row_lesson_time_start) / 1000 / 60; } else { row_lesson_time_start.setHours(lesson_time_array_0[0], lesson_time_array_0[1]); att_time = (row_lesson_time_end - row_lesson_time_start) / 1000 / 60; abs_time = 0; } } else { att_time = 0; abs_time = (row_lesson_time_end - row_lesson_time_start) / 1000 / 60; } tt_lesson_time = tt_lesson_time + ((row_lesson_time_end - row_lesson_time_start) / 1000 / 60); tt_att_time = tt_att_time + att_time; tt_abs_time = tt_abs_time + abs_time; } let time_remain; if (sbj_hours * 60 * 0.3 >= tt_abs_time) { time_remain = (sbj_hours * 60 * 0.3) - tt_abs_time; time_remain = time_convert(time_remain); } else { time_remain = "-/-"; } //var sbj_array = JSON.parse(GM_getValue(sbj)); data.sbj[c_id].att = time_convert(tt_att_time); data.sbj[c_id].att_p = (tt_att_time / (sbj_hours * 60) * 100).toFixed(2) + "%"; data.sbj[c_id].abs = time_convert(tt_abs_time); data.sbj[c_id].abs_p = (tt_abs_time / (sbj_hours * 60) * 100).toFixed(2) + "%"; data.sbj[c_id].remain = time_remain; data.sbj[c_id].avg_att = (60 / (sbj_hours * 60) * 100).toFixed(2) + "%"; dataUpdate(data); let calcResult = "<p style='padding:18px 25px;margin:0;line-height:130%'><b>計算結果 :</b><br>" + "<br>總時數 : " + sbj_hours + u_hour + "\n" + "<br>已上課堂時數 : " + time_convert(tt_lesson_time) + "<br><br>總出席時數 : " + time_convert(tt_att_time) + "<br>出席率 : " + (tt_att_time / (sbj_hours * 60) * 100).toFixed(2) + "%" + "<br><br>總缺席時數 : " + time_convert(tt_abs_time) + "\n" + "<br>缺席率 : " + (tt_abs_time / (sbj_hours * 60) * 100).toFixed(2) + "%" + "<br><br>每小時缺席率 : " + (60 / (sbj_hours * 60) * 100).toFixed(2) + "%" + "<br>剩餘可缺席時數 : " + time_remain + "</p>"; document.getElementById("sbjInfo").innerHTML = calcResult; dashboard(); } //Out put the dashboard record function dashboard() { let isExist = false; if (!($.isEmptyObject(data.dashboard))) { document.getElementById("sbjDashboard").innerHTML = "<tr><td>單元</td><td>出席率</td><td>缺席率</td><td>剩餘</td></tr>"; for (let id in data.dashboard) { if (c_id === data.dashboard[id]) { isExist = true; document.getElementById("sbjDashboard").innerHTML += "<tr><td><b><i>" + data.sbj[id].name + "</i></b></td><td><b><i>" + data.sbj[id].att_p + "</i></b></td><td><b><i>" + data.sbj[id].abs_p + "</i></b></td><td><b><i>" + data.sbj[id].remain + "</i></b></td></tr>"; } else { document.getElementById("sbjDashboard").innerHTML += "<tr><td>" + data.sbj[id].name + "</td><td>" + data.sbj[id].att_p + "</i></b></td><td><b><i>" + data.sbj[id].abs_p + "</td><td>" + data.sbj[id].remain + "</td></tr>"; } } } else { document.getElementById("sbjDashboard").innerHTML = "<tr><td>單元</td><td>出席率</td><td>缺席率</td><td>剩餘</td></tr><tr><td colspan=\"4\" style=\"text-align:center\"><b><i>暫無資料</i></b></td></tr>"; } document.getElementById("sbjSelectBtn").innerHTML = isExist ? "清除" : "加入"; } (function() { if ($('table.hkvtcsp_wording').length) { initialize(); document.body.insertBefore(sbj_info_div, document.body.firstChild); document.body.insertBefore(sbj_dashboard_div, document.body.firstChild); var sbjCls = document.getElementsByClassName("hkvtcsp_textInput"); c_id = sbjCls[0].options[sbjCls[0].selectedIndex].value; c_name = sbjCls[0].options[sbjCls[0].selectedIndex].text; db_sync_chk(); sbj_chk(); } })();
QingJ © 2025
镜像随时可能失效,请加Q群300939539或关注我们的公众号极客氢云获取最新地址