CF-problem-score-table

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

Terá de instalar uma extensão como Tampermonkey, Greasemonkey ou Violentmonkey para instalar este script.

You will need to install an extension such as Tampermonkey or Violentmonkey to install this script.

Terá de instalar uma extensão como Tampermonkey ou Violentmonkey para instalar este script.

Terá de instalar uma extensão como Tampermonkey ou Userscripts para instalar este script.

Terá de instalar uma extensão como Tampermonkey para instalar este script.

Terá de instalar uma extensão de gestão de scripts de utilizador para instalar este script.

(Já tenho um gestor de scripts de utilizador, deixe-me instalá-lo!)

Terá de instalar uma extensão como Stylus para instalar este estilo.

Terá de instalar uma extensão como Stylus para instalar este estilo.

Terá de instalar uma extensão como Stylus para instalar este estilo.

Terá de instalar uma extensão de gestão de estilos de utilizador para instalar este estilo.

Terá de instalar uma extensão de gestão de estilos de utilizador para instalar este estilo.

Terá de instalar uma extensão de gestão de estilos de utilizador para instalar este estilo.

(Já tenho um gestor de estilos de utilizador, deixe-me instalá-lo!)

// ==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>
		`)

})()