CF-problem-score-table

Add the "score table" to Codeforces in practice/virtual contest

Dovrai installare un'estensione come Tampermonkey, Greasemonkey o Violentmonkey per installare questo script.

Dovrai installare un'estensione come Tampermonkey o Violentmonkey per installare questo script.

Dovrai installare un'estensione come Tampermonkey o Violentmonkey per installare questo script.

Dovrai installare un'estensione come Tampermonkey o Userscripts per installare questo script.

Dovrai installare un'estensione come ad esempio Tampermonkey per installare questo script.

Dovrai installare un gestore di script utente per installare questo script.

(Ho già un gestore di script utente, lasciamelo installare!)

Dovrai installare un'estensione come ad esempio Stylus per installare questo stile.

Dovrai installare un'estensione come ad esempio Stylus per installare questo stile.

Dovrai installare un'estensione come ad esempio Stylus per installare questo stile.

Dovrai installare un'estensione per la gestione degli stili utente per installare questo stile.

Dovrai installare un'estensione per la gestione degli stili utente per installare questo stile.

Dovrai installare un'estensione per la gestione degli stili utente per installare questo stile.

(Ho già un gestore di stile utente, lasciamelo installare!)

// ==UserScript==
// @name         CF-problem-score-table
// @version      0.0.1
// @description  Add the "score table" to Codeforces in practice/virtual contest
// @match        *://codeforces.com/contest/*
// @grant        GM_getValue
// @grant        GM_setValue
// @namespace    https://greasyfork.org/users/410786
// ==/UserScript==


(async function(){
	const contestId=location.pathname.match('^/contest/(\\d+)')[1]
	let problems

	// stored value: [] for educational rounds, list of [index, points] otherwise
	if(GM_getValue('problem_score_'+contestId)!==undefined){
		problems=JSON.parse(GM_getValue('problem_score_'+contestId))
		if(problems.length>0&&problems[0][1]===null){ // fix a bug in previous version
			problems=[]
			GM_setValue('problem_score_'+contestId,JSON.stringify(problems))
		}
	}else{
		const data=await $.get(`/api/contest.standings?contestId=${contestId}&from=1&count=1`)
		if(data.status!=='OK'){
			console.log('Failed: ',data)
			return
		}
		problems=[]
		for(let problem of data.result.problems){
			if(!('points' in problem)){ // educational contest
				break
			}
			problems.push([problem.index,problem.points])
		}
		problems.sort()
		GM_setValue('problem_score_'+contestId,JSON.stringify(problems))
	}
	if(problems.length==0)
		return

	//let lastDark=problems.length%2!=0 // more consistent with Codeforces (according to
	// http://web.archive.org/web/20160123153752/http://codeforces.com/contest/617), but is not as beautiful
	// because the header row is light.

	let lastDark=false

	function lastDarkState(){
		return lastDark?'dark':''
	}
	function nextDarkState(){
		lastDark=!lastDark
		return lastDarkState()
	}

	// Thanks to the Internet Archive, I could get the "score table" HTML source without waiting for a real
	// contest. I just go to http://web.archive.org/web/*/https://codeforces.com/contest/*, then filter by
	// 'contest/' and sort by unique.
	// The page with the maximum unique count must have the score table.
	//
	// Taken from page: http://web.archive.org/web/20151230151115/http://codeforces.com/contest/611
	// (or http://web.archive.org/web/20160123153752/http://codeforces.com/contest/617 for Russian version)
	//
	// Currently only English is supported, but it's trivial to add the Russian version.

	let problemsHTML=String.raw`
		<div class="roundbox sidebox" style="">
			<div class="roundbox-lt">&nbsp;</div>
			<div class="roundbox-rt">&nbsp;</div>
			<div class="caption titled">→ Score table
				<div class="top-links">
				</div>
			</div>
			<table class="rtable ">
				<tbody>
					<tr>
								<th class="left" style="width:100%;"></th>
								<th class="" style="width:8em;">Score</th>
					</tr>
		`
	for(let [index,score] of problems){
		problemsHTML+=String.raw`
					<tr>
								<td class="left ${nextDarkState()}"><a href="/contest/${contestId}/problem/${index}">Problem ${index}</a></td>
								<td class=" ${lastDarkState()}">${score}</td>
					</tr>
		`
	}

	problemsHTML+=String.raw`
					<tr>
								<td class="left  ${nextDarkState()}"><span style="color:green;">Successful hack</span></td>
								<td class=" ${lastDarkState()}">100</td>
					</tr>
					<tr>
								<td class="left ${nextDarkState()}"><span style="color:red;">Unsuccessful hack</span></td>
								<td class="${lastDarkState()}">-50</td>
					</tr>
					<tr>
								<td class="left ${nextDarkState()}"><span style="color:black;">Unsuccessful submission</span></td>
								<td class="${lastDarkState()}">-50</td>
					</tr>
					<tr>
								<td class="left bottom ${nextDarkState()}"><span style="color:black;">Resubmission</span></td>
								<td class="bottom ${lastDarkState()}">-50</td>
					</tr>
				</tbody>
			</table>
		</div>
		`

	$('#sidebar').append(problemsHTML)
	$('#sidebar').append(String.raw`
		<div style="text-align:right; position:relative;bottom:1.75em;">
			<span class="small" style="color:gray;">* If you solve problem on 00:00 from the first attempt</span>
		</div>
		`)

})()