您需要先安装一个扩展,例如 篡改猴、Greasemonkey 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 Userscripts ,之后才能安装此脚本。
您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey,才能安装此脚本。
您需要先安装用户脚本管理器扩展后才能安装此脚本。
display AC count
// ==UserScript== // @name CodeForces-显示AC数 // @namespace http://tampermonkey.net/ // @version 2024-05-10 // @description display AC count // @author Qianfan // @match https://codeforces.com/profile/* // @icon https://www.google.com/s2/favicons?sz=64&domain=codeforces.com // @run-at document-end // @grant GM_addStyle // ==/UserScript== (async function() { 'use strict'; //注入css GM_addStyle(` .dropbtn { background-color: #4CAF50; color: white; padding: 10px; min-width: 100px; font-size: 14px; border: none; cursor: pointer; border-radius: 5px; } .dropbtn.loading { background-color: #c7a233; } .dropdown { position: relative; display: inline-block; } .dropdown-content { border-radius: 5px; transform-origin: center top; transform: scaleY(0); transition: transform 0.4s ease; position: absolute; background-color: #f9f9f9; min-width: 150px; box-shadow: 0px 8px 16px 0px rgba(0, 0, 0, 0.2); } .dropdown-content a { color: black; padding: 12px 16px; text-decoration: none; display: block; cursor: pointer; } .dropdown-content a:last-child { color: red; } .dropdown-content a:hover { background-color: #f1f1f1 } .dropdown:hover .dropdown-content { transform: scaleY(1); } `) //重要变量 const earliest = document.querySelector('rect').dataset.date let endDate = earliest, topMap const activeGraph = document.querySelector('div#userActivityGraph') const months = { 'Jan': '01', 'Feb': '02', 'Mar': '03', 'Apr': '04', 'May': '05', 'Jun': '06', 'Jul': '07', 'Aug': '08', 'Sep': '09', 'Oct': '10', 'Nov': '11', 'Dec': '12' }, dateRegex = /([A-Z][a-z][a-z])/ const domParser = new DOMParser() let stroageKey = '__CHONGTIAN_codeforces_daily_ac_v2_' const filePaths = window.location.pathname.split('/'), username = filePaths[filePaths.length - 1] , URL = `https://codeforces.com/submissions/${username}/page` stroageKey += username let topMapStr = localStorage.getItem(stroageKey) const dropDown = document.createElement('div'), box = document.querySelector('div.roundbox.userActivityRoundBox.borderTopRound.borderBottomRound') // dropDown.innerHTML = `<div class="dropdown"> <button class="dropbtn">完成!</button> <div class="dropdown-content"> <a class="render">渲染</a> <a class="refresh">刷新最近数据</a> <a class="refresh-all">刷新全部数据</a> </div> </div>` box.insertBefore(dropDown, box.firstChild) const realDropDown = dropDown.querySelector('div.dropdown'), dropbtn = dropDown.querySelector('button.dropbtn') dropDown.querySelector('.dropdown-content a.render').addEventListener('click', f => render()) dropDown.querySelector('.dropdown-content a.refresh').addEventListener('click', async f => await fetchData() ) dropDown.querySelector('.dropdown-content a.refresh-all').addEventListener('click', async f => { if (confirm('确定要刷新全部数据吗?')) await fetchData(earliest) } ) // const convertDate = date => date.replace(dateRegex, (match, p1) => months[p1]) const aLaterOrEquals = (a, b) => { const aArr = a.split('/'), bArr = b.split('/'); if (aArr[2] !== bArr[2]) return aArr[2] > bArr[2] if (aArr[0] !== bArr[0]) return aArr[0] > bArr[0] return aArr[1] >= bArr[1] } const solveDoc = (html, map, endDate2, getTot = false) => { const doc = domParser.parseFromString(html, 'text/html'), submissions = doc.querySelectorAll('tr[data-submission-id]') let tot = void 0, flag = false, latest = void 0 if (getTot) { const lis = doc.querySelectorAll('div.pagination ul li') tot = parseInt(lis[lis.length - 2].innerText) } for (const elem of submissions) { if (!elem.querySelector('span.verdict-accepted')) continue const date = convertDate(elem.querySelector('span.format-time').innerText.split(' ')[0]) if (!latest) latest = date if (!aLaterOrEquals(date, endDate2)) { flag = true break } if (!map[date]) map[date] = new Set() map[date].add(parseInt(elem.querySelector('td[data-problemid]').dataset.problemid)) } return { tot, flag, latest } } const render = f => { if (!activeGraph) return for (const key in topMap) { const rect = activeGraph.querySelector(`rect[data-date="${key}"]:not([fill="#EBEDF0"])`) if (!rect) continue rect.dataset.date = `${rect.dataset.date},Accept ${topMap[key]}` } } const fetchData = async endDate1 => { dropbtn.classList.toggle('loading') dropbtn.innerHTML = '获取数据...' const dataMap = {} if (topMapStr) { topMap = JSON.parse(topMapStr) endDate = topMap.latest } endDate1 = endDate1 ?? endDate const res = await fetch(`${URL}/1`) const html = await res.text() let { flag, tot, latest } = solveDoc(html, dataMap, endDate1, true) for (let page = 2; page <= tot && !flag; ++page) { const res = await fetch(`${URL}/${page}`) const html = await res.text() flag = solveDoc(html, dataMap, endDate1).flag } for (const k in dataMap) dataMap[k] = dataMap[k].size topMap = { ...topMap, ...dataMap, latest, } dropbtn.innerHTML = '完成!' dropbtn.classList.toggle('loading') } //main await fetchData() topMapStr = JSON.stringify(topMap) localStorage.setItem(stroageKey, topMapStr) render() })();
QingJ © 2025
镜像随时可能失效,请加Q群300939539或关注我们的公众号极客氢云获取最新地址