您需要先安装一个扩展,例如 篡改猴、Greasemonkey 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 Userscripts ,之后才能安装此脚本。
您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey,才能安装此脚本。
您需要先安装用户脚本管理器扩展后才能安装此脚本。
gym做题信息统计
当前为
- // ==UserScript==
- // @name Codeforces Gym Statistic
- // @namespace http://tampermonkey.net/
- // @version 1.0
- // @description gym做题信息统计
- // @author Tanphoon
- // @match https://codeforces.com/*
- // @icon https://www.google.com/s2/favicons?sz=64&domain=codeforces.com
- // @grant none
- // @license MIT
- // ==/UserScript==
- (function () {
- 'use strict';
- const pathname = window.location.pathname;
- console.log(pathname);
- if (pathname.startsWith("/contests/with/")) {
- gymAnalyze();
- }
- function gymAnalyze() {
- const handle = pathname.substring(pathname.lastIndexOf('/') + 1, pathname.length);
- // 定义请求的URL
- const userDataUrl = `https://codeforces.com/api/user.status?handle=${handle}`;
- const contestListUrl = 'https://codeforces.com/api/contest.list?gym=true';
- // 使用fetch函数获取JSON数据,并将其转换为JSON对象
- async function fetchData(url) {
- try {
- const response = await fetch(url);
- if (!response.ok) {
- throw new Error(`HTTP error! status: ${response.status}`);
- }
- return response.json();
- } catch (error) {
- console.error(`Fetch error for ${url}: `, error);
- throw error;
- }
- };
- async function getContestData() {
- const today = new Date().toLocaleDateString();
- // 比赛信息
- let contestData = {};
- if (!localStorage.getItem("ContestDataVersion") || localStorage.getItem("ContestDataVersion") != today) {
- try {
- const contestList = await fetchData(contestListUrl);
- contestList.result.forEach(item => {
- contestData[item.id] = item.name;
- });
- localStorage.setItem("ContestDataVersion", today);
- localStorage.setItem("ContestData", JSON.stringify(contestData));
- } catch (error) {
- console.error("An error occurred while fetching data:", error);
- }
- } else {
- contestData = JSON.parse(localStorage.getItem("ContestData"));
- }
- return contestData;
- }
- async function main() {
- const contestData = await getContestData();
- const userData = await fetchData(userDataUrl);
- let data = {};
- userData.result.forEach(item => {
- // 提取所需字段
- const commitId = item.id;
- const contestId = item.contestId;
- const time = new Date(item.creationTimeSeconds * 1000).toLocaleString();
- const verdict = item.verdict;
- const problemId = item.problem.index;
- if (contestId > 100000) {
- if (!data[contestId]) {
- data[contestId] = { 'name': contestData[contestId], 'correct': [], 'problem': {}, };
- }
- // 通过的题目
- if (verdict == "OK" && !data[contestId]['correct'].includes(problemId))
- data[contestId]['correct'].push(problemId);
- // 题目提交信息
- if (!data[contestId]['problem'][problemId]) {
- data[contestId]['problem'][problemId] = [];
- }
- data[contestId]['problem'][problemId].push({ commitId, time, verdict });
- }
- });
- // 用户信息
- drawTable(data);
- console.log(data);
- }
- function drawTable(data) {
- const facebox = document.createElement('style');
- facebox.textContent = `
- .popup {
- display: none;
- position: fixed;
- z-index: 99;
- left: 0;
- top: 0;
- width: 100%;
- height: 100%;
- overflow: auto;
- background-color: rgba(0, 0, 0, 0.4);
- }
- .popup-content {
- background-color: #fefefe;
- position: fixed;
- top: 50%;
- left: 50%;
- transform: translate(-50%, -50%);
- padding: 10px;
- width: 50%;
- border-radius: 5px;
- }
- .close {
- color: #aaa;
- float: right;
- font-size: 28px;
- font-weight: bold;
- }
- .close:hover,
- .close:focus {
- color: black;
- text-decoration: none;
- cursor: pointer;
- }
- .content {
- border: 1px solid #888;
- padding: 20px;
- border-radius: 5px;
- }
- #gym th, td {
- cursor: pointer;
- }
- `;
- document.head.appendChild(facebox);
- let datatable = `
- <div id="gyms" class="datatable" style="background-color: #E1E1E1; padding-bottom: 3px;">
- <div class="lt"> </div>
- <div class="rt"> </div>
- <div class="lb"> </div>
- <div class="lb"> </div>
- <div style="padding: 4px 0 0 6px;font-size:1.4rem;position:relative;">Gyms</div>
- <div style="background-color: white;margin:0.3em 3px 0 3px;position:relative;">
- <div class="ilt"> </div>
- <div class="irt"> </div>
- <table class="tablesorter user-contests-table">
- <thead>
- <tr>
- <th class="top left">#</th>
- <th class="top">Contest</th>
- ${Array.from("ABCDEFGHIJKLM").map(problemId => `<th class="top">${problemId}</th>`).join('')}
- <th class="top right">Solved</th>
- </tr>
- </thead>
- <tbody>
- ${Object.keys(data).map((contestId, index) => `
- <tr>
- <td>${index + 1}</td>
- <td><a href="/gym/${contestId}">${data[contestId]['name']}</a></td>
- ${Array.from("ABCDEFGHIJKLM").map(problemId => {
- const correct = data[contestId]['correct'].includes(problemId);
- const style = correct ? "font-weight: bold;color:#0a0" : "color:#00a";
- if (data[contestId]['problem'][problemId]) {
- return `
- <td style="${style}" problemid=${problemId}>
- ${correct ? '+' : '-'}${data[contestId]['problem'][problemId].length}
- </td>`;
- }
- else {
- return `<td problemid=${problemId}></td>`;
- }
- }).join('')}
- <td>${Object.keys(data[contestId]['problem']).length}</td>
- </tr>
- `).join('')}
- </tbody>
- </table>
- </div>
- </div>
- `;
- let contests = document.querySelector("#pageContent > .datatable");
- contests.insertAdjacentHTML("afterend", datatable);
- let gyms = document.querySelector("#pageContent > #gyms");
- contests.style.display = 'block';
- gyms.style.display = 'none';
- document.querySelector("#pageContent > div.second-level-menu > ul > li.current.selectedLava").insertAdjacentHTML("afterend", "<li><a id='toggleButton' style='cursor: pointer;'>SWITCH TO GYMS</a></li>")
- const toggleButton = document.getElementById('toggleButton');
- toggleButton.addEventListener('click', () => {
- if (contests.style.display === 'none') {
- contests.style.display = 'block';
- gyms.style.display = 'none';
- toggleButton.textContent = 'SWITCH TO GYMS';
- } else {
- contests.style.display = 'none';
- gyms.style.display = 'block';
- toggleButton.textContent = 'SWITCH TO COMTESTS';
- }
- });
- let popdiv = `
- <div id="mypopup" class="popup">
- <div class="popup-content">
- <span class="close">×</span>
- <div class="content" id="popupMessage">
- <h2>This is the popup content</h2>
- <p>You can add any content inside the popup.</p>
- </div>
- </div>
- </div>
- `;
- gyms.insertAdjacentHTML('afterend', popdiv);
- const table = document.getElementById("gyms");
- const popup = document.getElementById("mypopup");
- const closeBtn = document.querySelector(".close");
- const popupMessage = document.getElementById("popupMessage");
- const columnNames = Array.from(table.getElementsByTagName("th")).map(th => th.textContent);
- table.addEventListener("click", (event) => {
- const cell = event.target.closest("td");
- if (cell) {
- const contestId = Object.keys(data)[cell.parentNode.rowIndex - 1];
- const problemId = cell.getAttribute('problemid');
- const commitInfos = data[contestId]['problem'][problemId];
- if (commitInfos) {
- popupMessage.innerHTML = commitInfos.map(item => `
- ${item.time}
-
- <span style="${item.verdict == "OK" ? "font-weight: bold;color:#0a0" : "color:#00a"}">${item.verdict == "OK" ? "Accepted" : item.verdict.replace("/^\w/", (match) => match.toUpperCase())}</span>
- →
- <a href=https://cf.dianhsu.com/gym/${contestId}/submission/${item.commitId} target="_blank">${item.commitId}</a><br>
- `).join('');
- popup.style.display = "block";
- }
- }
- });
- closeBtn.addEventListener("click", () => {
- popup.style.display = "none";
- });
- popup.addEventListener("click", (event) => {
- if (event.target === popup) {
- popup.style.display = "none";
- }
- });
- }
- main();
- }
- })();
QingJ © 2025
镜像随时可能失效,请加Q群300939539或关注我们的公众号极客氢云获取最新地址