NDOJ/templates/contest/ranking.html
2022-01-10 23:50:38 +07:00

466 lines
15 KiB
HTML

{% extends "user/base-users.html" %}
{% block title_ruler %}{% endblock %}
{% block title_row %}
{% set title = contest.name %}
{% include "contest/contest-tabs.html" %}
{% endblock %}
{% block users_media %}
<style>
#content-left {
overflow-x: auto;
}
#users-table .username {
min-width: 20em;
}
#users-table td {
height: 2.5em;
}
#users-table a {
display: block;
}
.userinfo a, .user-name a, .user-name form {
display: inline !important;
}
#users-table th a, #users-table th a:link, #users-table th a:visited {
color: white;
}
#users-table th a:hover {
color: #0F0;
}
#users-table td a:hover {
text-decoration: underline;
}
.first-solve {
background: #00f9a1;
}
.rank {
min-width: 2.5em
}
.points {
min-width: 2.5em;
}
.disqualified {
background-color: #ffa8a8 !important;
}
.full-score, .full-score a {
font-weight: bold;
color: green;
}
.partial-score, .partial-score a {
color: green;
}
.failed-score, .failed-score a {
font-weight: bold;
color: red;
}
.pretest-full-score, .pretest-full-score a {
font-weight: bold;
color: #2980b9;
}
.pretest-partial-score, .pretest-partial-score a {
color: #2980b9;
}
.pretest-failed-score, .pretest-failed-score a {
font-weight: bold;
color: red;
}
.user-points {
font-weight: bold;
color: black;
}
.solving-time {
color: gray;
font-weight: normal;
font-size: 0.75em;
padding-bottom: -0.75em;
}
.point-denominator {
border-top: 1px solid gray;
font-size: 0.7em;
}
.start-time {
display: none;
}
.user-name {
position: relative;
}
.organization-column {
display: none;
text-align: left !important;
border-right: none !important;
}
.organization-column a {
color: gray !important;
font-weight: 600;
}
.fullname-column {
text-align: right !important;
border-right: none !important;
}
.fullname-column span {
color: gray !important;
font-weight: 600;
}
</style>
{% if has_rating %}
<style>#users-table .rate-box {
font-size: 0.85em;
float: left;
}
#users-table td:nth-child(1) .rating {
margin-left: 1.25em;
display: block;
}
#users-table td:nth-child(2) a {
display: block;
}
</style>
{% endif %}
<style>
.select2-selection__arrow {
display: none;
}
.select2-selection__rendered {
cursor: text;
overflow: initial !important
}
.select2-results__option--highlighted {
background-color: #DEDEDE !important;
}
.select2-results__option {
white-space: nowrap;
}
#search-contest, #search-contest + .select2 {
margin-top: 0.5em;
}
#search-contest {
width: 200px;
height: 2.3em;
}
</style>
{% endblock %}
{% block users_js_media %}
{% if can_edit %}
<script type="text/javascript">
$(function () {
$('a.disqualify-participation').click(function (e) {
e.preventDefault();
if (e.ctrlKey || e.metaKey || confirm("{{ _('Are you sure you want to disqualify this participation?') }}"))
$(this).closest('form').submit();
})
$('a.un-disqualify-participation').click(function (e) {
e.preventDefault();
if (e.ctrlKey || e.metaKey || confirm("{{ _('Are you sure you want to un-disqualify this participation?') }}"))
$(this).closest('form').submit();
})
});
</script>
{% endif %}
{% if perms.judge.change_contestparticipation %}
<script type="text/javascript">
$(function () {
$('td.user').find('a.user-name').click(function (e) {
var data = $(this).siblings('.edit-participation');
if (e.altKey && data.length) {
window.open(data.attr('data-link'), '_blank');
return false;
}
});
});
</script>
{% endif %}
{% if not contest.ended %}
<script type="text/javascript">
$(function () {
window.install_tooltips = function () {
$('td.user').find('a.user-name').each(function () {
var link = $(this);
link.mouseenter(function (e) {
var start_time = link.siblings('.start-time').text();
link.addClass('tooltipped tooltipped-e').attr('aria-label', start_time);
}).mouseleave(function (e) {
link.removeClass('tooltipped tooltipped-e').removeAttr('aria-label');
});
});
};
install_tooltips();
});
</script>
{% endif %}
<script type="text/javascript" src="{{ static('event.js') }}"></script>
<script type="text/javascript">
function isFaster(time1, time2) {
let arr1 = time1.split(':');
let arr2 = time2.split(':');
for (let i in arr1) {
let val1 = parseInt(arr1[i]);
let val2 = parseInt(arr2[i]);
if (val1 < val2) return true;
if (val1 > val2) return false;
}
return false;
}
function scoretimeComparison(sub1, sub2) {
if (!sub2) return true;
return sub1['score'] > sub2['score'] || (sub1['score'] === sub2['score'] && isFaster(sub1['time'], sub2['time']));
}
function highlightFirstSolve() {
// bucket to store submissions by problems
let bestSubmissions = {};
// get information
$('td a').each(function() {
let td = $(this)[0]
let link = td['attributes']['href']['value']
if (link.includes('submissions')) {
let scoreAndTime = (td.innerText.split('\n'))
let linkElements = link.split('/')
// get information
let problem = linkElements[linkElements.length - 2];
let score = parseFloat(scoreAndTime[0]);
let time = scoreAndTime[1];
if (time) {
let curSubmission = {
'td': $(this).parent(),
'score': score,
'time': time
}
// update best submissions
let curBest = bestSubmissions[problem]
if (scoretimeComparison(curSubmission, curBest) && score) {
bestSubmissions[problem] = curSubmission;
}
}
}
})
for (let problem in bestSubmissions) {
bestSubmissions[problem]['td'].addClass('first-solve')
}
}
function renew_filter() {
var checkboxes = [
'#show-organizations-checkbox',
'#show-fullnames-checkbox',
'#show-total-score-checkbox',
];
var checkboxes2 = [
'#show-friends-checkbox',
'#show-virtual-checkbox'
]
for (var i of checkboxes) {
var $box = $(i);
if ($box.is(':checked')) {
$box.prop('checked', false);
$box.click();
$box.prop('checked', true);
}
}
var to_update = false;
for (var i of checkboxes2) {
var $box = $(i);
if ($box.is(':checked')) {
to_update = true;
}
}
if (to_update) {
update_ranking();
}
}
function get_initial_rank() {
var ranks = $('.rank-td').map(function() {return this.innerHTML}).get();
var usernames = $('.user-name .rating a').map(function() {return this.text}).get();
window.user_rank = new Map();
for (var i = 0; i < ranks.length; i++) {
window.user_rank[usernames[i]] = ranks[i];
}
}
function add_initial_friend_rank() {
var usernames = $('.user-name .rating a').map(function() {return this.text}).get();
var is_virtual = [];
$('.user-name').each(function() {
if($(this).children('sup').length) {
is_virtual.push(1);
}
else is_virtual.push(0);
});
$('.rank-td').each(function(i) {
if (!is_virtual[i]) this.innerHTML += ' (' + window.user_rank[usernames[i]] + ')';
});
}
function update_ranking() {
var friend = $('#show-friends-checkbox').is(':checked');
var virtual = $('#show-virtual-checkbox').is(':checked');
$('#loading-gif').show();
$.get({
url: `/contest/{{contest.key}}/ranking/ajax?friend=${friend}&virtual=${virtual}`,
success: function(HTML) {
$('#users-table').html(HTML);
highlightFirstSolve();
$('#loading-gif').hide();
if (!virtual && !friend) {
get_initial_rank();
}
if (friend) {
add_initial_friend_rank();
}
},
fail: function() {
console.log('Fail to update ranking');
}
});
}
// window.load_dynamic_update = function (last_msg) {
// return new EventReceiver(
// "{{ EVENT_DAEMON_LOCATION }}", "{{ EVENT_DAEMON_POLL_LOCATION }}",
// ['contest_{{contest.id}}'], last_msg, function (message) {
// switch (message.type) {
// case 'update':
// update_ranking();
// break;
// }
// }
// );
// }
$(function () {
var url = '{{ url('contest_participation', contest.key, '__username__') }}';
var placeholder = $('#search-contest').replaceWith($('<select>').attr({
id: 'search-contest'
})).attr('placeholder');
$('#search-contest').select2({
placeholder: placeholder,
ajax: {
url: '{{ url('contest_user_search_select2_ajax', contest.key) }}'
},
minimumInputLength: 1,
escapeMarkup: function (markup) {
return markup;
},
templateResult: function (data, container) {
return ('<img class="user-search-image" src="' + data.gravatar_url + '" width="24" height="24">' +
'<span class="' + data.display_rank + ' user-search-name">' + data.text + '</span>');
}
}).on('change', function () {
window.location.href = url.replace('__username__', $(this).val());
});
$('#show-organizations-checkbox').click(function () {
$('.organization-column').toggle();
});
$('#show-fullnames-checkbox').click(function () {
$('.fullname-column').toggle();
});
{% if request.user.is_authenticated %}
$('#show-friends-checkbox').click(function() {
update_ranking();
})
{% endif %}
$('#show-virtual-checkbox').click(function() {
update_ranking();
})
$('#show-total-score-checkbox').click(function() {
$('.problem-score-col').toggle();
})
highlightFirstSolve();
renew_filter();
get_initial_rank();
{% if participation_tab %}
$('#show-virtual-checkbox').hide();
$('#show-virtual-label').hide();
{% else %}
{% if request.in_contest %}
setInterval(update_ranking, 60 * 1000);
{% endif %}
{% endif %}
});
</script>
{% include "contest/media-js.html" %}
{% endblock %}
{% block users_table %}
<div style="margin-bottom: 0.5em">
{% if tab == 'participation' %}
{% if contest.can_see_full_scoreboard(request.user) %}
<input id="search-contest" type="text" placeholder="{{ _('View user participation') }}">
{% endif %}
{% endif %}
<input id="show-organizations-checkbox" type="checkbox" style="vertical-align: bottom">
<label for="show-organizations-checkbox" style="vertical-align: bottom; margin-right: 1em;">{{ _('Show organizations') }}</label>
<input id="show-fullnames-checkbox" type="checkbox" style="vertical-align: bottom">
<label for="show-fullnames-checkbox" style="vertical-align: bottom; margin-right: 1em;">{{ _('Show full name') }}</label>
{% if request.user.is_authenticated %}
<input id="show-friends-checkbox" type="checkbox" style="vertical-align: bottom;">
<label for="show-friends-checkbox" style="vertical-align: bottom; margin-right: 1em;">{{ _('Show friends only') }}</label>
{% endif %}
<input id="show-total-score-checkbox" type="checkbox" style="vertical-align: bottom; ">
<label for="show-total-score-checkbox" style="vertical-align: bottom; margin-right: 1em;">{{ _('Total score only') }}</label>
<input id="show-virtual-checkbox" type="checkbox" style="vertical-align: bottom;">
<label id="show-virtual-label" for="show-virtual-checkbox" style="vertical-align: bottom; margin-right: 1em;">{{ _('Show virtual participation') }}</label>
<img src="{{static('loading.gif')}}" style="height: 1em; display:none;" id="loading-gif"></img>
</div>
{% include "contest/ranking-table.html" %}
{% endblock %}