Userscript to show the number of teams that have solved each problem on Universal Cup contests.
- Install Tamper Monkey as a browswer extension.
- Add the script universal_cup_enhanced.user.js to the extension.
![Screenshot 2024-06-18 at 11 59 25](https://private-user-images.githubusercontent.com/28708963/340633332-86aaa4fe-07ae-4895-b726-37e7692f09a2.png?jwt=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJnaXRodWIuY29tIiwiYXVkIjoicmF3LmdpdGh1YnVzZXJjb250ZW50LmNvbSIsImtleSI6ImtleTUiLCJleHAiOjE3MjE3NDQ0MjAsIm5iZiI6MTcyMTc0NDEyMCwicGF0aCI6Ii8yODcwODk2My8zNDA2MzMzMzItODZhYWE0ZmUtMDdhZS00ODk1LWI3MjYtMzdlNzY5MmYwOWEyLnBuZz9YLUFtei1BbGdvcml0aG09QVdTNC1ITUFDLVNIQTI1NiZYLUFtei1DcmVkZW50aWFsPUFLSUFWQ09EWUxTQTUzUFFLNFpBJTJGMjAyNDA3MjMlMkZ1cy1lYXN0LTElMkZzMyUyRmF3czRfcmVxdWVzdCZYLUFtei1EYXRlPTIwMjQwNzIzVDE0MTUyMFomWC1BbXotRXhwaXJlcz0zMDAmWC1BbXotU2lnbmF0dXJlPWM1ODE4YTQ2ZTBjMzU4NjQ4YWU0ZGRmNGIwYjMxOWViNWQ5NzIyOGY5NTk5NDg4YTgxZDU3MzlkMmQ5NTQyY2ImWC1BbXotU2lnbmVkSGVhZGVycz1ob3N0JmFjdG9yX2lkPTAma2V5X2lkPTAmcmVwb19pZD0wIn0.xWsqUFDgfeNibUAkoEWKlNuTH5FDkH69j0KZWCOijfw)
Userscript to show the number of teams that have solved each problem on Universal Cup contests.
// ==UserScript== | |
// @name Universal Cup Enhanced | |
// @namespace http://tampermonkey.net/ | |
// @version 2024-06-18 | |
// @description Provide extra information and tools for problems dashboard | |
// @author Marcelo Fornet | |
// @match https://contest.ucup.ac/contest/* | |
// @icon https://www.google.com/s2/favicons?sz=64&domain=ucup.ac | |
// @grant none | |
// ==/UserScript== | |
// https://stackoverflow.com/a/2091331/4950797 | |
function getQueryVariable(key, defaultValue) { | |
var query = window.location.search.substring(1); | |
var vars = query.split('&'); | |
for (var i = 0; i < vars.length; i++) { | |
var pair = vars[i].split('='); | |
if (decodeURIComponent(pair[0]) == key) { | |
return decodeURIComponent(pair[1]); | |
} | |
} | |
return defaultValue; | |
} | |
(function() { | |
'use strict'; | |
let currentPage = window.location.href; | |
let match = currentPage.match(/^https?:\/\/contest.ucup.ac\/contest\/\d+(\?.*)?$/); | |
if (match === null) { | |
return; | |
} | |
let sortBySolved = getQueryVariable('sortBySolved', 'True') === 'True'; | |
let qMarkIndex = currentPage.indexOf('?'); | |
if (qMarkIndex !== -1) { | |
currentPage = currentPage.slice(0, qMarkIndex); | |
} | |
fetch(currentPage + '/standings') | |
.then(data => data.text()) | |
.then(htmlString => { | |
const re = /\nscore=[^\n]*\n/ | |
let matches = htmlString.match(re); | |
let standingString = matches[0]; | |
standingString = standingString.slice(7, -2); | |
let standing = JSON.parse(standingString); | |
let problems = {}; | |
for (var team in standing) { | |
let submissions = standing[team]; | |
for (var problem in submissions) { | |
let result = submissions[problem]; | |
if (result[1] !== 0) { | |
if (problem in problems) { | |
problems[problem] = problems[problem] + 1; | |
} else { | |
problems[problem] = 1; | |
} | |
} | |
} | |
} | |
let table = document.getElementsByTagName('table')[0]; | |
let rows = table.getElementsByTagName('tr'); | |
let header = rows[0]; | |
let firstColumn = header.getElementsByTagName('th')[0]; | |
let sortById = document.createElement('a'); | |
sortById.href = currentPage + '?sortBySolved=False'; | |
sortById.textContent = '▼'; | |
firstColumn.textContent = '# '; | |
firstColumn.appendChild(sortById); | |
let th = document.createElement('th'); | |
th.textContent = 'Solved by '; | |
let sortBySolvedButton = document.createElement('a'); | |
sortBySolvedButton.href = currentPage + '?sortBySolved=True'; | |
sortBySolvedButton.textContent = '▼'; | |
th.appendChild(sortBySolvedButton); | |
header.appendChild(th); | |
let allRows = []; | |
let ix = 1; | |
while (ix < rows.length) { | |
let problemId = ix - 1; | |
let solvedBy = 0; | |
if (problemId in problems) { | |
solvedBy = problems[problemId]; | |
} | |
let td = document.createElement('td'); | |
td.textContent = solvedBy; | |
rows[ix].appendChild(td); | |
allRows.push({'row': rows[ix], solvedBy}); | |
ix += 1; | |
} | |
if (sortBySolved) { | |
while (ix > 1) { | |
ix -= 1; | |
table.deleteRow(ix); | |
} | |
let body = table.getElementsByTagName('tbody')[0]; | |
allRows.sort((a, b) => b.solvedBy - a.solvedBy); | |
for (let row of allRows) { | |
body.appendChild(row.row); | |
} | |
} | |
}); | |
})(); |