S2OJ/web/js/uoj.js

2390 lines
77 KiB
JavaScript
Raw Permalink Normal View History

2016-07-18 16:39:37 +00:00
// locale
uojLocaleData = {
"username": {
"en": "Username",
"zh-cn": "用户名"
},
"contests::total score": {
"en": "Score",
"zh-cn": "总分"
},
"contests::n participants": {
"en": function(n) {
return n + " participant" + (n <= 1 ? '' : 's');
},
"zh-cn": function(n) {
return "共 " + n + " 名参赛者";
}
},
"click-zan::good": {
"en": "Good",
"zh-cn": "好评"
},
"click-zan::bad": {
"en": "Bad",
"zh-cn": "差评"
},
"editor::language": {
"en": "Language",
"zh-cn": "语言"
},
"editor::browse": {
"en": "Browse",
"zh-cn": "浏览"
},
"editor::upload source": {
"en": "Source",
"zh-cn": "来源"
},
2016-07-18 16:39:37 +00:00
"editor::upload by editor": {
"en": "Editor",
"zh-cn": "编辑器"
2016-07-18 16:39:37 +00:00
},
"editor::upload from local": {
"en": "Local file",
2023-03-14 08:55:11 +00:00
"zh-cn": "本地文件",
},
"editor::edit": {
"en": "Edit",
"zh-cn": "编辑",
},
"editor::preview": {
"en": "Preview",
"zh-cn": "预览",
},
2016-07-18 16:39:37 +00:00
};
function uojLocale(name) {
locale = $.cookie('uoj_locale');
if (uojLocaleData[name] === undefined) {
return '';
}
if (uojLocaleData[name][locale] === undefined) {
locale = 'zh-cn';
}
val = uojLocaleData[name][locale];
if (!$.isFunction(val)) {
return val;
} else {
var args = [];
for (var i = 1; i < arguments.length; i++) {
args.push(arguments[i]);
}
return val.apply(this, args);
}
}
// utility
function strToDate(str) {
var a = str.split(/[^0-9]/);
return new Date(
parseInt(a[0]),
parseInt(a[1]) - 1,
parseInt(a[2]),
parseInt(a[3]),
parseInt(a[4]),
parseInt(a[5]),
0);
}
function dateToStr(date) {
return date.getFullYear() + '-' + (date.getMonth() + 1) + '-' + date.getDate() + ' ' + date.getHours() + ':' + date.getMinutes() + ':' + date.getSeconds();
}
function toFilledStr(o, f, l) {
var s = o.toString();
while (s.length < l) {
s = f.toString() + s;
}
return s;
}
function getPenaltyTimeStr(x) {
var ss = toFilledStr(x % 60, '0', 2);
x = Math.floor(x / 60);
var mm = toFilledStr(x % 60, '0', 2);
x = Math.floor(x / 60);
var hh = x.toString();
return hh + ':' + mm + ':' + ss;
}
function htmlspecialchars(str)
{
var s = "";
if (str.length == 0) return "";
s = str.replace(/&/g, "&amp;");
s = s.replace(/</g, "&lt;");
s = s.replace(/>/g, "&gt;");
s = s.replace(/"/g, "&quot;");
return s;
}
function getColOfScore(score) {
if (score == 0) {
return ColorConverter.toStr(ColorConverter.toRGB(new HSV(0, 76, 86)));
2016-07-18 16:39:37 +00:00
} else if (score == 100) {
return ColorConverter.toStr(ColorConverter.toRGB(new HSV(130, 89, 72)));
2016-07-18 16:39:37 +00:00
} else {
return ColorConverter.toStr(ColorConverter.toRGB(new HSV(30 + score * 60 / 100, 83, 89)));
2016-07-18 16:39:37 +00:00
}
}
2023-01-14 10:24:03 +00:00
function getUserLink(username, realname, color) {
2016-07-18 16:39:37 +00:00
if (!username) {
return '';
}
var text = username;
2023-02-23 11:46:33 +00:00
var className = 'uoj-username';
2016-07-18 16:39:37 +00:00
if (username.charAt(0) == '@') {
username = username.substr(1);
}
2022-03-17 10:26:29 +00:00
if (realname) {
text = text + ' <span class="uoj-realname d-inline-block">(' + realname + ')</span>';
2022-03-17 10:26:29 +00:00
}
2023-01-14 10:24:03 +00:00
if (color) {
2023-02-23 11:46:33 +00:00
className += ' uoj-username-' + color;
2023-01-14 10:24:03 +00:00
}
2023-02-23 11:46:33 +00:00
return '<a class="' + className + '" href="' + uojHome + '/user/' + username + '">' + text + '</a>';
2016-07-18 16:39:37 +00:00
}
2023-01-14 10:24:03 +00:00
function getUserSpan(username, realname, color) {
2016-07-18 16:39:37 +00:00
if (!username) {
return '';
}
var text = username;
2023-02-23 11:46:33 +00:00
var className = 'uoj-username';
2016-07-18 16:39:37 +00:00
if (username.charAt(0) == '@') {
username = username.substr(1);
}
2022-03-17 10:26:29 +00:00
if (realname) {
text = text + ' <span class="uoj-realname d-inline-block">(' + realname + ')</span>';
2022-03-17 10:26:29 +00:00
}
2023-01-14 10:24:03 +00:00
if (color) {
2023-02-23 11:46:33 +00:00
className += ' uoj-username-' + color;
2023-01-14 10:24:03 +00:00
}
2023-02-23 11:46:33 +00:00
return '<span class="' + className + '">' + text + '</span>';
2016-07-18 16:39:37 +00:00
}
function replaceWithHighlightUsername() {
var username = $(this).text();
2022-03-17 10:26:29 +00:00
var realname = $(this).data("realname");
var color = $(this).data("color");
2016-07-18 16:39:37 +00:00
if ($(this).data("link") != 0) {
2023-01-14 10:24:03 +00:00
$(this).replaceWith(getUserLink(username, realname, color));
2016-07-18 16:39:37 +00:00
} else {
2023-01-14 10:24:03 +00:00
$(this).replaceWith(getUserSpan(username, realname, color));
2016-07-18 16:39:37 +00:00
}
}
2022-03-17 10:26:29 +00:00
$.fn.uoj_honor = function() {
return this.each(function() {
var honor = $(this).text();
var realname = $(this).data("realname");
if (realname) {
honor = honor + ' (' + realname + ')';
}
$(this).css('color', '#007bff').html(honor);
});
}
2023-02-24 14:10:29 +00:00
function getClickZanBlock(type, id, cnt, val) {
return '<div class="uoj-click-zan-block" data-id="' + id + '" data-type="' + type + '" data-val="' + val + '" data-cnt="' + cnt + '"></div>';
}
2016-07-18 16:39:37 +00:00
function showErrorHelp(name, err) {
if (err) {
2022-11-06 02:26:21 +00:00
$('#div-' + name).addClass('has-validation has-error');
$('#div-' + name).addClass('is-invalid');
$('#input-' + name).addClass('is-invalid');
2016-07-18 16:39:37 +00:00
$('#help-' + name).text(err);
return false;
} else {
2022-11-06 02:26:21 +00:00
$('#div-' + name).removeClass('has-validation has-error');
$('#div-' + name).removeClass('is-invalid');
$('#input-' + name).removeClass('is-invalid');
2016-07-18 16:39:37 +00:00
$('#help-' + name).text('');
return true;
}
}
function getFormErrorAndShowHelp(name, val) {
var err = val($('#input-' + name).val());
return showErrorHelp(name, err);
}
function validateSettingPassword(str) {
if (str.length < 6) {
return '密码长度不应小于6。';
} else if (! /^[!-~]+$/.test(str)) {
return '密码应只包含可见ASCII字符。';
} else if (str != $('#input-confirm_password').val()) {
return '两次输入的密码不一致。';
} else {
return '';
}
}
function validatePassword(str) {
if (str.length < 6) {
return '密码长度不应小于6。';
} else if (! /^[!-~]+$/.test(str)) {
return '密码应只包含可见ASCII字符。';
} else {
return '';
}
}
function validateEmail(str) {
if (str.length > 50) {
return '电子邮箱地址太长。';
} else if (! /^(.+)@(.+)$/.test(str)) {
return '电子邮箱地址非法。';
} else {
return '';
}
}
function validateUsername(str) {
if (str.length == 0) {
return '用户名不能为空。';
} else if (! /^[a-zA-Z0-9_]+$/.test(str)) {
return '用户名应只包含大小写英文字母、数字和下划线。';
} else {
return '';
}
}
function validateQQ(str) {
if (str.length < 5) {
return 'QQ的长度不应小于5。';
} else if (str.length > 15) {
return 'QQ的长度不应大于15。';
} else if (/\D/.test(str)) {
return 'QQ应只包含0~9的数字。';
} else {
return '';
}
}
function validateMotto(str) {
2022-09-18 13:38:57 +00:00
if (str.length > 1024) {
return '不能超过 1024 个字符。';
2016-07-18 16:39:37 +00:00
} else {
return '';
}
}
// tags
$.fn.uoj_problem_tag = function() {
return this.each(function() {
$(this).attr('href', uojHome + '/problems?tag=' + encodeURIComponent($(this).text()));
});
}
2022-09-18 11:34:17 +00:00
$.fn.uoj_list_tag = function() {
return this.each(function() {
2022-10-22 11:24:48 +00:00
$(this).attr('href', uojHome + '/lists?tag=' + encodeURIComponent($(this).text()));
2022-09-18 11:34:17 +00:00
});
}
2016-07-18 16:39:37 +00:00
$.fn.uoj_blog_tag = function() {
return this.each(function() {
$(this).attr('href', uojBlogUrl + '/archive?tag=' + encodeURIComponent($(this).text()));
2016-07-18 16:39:37 +00:00
});
}
// click zan
function click_zan(zan_id, zan_type, zan_delta, node) {
2022-09-28 01:40:56 +00:00
var loading_node = $('<div class="uoj-click-zan-block text-muted">loading...</div>');
2016-07-18 16:39:37 +00:00
$(node).replaceWith(loading_node);
$.post(zan_link + '/click-zan', {
2016-07-18 16:39:37 +00:00
id : zan_id,
delta : zan_delta,
type : zan_type,
2016-07-18 16:39:37 +00:00
}, function(ret) {
$(loading_node).replaceWith($(ret).click_zan_block());
}).fail(function() {
2022-09-28 01:40:56 +00:00
$(loading_node).replaceWith('<div class="uoj-click-zan-block text-danger">failed</div>');
2016-07-18 16:39:37 +00:00
});
}
$.fn.click_zan_block = function() {
return this.each(function() {
var id = $(this).data('id');
var type = $(this).data('type');
var val = parseInt($(this).data('val'));
var cnt = parseInt($(this).data('cnt'));
2023-02-24 14:10:29 +00:00
var rendered = $(this).attr('data-click-zan-rendered');
if (rendered == 'true') {
return;
}
2016-07-18 16:39:37 +00:00
if (isNaN(cnt)) {
return;
}
2023-02-05 12:55:14 +00:00
var up_icon_html = '<i class="bi bi-hand-thumbs-up"></i>';
var down_icon_html = '<i class="bi bi-hand-thumbs-down"></i>';
2016-07-18 16:39:37 +00:00
if (val == 1) {
$(this).addClass('uoj-click-zan-block-cur-up');
up_icon_html = '<i class="bi bi-hand-thumbs-up-fill"></i>';
2016-07-18 16:39:37 +00:00
} else if (val == 0) {
$(this).addClass('uoj-click-zan-block-cur-zero');
} else if (val == -1) {
$(this).addClass('uoj-click-zan-block-cur-down');
down_icon_html = '<i class="bi bi-hand-thumbs-down-fill"></i>';
2016-07-18 16:39:37 +00:00
} else {
return;
}
if (cnt > 0) {
$(this).addClass('uoj-click-zan-block-positive');
} else if (cnt == 0) {
$(this).addClass('uoj-click-zan-block-neutral');
} else {
$(this).addClass('uoj-click-zan-block-negative');
}
2022-09-24 02:18:55 +00:00
2016-07-18 16:39:37 +00:00
var node = this;
var up_node = $('<a href="#" class="uoj-click-zan-up">'+up_icon_html+uojLocale('click-zan::good')+'</a>').click(function(e) {
2016-07-18 16:39:37 +00:00
e.preventDefault();
click_zan(id, type, 1, node);
2023-02-05 12:55:14 +00:00
});
var down_node = $('<a href="#" class="uoj-click-zan-down">'+down_icon_html+uojLocale('click-zan::bad')+'</a>').click(function(e) {
2016-07-18 16:39:37 +00:00
e.preventDefault();
click_zan(id, type, -1, node);
2023-02-05 12:55:14 +00:00
});
var display_cnt = cnt > 0 ? '+' + cnt : cnt;
2023-02-24 09:04:29 +00:00
if (cnt < 0) display_cnt = '-?';
2023-02-24 14:10:29 +00:00
2016-07-18 16:39:37 +00:00
$(this)
2023-02-24 14:10:29 +00:00
.attr('data-click-zan-rendered', 'true')
2016-07-18 16:39:37 +00:00
.append(up_node)
.append(down_node)
2023-02-24 09:21:09 +00:00
.append($('<span class="uoj-click-zan-cnt" title="' + cnt + '">[<strong>' + display_cnt + '</strong>]</span>'));
2016-07-18 16:39:37 +00:00
});
}
// count down
2023-02-26 10:03:00 +00:00
function getCountdownStr(t, config) {
2016-07-18 16:39:37 +00:00
var x = Math.floor(t);
var ss = toFilledStr(x % 60, '0', 2);
x = Math.floor(x / 60);
var mm = toFilledStr(x % 60, '0', 2);
x = Math.floor(x / 60);
var hh = x.toString();
2023-02-26 10:03:00 +00:00
var style = '';
if (config.font_size) {
style += 'font-size: ' + config.font_size + ';';
}
2016-07-18 16:39:37 +00:00
2023-02-26 10:03:00 +00:00
var res = '<span style="' + style + '">';
res += '<span>' + hh + '</span>';
2016-07-18 16:39:37 +00:00
res += ':';
2023-02-26 10:03:00 +00:00
res += '<span>' + mm + '</span>';
2016-07-18 16:39:37 +00:00
res += ':';
2023-02-26 10:03:00 +00:00
res += '<span>' + ss + '</span>';
res += '</span>';
2016-07-18 16:39:37 +00:00
return res;
}
2023-02-26 10:03:00 +00:00
$.fn.countdown = function(rest, config = {}) {
2016-07-18 16:39:37 +00:00
return this.each(function() {
var start = new Date().getTime();
var cur_rest = rest != undefined ? rest : parseInt($(this).data('rest'));
2023-02-26 10:03:00 +00:00
config = $.merge(config, JSON.parse($(this).data('config') || '{}'));
2016-07-18 16:39:37 +00:00
var cur = this;
var countdown = function() {
var passed = Math.floor((new Date().getTime() - start) / 1000);
if (passed >= cur_rest) {
2023-02-26 10:03:00 +00:00
$(cur).html(getCountdownStr(0, config));
if (config.callback != undefined) {
2016-07-18 16:39:37 +00:00
callback();
}
} else {
2023-02-26 10:03:00 +00:00
$(cur).html(getCountdownStr(cur_rest - passed, config));
setTimeout(countdown, 500);
2016-07-18 16:39:37 +00:00
}
}
countdown();
});
};
// update_judgement_status
update_judgement_status_list = []
function update_judgement_status_details(id) {
update_judgement_status_list.push(id);
};
$(document).ready(function() {
function update() {
$.get("/api/submission/submission_status_details", {
get: update_judgement_status_list,
2016-07-18 16:39:37 +00:00
},
function(data) {
for (var i = 0; i < update_judgement_status_list.length; i++) {
$("#status_details_" + update_judgement_status_list[i]).html(data[i].html);
if (data[i].judged) {
location.reload();
}
}
}, 'json').always(
function() {
setTimeout(update, 500);
}
);
}
if (update_judgement_status_list.length > 0) {
setTimeout(update, 500);
}
});
// highlight
$.fn.uoj_highlight = function() {
return $(this).each(function() {
$(this).find("span.uoj-username, span[data-uoj-username]").each(replaceWithHighlightUsername);
2022-03-17 10:26:29 +00:00
$(this).find(".uoj-honor").uoj_honor();
2016-07-18 16:39:37 +00:00
$(this).find(".uoj-score").each(function() {
var score = parseFloat($(this).text());
var maxscore = parseFloat($(this).data('max'));
2016-07-18 16:39:37 +00:00
if (isNaN(score)) {
return;
}
if (isNaN(maxscore)) {
$(this).css("color", getColOfScore(score));
} else {
$(this).css("color", getColOfScore(score / maxscore * 100));
}
});
$(this).find(".uoj-status").each(function() {
var success = parseInt($(this).data("success"));
if(isNaN(success)){
return;
}
if (success == 1) {
$(this).css("color", ColorConverter.toStr(ColorConverter.toRGB(new HSV(120, 100, 80))));
}
else {
$(this).css("color", ColorConverter.toStr(ColorConverter.toRGB(new HSV(0, 100, 100))));
}
});
$(this).find(".uoj-problem-tag").uoj_problem_tag();
2022-09-18 11:34:17 +00:00
$(this).find(".uoj-list-tag").uoj_list_tag();
2016-07-18 16:39:37 +00:00
$(this).find(".uoj-blog-tag").uoj_blog_tag();
$(this).find(".uoj-click-zan-block").click_zan_block();
$(this).find(".countdown").countdown();
$(this).find(".uoj-readmore").readmore({
moreLink: '<a href="#" class="text-right">more...</a>',
lessLink: '<a href="#" class="text-right">close</a>',
});
2016-07-18 16:39:37 +00:00
});
};
$(document).ready(function() {
$('body').uoj_highlight();
});
// contest notice
2022-11-06 02:26:21 +00:00
function checkNotice(lastTime) {
$.post(uojHome + '/check-notice', {
2016-07-18 16:39:37 +00:00
last_time : lastTime
},
function(data) {
2022-11-06 02:26:21 +00:00
if (data === null) {
return;
}
2016-07-18 16:39:37 +00:00
setTimeout(function() {
2022-11-06 02:26:21 +00:00
checkNotice(data.time);
2016-07-18 16:39:37 +00:00
}, 60000);
2022-11-06 02:26:21 +00:00
for (var i = 0; i < data.msg.length; i++) {
alert(data.msg[i]);
}
2016-07-18 16:39:37 +00:00
},
'json'
).fail(function() {
setTimeout(function() {
2022-11-06 02:26:21 +00:00
checkNotice(lastTime);
2016-07-18 16:39:37 +00:00
}, 60000);
});
}
// long table
$.fn.long_table = function(data, cur_page, header_row, get_row_str, config) {
return this.each(function() {
var table_div = this;
$(table_div).html('');
var page_len = config.page_len != undefined ? config.page_len : 10;
if (!config.echo_full) {
var n_rows = data.length;
var n_pages = Math.max(Math.ceil(n_rows / page_len), 1);
if (cur_page == undefined) {
cur_page = 1;
}
if (cur_page < 1) {
cur_page = 1;
} else if (cur_page > n_pages) {
cur_page = n_pages;
}
var cur_start = (cur_page - 1) * page_len;
} else {
var n_rows = data.length;
var n_pages = 1;
cur_page = 1;
var cur_start = (cur_page - 1) * page_len;
}
var div_classes = config.div_classes != undefined ? config.div_classes : ['table-responsive'];
var table_classes = config.table_classes != undefined ? config.table_classes : ['table', 'table-bordered', 'table-hover', 'table-striped', 'table-text-center'];
var now_cnt = 0;
var tbody = $('<tbody />')
for (var i = 0; i < page_len && cur_start + i < n_rows; i++) {
now_cnt++;
if (config.get_row_index) {
tbody.append(get_row_str(data[cur_start + i], cur_start + i));
} else {
tbody.append(get_row_str(data[cur_start + i]));
}
}
if (now_cnt == 0) {
tbody.append('<tr><td colspan="233">无</td></tr>');
}
$(table_div).append(
$('<div class="' + div_classes.join(' ') + '" />')
.append(typeof config.print_before_table === 'function' ? config.print_before_table() : '')
.append(
$('<table class="' + table_classes.join(' ') + '" />')
.append($('<thead />').append(header_row))
.append(tbody)
)
.append(typeof config.print_after_table === 'function' ? config.print_after_table() : '')
2016-07-18 16:39:37 +00:00
);
var get_page_li = function(p, h) {
if (p == -1) {
return $('<li class="page-item"></li>').addClass('disabled').append($('<a class="page-link"></a>').append(h));
2016-07-18 16:39:37 +00:00
}
var li = $('<li class="page-item"></li>');
2016-07-18 16:39:37 +00:00
if (p == cur_page) {
li.addClass('active');
}
li.append(
$('<a class="page-link"></a>').attr('href', '#' + table_div.id).append(h).click(function(e) {
2016-07-18 16:39:37 +00:00
if (config.prevent_focus_on_click) {
e.preventDefault();
}
$(table_div).long_table(data, p, header_row, get_row_str, config);
})
);
return li;
};
2023-02-07 12:41:37 +00:00
var get_pagination = function() {
var pagination = $('<ul class="pagination top-buffer-no bot-buffer-sm justify-content-center"></ul>');
2016-07-18 16:39:37 +00:00
if (cur_page > 1) {
2023-02-05 12:55:14 +00:00
pagination.append(get_page_li(1, '<i class="bi bi-chevron-double-left"></i>'));
pagination.append(get_page_li(cur_page - 1, '<i class="bi bi-chevron-left"></i>'));
2016-07-18 16:39:37 +00:00
} else {
2023-02-05 12:55:14 +00:00
pagination.append(get_page_li(-1, '<i class="bi bi-chevron-double-left"></i>'));
pagination.append(get_page_li(-1, '<i class="bi bi-chevron-left"></i>'));
2016-07-18 16:39:37 +00:00
}
var max_extend = config.max_extend != undefined ? config.max_extend : 5;
for (var i = Math.max(cur_page - max_extend, 1); i <= Math.min(cur_page + max_extend, n_pages); i++) {
pagination.append(get_page_li(i, i.toString()));
}
if (cur_page < n_pages) {
2023-02-05 12:55:14 +00:00
pagination.append(get_page_li(cur_page + 1, '<i class="bi bi-chevron-right"></i>'));
pagination.append(get_page_li(n_pages, '<i class="bi bi-chevron-double-right"></i>'));
2016-07-18 16:39:37 +00:00
} else {
2023-02-05 12:55:14 +00:00
pagination.append(get_page_li(-1, '<i class="bi bi-chevron-right"></i>'));
pagination.append(get_page_li(-1, '<i class="bi bi-chevron-double-right"></i>'));
2016-07-18 16:39:37 +00:00
}
2023-02-07 12:41:37 +00:00
return pagination;
}
if (n_pages > 1) {
$(table_div).append($('<div class="text-center"></div>').append(get_pagination()));
if (config.top_pagination) {
$(table_div).prepend($('<div class="text-center"></div>').append(get_pagination()));
}
2016-07-18 16:39:37 +00:00
}
});
};
// monaco editor
function require_monaco(config, callback) {
window.require = {
paths: {
vs: '/js/monaco-editor/min/vs',
},
"vs/nls": {
availableLanguages: {
'*': 'zh-cn',
},
},
};
$LAB.script('/js/monaco-editor/min/vs/loader.js').wait()
.script('/js/monaco-editor/min/vs/editor/editor.main.nls.js').wait()
.script('/js/monaco-editor/min/vs/editor/editor.main.nls.zh-cn.js').wait()
.script('/js/monaco-editor/min/vs/editor/editor.main.js').wait(function() {
2023-02-08 23:39:21 +00:00
$LAB.script('/js/monaco-themes.js').wait(function() {
2023-02-23 10:28:20 +00:00
update_monaco_theme(getPreferredTheme());
2023-02-08 23:39:21 +00:00
if (config.markdown) {
$LAB.script('/js/blog-editor/monaco-markdown.js').wait(callback);
} else {
callback();
}
});
});
2016-07-18 16:39:37 +00:00
}
2023-02-23 10:28:20 +00:00
function update_monaco_theme(theme) {
if (!('monaco' in window)) return;
if (theme == 'dark') {
monaco.editor.setTheme('github-dark');
} else {
monaco.editor.setTheme('github');
}
}
function get_monaco_mode(lang) {
2016-07-18 16:39:37 +00:00
switch (lang) {
case 'C++':
case 'C++11':
2022-09-18 02:54:13 +00:00
case 'C++17':
2022-10-04 13:31:28 +00:00
case 'C++20':
2022-09-18 02:54:13 +00:00
case 'C++98':
2022-10-04 13:31:28 +00:00
case 'C++03':
return 'cpp';
2016-07-18 16:39:37 +00:00
case 'C':
return 'c';
case 'Python2':
2022-10-04 13:31:28 +00:00
case 'Python2.7':
2016-07-18 16:39:37 +00:00
case 'Python3':
return 'python';
2016-07-18 16:39:37 +00:00
case 'Pascal':
return 'pascal';
2022-10-04 23:47:56 +00:00
case 'Java8':
case 'Java11':
case 'Java17':
return 'java';
2016-07-18 16:39:37 +00:00
case 'text':
return 'text';
2016-07-18 16:39:37 +00:00
default:
return 'text';
2016-07-18 16:39:37 +00:00
}
}
2016-07-18 16:39:37 +00:00
// auto save
function autosave_locally_monaco(interval, name, monaco_instance) {
if (typeof(Storage) === "undefined") {
console.log('autosave_locally_monaco: Sorry! No Web Storage support..');
return;
}
var url = window.location.href;
var hp = url.indexOf('#');
var uri = hp == -1 ? url : url.substring(0, hp);
var full_name = name + '@' + uri;
monaco_instance.getModel().setValue(localStorage.getItem(full_name));
var save = function() {
localStorage.setItem(full_name, monaco_instance.getModel().getValue());
setTimeout(save, interval);
};
setTimeout(save, interval);
}
2016-07-18 16:39:37 +00:00
// source code form group
$.fn.source_code_form_group = function(name, text, langs_options_html) {
return this.each(function() {
var input_upload_type_editor_id = 'input-' + name + '_upload_type_editor';
var input_upload_type_file_id = 'input-' + name + '_upload_type_file';
var input_upload_type_name = name + '_upload_type';
2016-07-18 16:39:37 +00:00
var input_language_id = 'input-' + name + '_language';
var input_language_name = name + '_language';
var input_editor_id = 'input-' + name + '_editor';
var input_editor_name = name + '_editor';
var input_file_id = 'input-' + name + '_file';
var input_file_name = name + '_file';
var spinner_id = 'spinner-' + name + '_editor';
2016-07-18 16:39:37 +00:00
var div_help_language_id = 'div-help-' + name + '_language';
2023-03-21 09:18:17 +00:00
var div_help_forbidden_code_id = 'div-help-' + name + '_forbidden_code';
2016-07-18 16:39:37 +00:00
var div_editor_id = 'div-' + name + '_editor';
var div_file_id = 'div-' + name + '_file';
var help_file_id = 'help-' + name + '_file';
var input_language =
$('<select id="' + input_language_id + '" name="' + input_language_name + '" class="form-select form-select-sm d-inline-block"/>')
2016-07-18 16:39:37 +00:00
.html(langs_options_html);
var input_upload_type_editor = $('<input class="form-check-input" type="radio" id="' + input_upload_type_editor_id + '" name="' + input_upload_type_name + '" value="editor" />');
var input_upload_type_file = $('<input class="form-check-input" type="radio" id="' + input_upload_type_file_id + '" name="' + input_upload_type_name + '" value="file" />');
var input_file = $('<input type="file" class="form-control" id="' + input_file_id + '" name="' + input_file_name + '" />');
2016-07-18 16:39:37 +00:00
var div_editor =
$('<div id="' + div_editor_id + '" style="height: 350px" />')
.append(
$('<div id="' + spinner_id + '" class="border d-flex justify-content-center align-items-center" style="width: 100%; height: 350px;" />')
.append('<div class="spinner-border text-muted" style="width: 3rem; height: 3rem;" />')
);
2016-07-18 16:39:37 +00:00
var div_file =
$('<div id="' + div_file_id + '" />')
2016-07-18 16:39:37 +00:00
.append(input_file)
.append($('<span class="help-block" id="' + help_file_id + '"></span>'))
2023-03-21 09:18:17 +00:00
var div_help_language = $('<div id="' + div_help_language_id + '" class="text-warning-emphasis mb-2">');
var div_help_forbidden_code = $('<div id="' + div_help_forbidden_code_id + '" class="text-warning-emphasis mb-2">');
var show_help_lang = function() {
if ($(this).val().startsWith('Java')) {
div_help_language.text('注意Java 程序源代码中不应指定所在的 package。我们会在源代码中找到第一个被定义的类并以它的 main 函数为程序入口点。');
} else {
div_help_language.text('');
}
};
2023-03-21 09:18:17 +00:00
var show_help_forbidden_code = function(lang, code) {
if (lang == 'C' || lang.startsWith('C++')) {
if (/\n\s*#pragma/.test('\n' + code)) {
2023-03-21 09:18:17 +00:00
div_help_forbidden_code.text('注意C/C++ 程序源代码中不应包含 #pragma 指令,这在正式比赛中是不被允许的。');
}
} else {
//
}
};
var monaco_editor_instance = null;
var monaco_editor_init = function() {
require_monaco({}, function() {
if (monaco_editor_instance != null) {
return;
}
$(div_editor).html('');
var mode = get_monaco_mode(input_language.val());
monaco_editor_instance = monaco.editor.create(div_editor[0], {
language: mode,
automaticLayout: true,
2023-02-28 09:32:22 +00:00
fontSize: "16px",
});
$('#' + spinner_id).css('display', 'none !important');
$(div_editor).addClass('border overflow-hidden').show();
autosave_locally_monaco(2000, name, monaco_editor_instance);
$('#' + input_editor_id).val(monaco_editor_instance.getModel().getValue());
monaco_editor_instance.onDidChangeModelContent(function () {
2023-03-21 09:18:17 +00:00
var lang = input_language.val();
var new_val = monaco_editor_instance.getModel().getValue();
$('#' + input_editor_id).val(new_val);
show_help_forbidden_code(lang, new_val);
});
input_language.change(function() {
2023-03-21 09:18:17 +00:00
var new_lang = input_language.val();
var val = monaco_editor_instance.getModel().getValue();
monaco.editor.setModelLanguage(monaco_editor_instance.getModel(), get_monaco_mode(new_lang));
show_help_forbidden_code(new_lang, val);
2016-07-18 16:39:37 +00:00
});
});
}
var save_prefer_upload_type = function(type) {
$.cookie('uoj_source_code_form_group_preferred_upload_type', type, { expires: 7, path: '/' });
};
var prefer_upload_type = $.cookie('uoj_source_code_form_group_preferred_upload_type');
if (prefer_upload_type === null) {
prefer_upload_type = 'editor';
}
if (prefer_upload_type == 'file') {
input_upload_type_file[0].checked = true;
div_editor.css('display', 'none');
} else {
input_upload_type_editor[0].checked = true;
div_file.css('display', 'none');
}
input_language.each(show_help_lang);
input_language.change(show_help_lang);
2016-07-18 16:39:37 +00:00
input_upload_type_editor.click(function() {
div_editor.show('fast');
div_file.hide('fast');
save_prefer_upload_type('editor');
});
input_upload_type_file.click(function() {
div_file.show('fast');
div_editor.hide('fast');
save_prefer_upload_type('file');
});
$(this).append(
$('<div class="row mb-2 align-items-center"/>')
.append($('<div class="col-sm-4 text-start">' + text + '</div>'))
.append(
$('<div class="col-sm-4 row align-items-center"/>')
.append($('<div class="col-auto" />').append('<label class="col-form-label px-1' +' " for="' + input_language_id + '">' + uojLocale('editor::language') + '</label>'))
.append($('<div class="col-auto" />').append(input_language))
)
.append($('<div class="col-sm-4 text-end"/>')
.append(uojLocale('editor::upload source') + ': ')
.append($('<div class="form-check d-inline-block">')
.append($('<label for="' + input_upload_type_editor_id + '" />')
.append(input_upload_type_editor)
.append(' ' + uojLocale('editor::upload by editor'))
)
)
.append($('<div class="form-check d-inline-block ms-3"/>')
.append(input_upload_type_file)
.append($('<label for="' + input_upload_type_file_id +'" />')
.append(' ' + uojLocale('editor::upload from local'))
)
))
)
.append(div_help_language)
2023-03-21 09:18:17 +00:00
.append(div_help_forbidden_code)
.append(div_editor)
.append(div_file)
.append($('<input type="hidden" name="' + input_editor_name + '" id="' + input_editor_id + '"/>'));
var check_monaco_editor_init = function() {
if (div_editor.is(':visible')) {
monaco_editor_init();
} else {
setTimeout(check_monaco_editor_init, 1);
2016-07-18 16:39:37 +00:00
}
}
check_monaco_editor_init();
2016-07-18 16:39:37 +00:00
});
}
// text file form group
$.fn.text_file_form_group = function(name, text) {
return this.each(function() {
var input_upload_type_editor_id = 'input-' + name + '_upload_type_editor';
var input_upload_type_file_id = 'input-' + name + '_upload_type_file';
2016-07-18 16:39:37 +00:00
var input_upload_type_name = name + '_upload_type';
var input_editor_id = 'input-' + name + '_editor';
var input_editor_name = name + '_editor';
var input_file_id = 'input-' + name + '_file';
var input_file_name = name + '_file';
var spinner_id = 'spinner-' + name + '_editor';
2016-07-18 16:39:37 +00:00
var div_editor_id = 'div-' + name + '_editor';
var div_file_id = 'div-' + name + '_file';
var help_file_id = 'help-' + name + '_file';
var input_upload_type_editor = $('<input class="form-check-input" type="radio" id="' + input_upload_type_editor_id + '" name="' + input_upload_type_name + '" value="editor" />');
var input_upload_type_file = $('<input class="form-check-input" type="radio" id="' + input_upload_type_file_id + '" name="' + input_upload_type_name + '" value="file" />');
var input_file = $('<input type="file" class="form-control" id="' + input_file_id + '" name="' + input_file_name + '" />');
2016-07-18 16:39:37 +00:00
var div_editor = $('<div id="' + div_editor_id + '" style="height: 350px" />')
.append(
$('<div id="' + spinner_id + '" class="border d-flex justify-content-center align-items-center" style="width: 100%; height: 350px;" />')
.append('<div class="spinner-border text-muted" style="width: 3rem; height: 3rem;" />')
);
2016-07-18 16:39:37 +00:00
var div_file =
$('<div id="' + div_file_id + '" />')
2016-07-18 16:39:37 +00:00
.append(input_file)
.append($('<span class="help-block" id="' + help_file_id + '"></span>'))
var monaco_editor_instance = null;
var monaco_editor_init = function() {
require_monaco({}, function() {
if (monaco_editor_instance != null) {
return;
}
$(div_editor).html('');
monaco_editor_instance = monaco.editor.create(div_editor[0], {
language: 'text',
automaticLayout: true,
2023-03-14 08:55:11 +00:00
fontSize: "16px",
});
$('#' + spinner_id).css('display', 'none !important');
$(div_editor).addClass('border overflow-hidden').show();
autosave_locally_monaco(2000, name, monaco_editor_instance);
$('#' + input_editor_id).val(monaco_editor_instance.getModel().getValue());
monaco_editor_instance.onDidChangeModelContent(function () {
$('#' + input_editor_id).val(monaco_editor_instance.getModel().getValue());
2016-07-18 16:39:37 +00:00
});
});
}
var save_prefer_upload_type = function(type) {
$.cookie('uoj_text_file_form_group_preferred_upload_type', type, { expires: 7, path: '/' });
};
var prefer_upload_type = $.cookie('uoj_text_file_form_group_preferred_upload_type');
if (prefer_upload_type === null) {
prefer_upload_type = 'editor';
}
if (prefer_upload_type == 'file') {
input_upload_type_file[0].checked = true;
div_editor.css('display', 'none');
} else {
input_upload_type_editor[0].checked = true;
div_file.css('display', 'none');
}
input_upload_type_editor.click(function() {
div_editor.show('fast');
div_file.hide('fast');
save_prefer_upload_type('editor');
});
input_upload_type_file.click(function() {
div_file.show('fast');
div_editor.hide('fast');
save_prefer_upload_type('file');
});
$(this)
.append($('<div class="row justify-content-between mb-2" />')
.append($('<div class="col text-start">' + text + '</div>'))
.append($('<div class="col text-end"/>')
.append(uojLocale('editor::upload source') + ': ')
.append($('<div class="form-check d-inline-block">')
.append($('<label for="' + input_upload_type_editor_id + '" />')
.append(input_upload_type_editor)
.append(' ' + uojLocale('editor::upload by editor'))
)
2016-07-18 16:39:37 +00:00
)
.append($('<div class="form-check d-inline-block ms-3"/>')
2016-07-18 16:39:37 +00:00
.append(input_upload_type_file)
.append($('<label for="' + input_upload_type_file_id +'" />')
.append(' ' + uojLocale('editor::upload from local'))
)
))
)
2016-07-18 16:39:37 +00:00
.append(div_editor)
.append(div_file)
.append($('<input type="hidden" name="' + input_editor_name + '" id="' + input_editor_id + '"/>'));
2016-07-18 16:39:37 +00:00
var check_monaco_editor_init = function() {
if (div_editor.is(':visible')) {
monaco_editor_init();
} else {
setTimeout(check_monaco_editor_init, 1);
2016-07-18 16:39:37 +00:00
}
}
check_monaco_editor_init();
2016-07-18 16:39:37 +00:00
});
}
// remote judge submit type group
$.fn.remote_submit_type_group = function(oj, pid, url, submit_type) {
return this.each(function() {
var input_submit_type_bot_id = 'input-submit_type_bot';
var input_submit_type_my_id = 'input-submit_type_my';
var input_submit_type_archive_id = 'input-submit_type_archive';
var div_submit_type_bot_id = 'div-submit_type_bot';
var div_submit_type_my_id = 'div-submit_type_my';
var div_submit_type_archive_id = 'div-submit_type_archive';
var input_submit_type_bot = $('<input class="form-check-input" type="radio" name="answer_remote_submit_type" id="' + input_submit_type_bot_id + '" value="bot" />');
var input_submit_type_my = $('<input class="form-check-input" type="radio" name="answer_remote_submit_type" id="' + input_submit_type_my_id + '" value="my" />');
var input_submit_type_archive = $('<input class="form-check-input" type="radio" name="answer_remote_submit_type" id="' + input_submit_type_archive_id + '" value="archive" />');
var input_my_account_data = $('<input type="hidden" name="answer_remote_account_data" value="" />');
var my_account_validation_status = $('<span />').append('<span class="text-secondary">待验证</span>');
var my_account_validation_btn = $('<button type="button" class="btn btn-secondary btn-sm ms-2">验证</button>');
var validate_my_account = function(data) {
my_account_validation_btn.html('<span class="spinner-border spinner-border-sm" role="status"></span>');
my_account_validation_btn.addClass('disabled');
$.ajax({
type: 'POST',
url: '/api/remote_judge/custom_account_validator?type=' + oj,
data: data,
success: function(res) {
my_account_validation_btn.html('验证');
my_account_validation_btn.removeClass('disabled');
console.log('Validation status', res);
if (res.ok) {
my_account_validation_status.html('<span class="text-success">可用</span>');
} else {
my_account_validation_status.html('<span class="text-danger">不可用</span>');
}
},
error: function() {
my_account_validation_btn.html('验证');
my_account_validation_btn.removeClass('disabled');
my_account_validation_status.html('<span class="text-secondary">待验证</span>');
},
dataType: 'json',
});
};
var div_submit_type_bot = $('<div id="' + div_submit_type_bot_id + '" />')
.append('<div class="mt-3">将使用公用账号提交本题。</div>');
var div_submit_type_my = $('<div id="' + div_submit_type_my_id + '" />')
.append($('<div class="mt-3" />')
.append('<span>将使用您的账号提交本题。</span>')
2023-02-14 02:39:32 +00:00
.append('<span>配置方法请查阅 <a href="https://s2oj.github.io/#/user/problem?id=remote-judge-%e9%a2%98%e7%9b%ae" target="_blank">使用教程</a>。</span>')
);
var div_submit_type_archive = $('<div id="' + div_submit_type_archive_id + '" />')
.append($('<div class="mt-3" />')
.append('<span>将从您给定的提交记录中抓取评测结果。</span>')
2023-02-14 02:39:32 +00:00
.append('<span>配置方法请查阅 <a href="https://s2oj.github.io/#/user/problem?id=remote-judge-%e9%a2%98%e7%9b%ae" target="_blank">使用教程</a>。</span>')
).append(
$('<div class="row mt-3 align-items-center" />')
.append($('<div class="col-sm-2" />').append('<label for="input-answer_remote_submission_id" class="col-form-label">提交记录 ID</label>'))
.append($('<div class="col-sm-4" />').append('<input id="input-answer_remote_submission_id" name="answer_remote_submission_id" class="form-control font-monospace" autocomplete="off" />'))
.append($('<div class="col-sm-6" />').append($('<div class="form-text mt-0" />').append('请填入远程 OJ 上的提交记录 ID。')))
);
var div_account_data = $('<div class="border px-3 py-2 mt-3" />')
.append($('<div class="mt-2" />').append('<span class="fs-6 fw-bold">远程账号信息</span>'))
.append($('<div class="mt-3" />')
.append('<span>账号状态:</span>')
.append(my_account_validation_status)
.append(my_account_validation_btn)
);
if ('localStorage' in window) {
var prefer_submit_type = localStorage.getItem('uoj_remote_judge_save_prefer_submit_type__' + oj) || null;
var save_prefer_submit_type = function(type) {
localStorage.setItem('uoj_remote_judge_save_prefer_submit_type__' + oj, type);
}
} else {
var prefer_submit_type = null;
var save_prefer_submit_type = function(type) {};
}
input_submit_type_bot.click(function() {
div_account_data.hide('fast');
div_submit_type_my.hide('fast');
div_submit_type_archive.hide('fast');
div_submit_type_bot.show('fast');
$('#form-group-answer_answer').show('fast');
save_prefer_submit_type('bot');
});
input_submit_type_my.click(function() {
div_submit_type_bot.hide('fast');
div_submit_type_archive.hide('fast');
div_submit_type_my.show('fast');
div_account_data.show('fast');
$('#form-group-answer_answer').show('fast');
save_prefer_submit_type('my');
});
input_submit_type_archive.click(function() {
div_submit_type_bot.hide('fast');
div_submit_type_my.hide('fast');
div_submit_type_archive.show('fast');
div_account_data.show('fast');
$('#form-group-answer_answer').hide('fast');
save_prefer_submit_type('archive');
});
if (submit_type[0] == 'bot') {
div_account_data.hide();
div_submit_type_my.hide();
div_submit_type_archive.hide();
div_submit_type_bot.show();
$('#form-group-answer_answer').show();
input_submit_type_bot[0].checked = true;
} else if (submit_type[0] == 'my') {
div_submit_type_bot.hide();
div_submit_type_my.show();
div_submit_type_archive.hide();
div_account_data.show();
$('#form-group-answer_answer').show();
input_submit_type_my[0].checked = true;
} else if (submit_type[0] == 'archive') {
div_submit_type_bot.hide();
div_submit_type_my.hide();
div_submit_type_archive.show();
div_account_data.show();
$('#form-group-answer_answer').hide();
input_submit_type_archive[0].checked = true;
}
if (submit_type.indexOf('bot') == -1) {
input_submit_type_bot.attr('disabled', 'disabled');
} else if (prefer_submit_type == 'bot') {
div_account_data.hide();
div_submit_type_my.hide();
div_submit_type_archive.hide();
div_submit_type_bot.show();
$('#form-group-answer_answer').show();
input_submit_type_bot[0].checked = true;
input_submit_type_my[0].checked = false;
input_submit_type_archive[0].checked = false;
}
if (submit_type.indexOf('my') == -1) {
input_submit_type_my.attr('disabled', 'disabled');
} else if (prefer_submit_type == 'my') {
div_submit_type_bot.hide();
div_submit_type_my.show();
div_submit_type_archive.hide();
div_account_data.show();
$('#form-group-answer_answer').show();
input_submit_type_bot[0].checked = false;
input_submit_type_my[0].checked = true;
input_submit_type_archive[0].checked = false;
}
if (submit_type.indexOf('archive') == -1) {
input_submit_type_archive.attr('disabled', 'disabled');
} else if (prefer_submit_type == 'archive') {
div_submit_type_bot.hide();
div_submit_type_my.hide();
div_submit_type_archive.show();
div_account_data.show();
$('#form-group-answer_answer').hide();
input_submit_type_bot[0].checked = false;
input_submit_type_my[0].checked = false;
input_submit_type_archive[0].checked = true;
}
if (oj == 'luogu') {
2023-02-03 02:47:58 +00:00
var luogu_account_data = {"_uid": "", "__client_id": ""};
var input_luogu_uid = $('<input class="form-control font-monospace" type="text" name="luogu_uid" id="input-luogu_uid" autocomplete="off" />');
var input_luogu_client_id = $('<input class="form-control font-monospace" type="text" name="luogu_client_id" id="input-luogu_client_id" autocomplete="off" />');
if ('localStorage' in window) {
try {
var luogu_account_data_str = localStorage.getItem('uoj_remote_judge_luogu_account_data');
if (luogu_account_data_str) {
luogu_account_data = JSON.parse(luogu_account_data_str);
}
} catch (e) {}
var save_luogu_account_data = function() {
localStorage.setItem('uoj_remote_judge_luogu_account_data', JSON.stringify(luogu_account_data));
}
} else {
var save_luogu_account_data = function() {};
}
input_luogu_uid.change(function() {
luogu_account_data._uid = $(this).val();
input_my_account_data.val(JSON.stringify(luogu_account_data));
save_luogu_account_data();
my_account_validation_status.html('<span class="text-secondary">待验证</span>');
});
2023-02-03 02:47:58 +00:00
input_luogu_client_id.change(function() {
luogu_account_data.__client_id = $(this).val();
input_my_account_data.val(JSON.stringify(luogu_account_data));
save_luogu_account_data();
my_account_validation_status.html('<span class="text-secondary">待验证</span>');
});
my_account_validation_btn.click(function() {
validate_my_account({
type: 'luogu',
_uid: input_luogu_uid.val(),
__client_id: input_luogu_client_id.val(),
});
});
input_my_account_data.val(JSON.stringify(luogu_account_data));
2023-02-03 02:47:58 +00:00
input_luogu_uid.val(luogu_account_data._uid);
input_luogu_client_id.val(luogu_account_data.__client_id);
if (luogu_account_data._uid && luogu_account_data.__client_id){
validate_my_account({
type: 'luogu',
_uid: luogu_account_data._uid,
__client_id: luogu_account_data.__client_id,
});
}
div_account_data.append(
$('<div class="row mt-3 align-items-center" />')
.append($('<div class="col-sm-2" />').append('<label for="input-luogu_uid" class="col-form-label">_uid</label>'))
.append($('<div class="col-sm-4" />').append(input_luogu_uid))
.append($('<div class="col-sm-6" />').append($('<div class="form-text mt-0" />').append('请填入 Cookie 中的 <code>_uid</code>。')))
).append(
$('<div class="row mt-3 align-items-center" />')
.append($('<div class="col-sm-2" />').append('<label for="input-luogu_client_id" class="col-form-label">__client_id</label>'))
2023-02-03 02:47:58 +00:00
.append($('<div class="col-sm-4" />').append(input_luogu_client_id))
.append($('<div class="col-sm-6" />').append($('<div class="form-text mt-0" />').append('请填入 Cookie 中的 <code>__client_id</code>。')))
);
} else if (oj == 'codeforces') {
var codeforces_account_data = {"JSESSIONID": ""};
var input_codeforces_jsessionid = $('<input class="form-control font-monospace" type="text" name="codeforces_jsessionid" id="input-codeforces_jsessionid" autocomplete="off" />');
if ('localStorage' in window) {
try {
var codeforces_account_data_str = localStorage.getItem('uoj_remote_judge_codeforces_account_data');
if (codeforces_account_data_str) {
codeforces_account_data = JSON.parse(codeforces_account_data_str);
}
} catch (e) {}
var save_codeforces_account_data = function() {
localStorage.setItem('uoj_remote_judge_codeforces_account_data', JSON.stringify(codeforces_account_data));
}
}
input_codeforces_jsessionid.change(function() {
codeforces_account_data.JSESSIONID = $(this).val();
input_my_account_data.val(JSON.stringify(codeforces_account_data));
save_codeforces_account_data();
my_account_validation_status.html('<span class="text-secondary">待验证</span>');
});
my_account_validation_btn.click(function() {
validate_my_account({
type: 'codeforces',
JSESSIONID: input_codeforces_jsessionid.val(),
});
});
input_my_account_data.val(JSON.stringify(codeforces_account_data));
input_codeforces_jsessionid.val(codeforces_account_data.JSESSIONID);
if (codeforces_account_data.JSESSIONID) {
validate_my_account({
type: 'codeforces',
JSESSIONID: codeforces_account_data.JSESSIONID,
});
}
div_account_data.append(
$('<div class="row mt-3 align-items-center" />')
.append($('<div class="col-sm-2" />').append('<label for="input-codeforces_jsessionid" class="col-form-label">JSESSIONID</label>'))
.append($('<div class="col-sm-4" />').append(input_codeforces_jsessionid))
.append($('<div class="col-sm-6" />').append($('<div class="form-text mt-0" />').append('请填入 Cookie 中的 <code>JSESSIONID</code>。')))
);
} else if (oj == 'loj') {
var loj_account_data = {username: "", token: ""};
var input_loj_token = $('<input class="form-control font-monospace" type="text" name="loj_token" id="input-loj_token" autocomplete="off" />');
if ('localStorage' in window) {
try {
var loj_account_data_str = localStorage.getItem('uoj_remote_judge_loj_account_data');
if (loj_account_data_str) {
loj_account_data = JSON.parse(loj_account_data_str);
}
} catch (e) {}
var save_loj_account_data = function() {
localStorage.setItem('uoj_remote_judge_loj_account_data', JSON.stringify(loj_account_data));
}
} else {
var save_loj_account_data = function() {};
}
input_loj_token.change(function() {
loj_account_data.token = $(this).val();
input_my_account_data.val(JSON.stringify(loj_account_data));
save_loj_account_data();
my_account_validation_status.html('<span class="text-secondary">待验证</span>');
});
my_account_validation_btn.click(function() {
validate_my_account({
type: 'loj',
token: input_loj_token.val(),
});
});
input_my_account_data.val(JSON.stringify(loj_account_data));
input_loj_token.val(loj_account_data.token);
if (loj_account_data.token) {
validate_my_account({
type: 'loj',
token: loj_account_data.token,
});
}
div_account_data.append(
$('<div class="row mt-3 align-items-center" />')
.append($('<div class="col-sm-2" />').append('<label for="input-loj_token" class="col-form-label">Token</label>'))
.append($('<div class="col-sm-4" />').append(input_loj_token))
.append($('<div class="col-sm-6" />').append($('<div class="form-text mt-0" />').append('请前往 <a href="https://loj.ac" target="_blank">LibreOJ</a> 登录账号,然后输入在控制台中运行 <code>console.log(JSON.parse(localStorage.appState).token)</code> 的输出结果。')))
);
} else if (oj == 'uoj') {
var uoj_account_data = {"UOJSESSID": ""};
var input_uoj_uojsessid = $('<input class="form-control font-monospace" type="text" name="uoj_uojsessid" id="input-uoj_uojsessid" />');
if ('localStorage' in window) {
try {
var uoj_account_data_str = localStorage.getItem('uoj_remote_judge_uoj_account_data');
if (uoj_account_data_str) {
uoj_account_data = JSON.parse(uoj_account_data_str);
}
} catch (e) {}
var save_uoj_account_data = function() {
localStorage.setItem('uoj_remote_judge_uoj_account_data', JSON.stringify(uoj_account_data));
}
}
input_uoj_uojsessid.change(function() {
uoj_account_data.UOJSESSID = $(this).val();
input_my_account_data.val(JSON.stringify(uoj_account_data));
save_uoj_account_data();
my_account_validation_status.html('<span class="text-secondary">待验证</span>');
});
my_account_validation_btn.click(function() {
validate_my_account({
type: 'uoj',
UOJSESSID: input_uoj_uojsessid.val(),
});
});
input_my_account_data.val(JSON.stringify(uoj_account_data));
input_uoj_uojsessid.val(uoj_account_data.UOJSESSID);
if (uoj_account_data.UOJSESSID) {
validate_my_account({
type: 'uoj',
UOJSESSID: uoj_account_data.UOJSESSID,
});
}
div_account_data.append(
$('<div class="row mt-3 align-items-center" />')
.append($('<div class="col-sm-2" />').append('<label for="input-uoj_uojsessid" class="col-form-label">UOJSESSID</label>'))
.append($('<div class="col-sm-4" />').append(input_uoj_uojsessid))
.append($('<div class="col-sm-6" />').append($('<div class="form-text mt-0" />').append('请填入 Cookie 中的 <code>UOJSESSID</code>。')))
);
}
$(this).append(
$('<div class="mt-3" />').append(
$('<div class="form-check d-inline-block" />')
.append(input_submit_type_bot)
.append($('<label class="form-check-label" for="' + input_submit_type_bot_id + '" />').append(' 公用账号'))
).append(
$('<div class="form-check d-inline-block ms-3" />')
.append(input_submit_type_my)
.append($('<label class="form-check-label" for="' + input_submit_type_my_id + '" />').append(' 自有账号'))
).append(
$('<div class="form-check d-inline-block ms-3" />')
.append(input_submit_type_archive)
.append($('<label class="form-check-label" for="' + input_submit_type_archive_id + '" />').append(' 归档'))
)
)
.append(div_submit_type_bot)
.append(div_submit_type_my)
.append(div_submit_type_archive)
.append(div_account_data)
.append(input_my_account_data);
});
}
// problem_configure: print problem.conf
$.fn.problem_conf_preview = function(problem_conf) {
return $(this).each(function() {
var keys = Object.keys(problem_conf);
var res = '';
for (var i = 0; i < keys.length; i++) {
var key = keys[i];
var value = problem_conf[key];
if (!value) {
continue;
}
if (key == 'use_builtin_judger' && value == 'off') {
continue;
}
if (key == 'use_builtin_checker' && value == 'ownchk') {
continue;
}
res += key + ' ' + value + '\n';
}
2023-02-23 10:28:20 +00:00
$(this).html('<pre class="bg-body-tertiary mb-0 p-3"><code>' + res + '</code></pre>');
});
}
// problem_configure: point scores
$.fn.problem_configure_point_scores = function(problem_conf) {
return $(this).each(function() {
var _this = this;
var n_tests = parseInt(problem_conf['n_tests']);
$(this).empty();
if (isNaN(n_tests) || n_tests <= 0) {
$(this).html('不可用。');
return;
}
for (var i = 1; i <= n_tests; i++) {
var input_point_score = $('<input class="form-control form-control-sm uoj-problem-configure-point-score-input" type="number" name="point_score_' + i + '" id="input-point_score_' + i + '" min="0" max="100" />');
if (problem_conf['point_score_' + i]) {
input_point_score.val(problem_conf['point_score_' + i]);
}
(function(i){
input_point_score.change(function() {
problem_conf['point_score_' + i] = $(this).val();
$('#problem-conf-preview').problem_conf_preview(problem_conf);
});
})(i);
$(this).append(
$('<div class="col-sm-6" />').append(
$('<div class="" />')
.append($('<div class="" />').append('<label for="input-point_score_' + i + '" class="col-form-label col-form-label-sm">测试点 #' + i + '</label>'))
.append($('<div class="" />').append(input_point_score))
)
);
}
$('.uoj-problem-configure-point-score-input', this).change(function() {
var full_score = 100;
var rest_tests = parseInt(problem_conf['n_tests'] || '10');
var score_type = problem_conf['score_type'] || 'int';
$('.uoj-problem-configure-point-score-input', _this).each(function() {
var point_score = parseInt($(this).val());
if (!isNaN(point_score)) {
full_score -= point_score;
rest_tests--;
}
});
$('.uoj-problem-configure-point-score-input', _this).each(function() {
if ($(this).val() == '') {
var val = full_score / rest_tests;
if (score_type == 'int') {
val = Math.floor(val);
} else {
var decimal_places = parseInt(score_type.substring(5));
val = val.toFixed(decimal_places);
}
$(this).attr('placeholder', val);
}
});
});
$('.uoj-problem-configure-point-score-input', this).first().trigger('change');
});
};
// problem_configure: subtasks
$.fn.problem_configure_subtasks = function(problem_conf) {
return $(this).each(function() {
var _this = this;
var n_subtasks = parseInt(problem_conf['n_subtasks'] || '0');
$(this).empty();
if (isNaN(n_subtasks)) {
$(this).html('不可用。');
return;
}
var input_n_subtasks = $('<input class="form-control" type="number" name="n_subtasks" id="input-n_subtasks" />');
var div_subtasks = $('<div class="list-group list-group-flush border-top" />');
if (n_subtasks) {
input_n_subtasks.val(n_subtasks);
}
$(this).append(
$('<div class="m-3" />').append(
$('<div class="row" />').append(
$('<div class="col-4" />').append('<label for="input-n_subtasks" class="col-form-label">子任务数</label>')
).append(
$('<div class="col-8" />').append(input_n_subtasks)
)
)
).append(div_subtasks);
input_n_subtasks.change(function() {
div_subtasks.empty();
var n_subtasks = parseInt(input_n_subtasks.val() || '0');
var n_tests = parseInt(problem_conf['n_tests'] || '10');
problem_conf['n_subtasks'] = input_n_subtasks.val();
for (var i = 1; i <= n_subtasks; i++) {
var input_subtask_type = $('<select class="form-select form-select-sm" name="subtask_type_' + i + '" id="input-subtask_type_' + i + '" />');
var input_subtask_end = $('<input class="form-control form-control-sm uoj-problem-configure-subtask-end-input" type="number" name="subtask_end_' + i + '" id="input-subtask_end_' + i + '" min="0" max="' + n_tests + '" />');
var input_subtask_score = $('<input class="form-control form-control-sm uoj-problem-configure-subtask-score-input" type="number" name="subtask_score_' + i + '" id="input-subtask_score_' + i + '" min="0" max="100" />');
var input_subtask_used_time_type = $('<select class="form-select form-select-sm" name="subtask_used_time_type_' + i + '" id="input-subtask_used_time_type_' + i + '" />');
input_subtask_type
.append($('<option value="packed" />').text('错一个就零分'))
.append($('<option value="min" />').text('取所有测试点中的最小值'));
input_subtask_used_time_type
.append($('<option value="sum" />').text('全部相加'))
.append($('<option value="max" />').text('取所有测试点中的最大值'));
(function(i) {
input_subtask_type.change(function() {
problem_conf['subtask_type_' + i] = $(this).val();
$('#problem-conf-preview').problem_conf_preview(problem_conf);
});
input_subtask_end.change(function() {
problem_conf['subtask_end_' + i] = $(this).val();
$('#problem-conf-preview').problem_conf_preview(problem_conf);
})
input_subtask_score.change(function() {
problem_conf['subtask_score_' + i] = $(this).val();
$('#problem-conf-preview').problem_conf_preview(problem_conf);
});
input_subtask_used_time_type.change(function() {
problem_conf['subtask_used_time_type_' + i] = $(this).val();
$('#problem-conf-preview').problem_conf_preview(problem_conf);
});
})(i);
if (problem_conf['subtask_type_' + i]) {
input_subtask_type.val(problem_conf['subtask_type_' + i]);
}
if (problem_conf['subtask_end_' + i]) {
input_subtask_end.val(problem_conf['subtask_end_' + i]);
}
if (problem_conf['subtask_score_' + i]) {
input_subtask_score.val(problem_conf['subtask_score_' + i]);
}
if (problem_conf['subtask_used_time_type_' + i]) {
input_subtask_used_time_type.val(problem_conf['subtask_used_time_type_' + i]);
}
div_subtasks.append(
$('<div class="list-group-item" />').append(
$('<div class="fw-bold" />').text('Subtask #' + i)
).append(
$('<div />').append(
$('<div class="row mt-2" />').append(
$('<div class="col-sm-6" />').append('<label for="input-subtask_type_' + i + '" class="col-form-label col-form-label-sm">评分类型</label>')
).append(
$('<div class="col-sm-6" />').append(input_subtask_type)
)
).append(
$('<div class="row mt-2" />').append(
$('<div class="col-sm-6" />').append('<label for="input-subtask_end_' + i + '" class="col-form-label col-form-label-sm">最后一个测试点的编号</label>')
).append(
$('<div class="col-sm-6" />').append(input_subtask_end)
)
).append(
$('<div class="row mt-2" />').append(
$('<div class="col-sm-6" />').append('<label for="input-subtask_score_' + i + '" class="col-form-label col-form-label-sm">分数</label>')
).append(
$('<div class="col-sm-6" />').append(input_subtask_score)
)
).append(
$('<div class="row mt-2" />').append(
$('<div class="col-sm-6" />').append('<label for="input-subtask_used_time_type_' + i + '" class="col-form-label col-form-label-sm">程序用时统计方式</label>')
).append(
$('<div class="col-sm-6" />').append(input_subtask_used_time_type)
)
)
)
);
}
$('.uoj-problem-configure-subtask-score-input', _this).change(function() {
var full_score = 100;
var rest_subtasks = parseInt(problem_conf['n_subtasks'] || '10');
var score_type = problem_conf['score_type'] || 'int';
$('.uoj-problem-configure-subtask-score-input', _this).each(function() {
var subtask_score = parseInt($(this).val());
if (!isNaN(subtask_score)) {
full_score -= subtask_score;
rest_subtasks--;
}
});
$('.uoj-problem-configure-subtask-score-input', _this).each(function() {
if ($(this).val() == '') {
var val = full_score / rest_subtasks;
if (score_type == 'int') {
val = Math.floor(val);
} else {
var decimal_places = parseInt(score_type.substring(5));
val = val.toFixed(decimal_places);
}
$(this).attr('placeholder', val);
}
});
});
$('.uoj-problem-configure-subtask-score-input', _this).first().trigger('change');
$('#problem-conf-preview').problem_conf_preview(problem_conf);
});
input_n_subtasks.trigger('change');
});
};
2016-07-18 16:39:37 +00:00
// custom test
function custom_test_onsubmit(response_text, div_result, url) {
if (response_text != '') {
$(div_result).html('<div class="text-danger">' + response_text + '</div>');
return;
}
var update = function() {
var can_next = true;
$.get(url,
function(data) {
if (data.judged === undefined) {
$(div_result).html('<div class="text-danger">error</div>');
} else {
var judge_status = $('<table class="table table-bordered table-text-center"><tr class="info">' + data.html + '</tr></table>');
$(div_result).empty();
$(div_result).append(judge_status);
if (data.judged) {
var judge_result = $(data.result);
judge_result.css('display', 'none');
$(div_result).append(judge_result);
judge_status.hide(500);
judge_result.slideDown(500);
can_next = false;
}
}
}, 'json')
.always(function() {
if (can_next) {
setTimeout(update, 500);
}
});
};
setTimeout(update, 500);
}
2023-03-14 08:55:11 +00:00
// markdown input editor
$.fn.markdown_input_editor = function(name, type, text) {
return this.each(function() {
var input_editor_name = name;
var input_editor_id = 'input-' + name + '_editor';
var spinner_id = 'spinner-' + name + '_editor';
var div_editor_id = 'div-' + name + '_editor';
var div_preview_id = 'div-' + name + '_preview';
var btn_editor = $('<button class="nav-link" type="button" />').attr('data-bs-target', '#' + div_editor_id + '_edit').attr('data-bs-toggle', 'tab').text(uojLocale('editor::edit')).addClass('active');
var btn_preview = $('<button class="nav-link" type="button" />').attr('data-bs-target', '#' + div_editor_id + '_preview').attr('data-bs-toggle', 'tab').text(uojLocale('editor::preview'));
var div_editor = $('<div id="' + div_editor_id + '" style="height: 350px" />')
.append(
$('<div id="' + spinner_id + '" class="d-flex justify-content-center align-items-center" style="width: 100%; height: 350px;" />')
.append('<div class="spinner-border text-muted" style="width: 3rem; height: 3rem;" />')
);
var div_preview = $('<div id="' + div_preview_id + '" style="min-height: 350px" />');
var monaco_editor_instance = null;
var monaco_editor_init = function() {
require_monaco({ markdown: true }, function() {
if (monaco_editor_instance != null) {
return;
}
$(div_editor).empty();
monaco_editor_instance = monaco.editor.create(div_editor[0], {
language: 'markdown-math',
automaticLayout: true,
fontSize: "16px",
minimap: {
enabled: false,
},
wordWrap: 'on',
unicodeHighlight: {
ambiguousCharacters: false,
},
});
$('#' + spinner_id).css('display', 'none !important');
$(div_editor).addClass('overflow-hidden rounded-bottom').show();
monaco_editor_instance.getModel().setValue(text);
monaco_editor_instance.onDidChangeModelContent(function () {
$('#' + input_editor_id).val(monaco_editor_instance.getModel().getValue());
});
require(['MonacoMarkdown'], function(MonacoMarkdown) {
var extension = new MonacoMarkdown.MonacoMarkdownExtension();
extension.activate(monaco_editor_instance);
});
});
}
$(this)
.append(
$('<div class="card" />')
.append(
$('<div class="card-header" />').append(
$('<ul class="nav nav-tabs card-header-tabs">')
.append($('<li class="nav-item" />').append(btn_editor))
.append($('<li class="nav-item" />').append(btn_preview))
)
)
.append(
$('<div class="card-body tab-content p-0" />')
.append(
$('<div class="tab-pane active" />')
.attr('id', div_editor_id + '_edit')
.append(div_editor)
)
.append(
$('<div class="tab-pane" />')
.attr('id', div_editor_id + '_preview')
.append(div_preview)
)
)
)
.append($('<input type="hidden" name="' + input_editor_name + '" id="' + input_editor_id + '"/>').val(text));
bootstrap.Tab.jQueryInterface.call(btn_editor);
bootstrap.Tab.jQueryInterface.call(btn_preview).on('shown.bs.tab', function () {
$(div_preview)
.empty()
.append(
$('<div class="d-flex justify-content-center align-items-center" style="width: 100%; height: 350px;" />')
.append('<div class="spinner-border text-muted" style="width: 3rem; height: 3rem;" />')
);
var render = function () {
$.ajax({
url: '/api/markdown',
type: 'POST',
dataType: 'text',
data: {
markdown: $('#' + input_editor_id).val(),
purifier_type: type,
parsedown_type: type,
},
success: function (html) {
$(div_preview).empty().append($('<div class="markdown-body p-3" />').html(html)).uoj_highlight();
if (window.MathJax) window.MathJax.typeset();
},
error: function () {
var btn_retry = $('<button type="button" class="btn btn-link p-0 alert-link" />').text('retry').click(function() {
$(div_preview)
.empty()
.append(
$('<div class="d-flex justify-content-center align-items-center" style="width: 100%; height: 350px;" />')
.append('<div class="spinner-border text-muted" style="width: 3rem; height: 3rem;" />')
);
render();
});
$(div_preview).empty().append(
$('<div class="m-3 alert alert-danger" />')
.append('<span>Render failed, </span>')
.append('<span>please </span>')
.append(btn_retry)
);
},
});
}
render();
});
var check_monaco_editor_init = function() {
if (div_editor.is(':visible')) {
monaco_editor_init();
} else {
setTimeout(check_monaco_editor_init, 1);
}
}
check_monaco_editor_init();
});
}
2023-02-07 10:38:24 +00:00
// hide comment
function toggleModalHideComment(id, content) {
$('#input-comment_hide_id').val(id);
$('#span-comment_hide_id').text(id);
$('#HideCommentModalOriginalComment').html(content);
$('#HideCommentModal').modal('show');
}
2016-07-18 16:39:37 +00:00
// comment
function showCommentReplies(id, replies) {
var toggleFormReply = function(from, text) {
if (text == undefined) {
text = '';
}
var p = '#comment-body-' + id;
var q = '#div-form-reply';
var r = '#input-reply_comment';
var t = '#input-reply_id';
if ($(q).data('from') != from) {
$(q).data('from', from);
$(q).hide('fast', function() {
$(this).appendTo(p).show('fast', function() {
$(t).val(id);
$(r).val(text).focus();
});
});
} else if ($(q).css('display') != 'none') {
$(q).appendTo(p).hide('fast');
} else {
$(q).appendTo(p).show('fast', function() {
$(t).val(id);
$(r).val(text).focus();
});
}
}
$('#reply-to-' + id).click(function(e) {
e.preventDefault();
toggleFormReply(id);
});
if (replies.length == 0) {
return;
}
$("#replies-" + id).long_table(
replies,
1,
'<tr>' +
'<th>评论回复</th>' +
'</tr>',
function(reply) {
return $('<tr id="' + 'comment-' + reply.id + '" />').append(
$('<td />').append(
2023-02-24 14:10:29 +00:00
$('<div class="d-flex" />').append(
$('<div class="d-none d-sm-block mr-3 flex-shrink-0" />').append(
$('<a />').append(
$('<img class="rounded uoj-user-avatar" width="64" height="64" />').attr('src', reply.poster_avatar)
).attr('href', uojHome + '/user/' + reply.poster)
)
2023-02-07 10:38:24 +00:00
).append(
2023-02-24 14:10:29 +00:00
$('<div id="comment-body-' + reply.id + '" class="flex-grow-1 ms-3" />').append(
$('<div class="row justify-content-between flex-wrap g-0" />').append(
$('<div class="col-auto" />').append(getUserLink(reply.poster, reply.poster_realname, reply.poster_username_color))
).append(
$('<div class="col-auto" />').append(reply.click_zan_block)
)
).append(
$('<div class="comment-content markdown-body my-2" />').attr('id', 'comment-content-' + reply.id).html(reply.content)
).append(
$('<ul class="text-end mb-0 list-inline" />').append(
'<li class="list-inline-item small text-muted">' + reply.post_time + '</li>'
).append(
user_can_hide_comment
? $('<li class="list-inline-item" />').append(
$('<a href="#" class="text-warning-emphasis text-decoration-none p-0" />').data('comment-id', reply.id).text('隐藏').click(function(event) {
event.preventDefault();
toggleModalHideComment(reply.id, reply.content);
})
)
: ''
).append(
$('<li class="list-inline-item" />').append(
$('<a href="#">回复</a>').click(function (e) {
e.preventDefault();
toggleFormReply(reply.id, '回复 @' + reply.poster + '');
})
)
2023-02-07 10:38:24 +00:00
)
2016-07-18 16:39:37 +00:00
)
)
)
).uoj_highlight();
}, {
2023-02-01 13:30:36 +00:00
table_classes: ['table'],
2016-07-18 16:39:37 +00:00
page_len: 5,
prevent_focus_on_click: true
}
);
}
2023-01-11 02:48:20 +00:00
2023-02-07 12:41:37 +00:00
function getACMStandingsMeta() {
var stat = {};
var full_score = 0;
for (var k = 0; k < problems.length; k++) {
var pid = problems[k];
stat[pid] = {};
stat[pid].cnt = 0;
stat[pid].ac_cnt = 0;
stat[pid].earliest = null;
if (("problem_" + pid) in bonus) {
for (var j in score) {
if (score[j][k] != undefined) {
stat[pid].cnt += score[j][k][3];
if (score[j][k][1] === -1200) {
stat[pid].ac_cnt++;
}
}
}
} else {
full_score += 100;
for (var j in score) {
if (score[j][k] != undefined) {
stat[pid].cnt += score[j][k][3];
if (score[j][k][0] === 100) {
stat[pid].ac_cnt++;
if (stat[pid].earliest === null || score[j][k][2] < stat[pid].earliest) {
stat[pid].earliest = score[j][k][2];
}
}
}
}
}
}
return { stat, full_score };
}
function setACMStandingsTH(th, i, meta) {
if (i == -3) {
return $(th).css('width', '3em').text('#');
2023-02-07 12:41:37 +00:00
} else if (i == -2) {
return $(th).css('width', '14em').text(uojLocale('username'));
2023-02-07 12:41:37 +00:00
} else if (i == -1) {
return $(th).css('width', '5em').text(uojLocale('contests::total score'));
2023-02-07 12:41:37 +00:00
}
var pid = problems[i];
$(th).css('width', '5em');
2023-02-07 12:41:37 +00:00
if (("problem_" + pid) in bonus) {
$(th).attr('title', '附加题,通过后减免 20 分钟罚时');
}
var th_str = '<div><a href="/contest/' + contest_id + '/problem/' + pid + '">' + String.fromCharCode('A'.charCodeAt(0) + i);
if (("problem_" + pid) in bonus) {
th_str += '*';
}
th_str += '</a></div>';
if (meta && pid in meta.stat) {
th_str += '<div>' + meta.stat[pid].ac_cnt + '/' + meta.stat[pid].cnt + '</div>';
}
return $(th).html(th_str);
}
function setACMStandingsTD(td, row, i, meta) {
if (i == -3) {
return $(td).attr('class', '').html(row[3]);
} else if (i == -2) {
if (2 in row[2] && row[2][2]) {
let td_title = row[2][2]['team_name'] + "\n";
for (var i = 0; i < row[2][2]['members'].length; i++) {
td_title += row[2][2]['members'][i]['name'];
td_title += " ";
td_title += row[2][2]['members'][i]['organization'];
td_title += "";
if (i < row[2][2]['members'].length - 1) {
td_title += "\n";
}
}
return $(td).attr('class', '').attr('title', td_title).html(
'<div class="text-center" style="overflow-wrap:anywhere;">' +
'<small><strong>' + htmlspecialchars(row[2][2]['team_name']) + '</strong></small>' +
'</div>' +
'<div>' +
'<small>' + getUserLink(row[2][0], row[2][1], row[2][3]) + '</small>' +
'</div>'
);
} else {
return $(td).attr('class', '').html(getUserLink(row[2][0], row[2][1], row[2][3]));
}
} else if (i == -1) {
let td_title = "总分:" + row[0] + "\n";
td_title += "罚时:" + row[1] + ",即 " + getPenaltyTimeStr(row[1]);
return $(td).attr('class', 'standings-score-td').attr('title', td_title).html(
'<div>' +
'<span class="uoj-score" data-max="' + meta.full_score + '" style="color:' + getColOfScore(row[0] * 100 / meta.full_score) + '">' +
row[0] +
'</span>' +
'</div>' +
'<div>' +
'<small>' + getPenaltyTimeStr(row[1]) + '</small>' +
'</div>'
);
}
var col = score[row[2][0]][i];
$(td).attr('class', 'standings-score-td');
if (col === undefined) {
return $(td).html('');
}
var td_title = String.fromCharCode('A'.charCodeAt(0) + i) + "题\n";
var td_content = '';
if (("problem_" + problems[i]) in bonus) {
td_content += '<div>';
if (col[0] !== null) {
if (col[1] == -1200) {
td_content += '<a href="/submission/' + col[2] + '" class="uoj-score" data-score="100" style="color:' + getColOfScore(100) + '">';
td_content += '+';
td_content += '</a>';
td_title += col[3] + " 次有效提交后通过,减免罚时 20 分钟";
} else {
td_content += '<a href="/submission/' + col[2] + '" class="uoj-score" data-score="0" style="color:' + getColOfScore(0) + '">';
td_content += 0;
td_content += '</a>';
td_title += "尚未通过,未减免罚时";
td_title += "\n" + col[3] + " 次有效提交";
}
if (col[5] > 0) {
td_content += ' + ';
td_title += "\n" + "因封榜有 " + col[5] + " 次提交结果未知";
}
} else {
td_title += "封榜后提交了 " + col[5] + " 次,结果未知";
}
if (col[5] > 0) {
td_content += '<strong class="text-muted">?</strong>';
}
td_content += '</div>';
if (col[4] > 0) {
td_content += '<div><small>';
td_content += '(+' + col[4] + ')';
td_content += '</small></div>';
}
} else {
td_content += '<div>';
if (col[0] !== null) {
td_content += '<a href="/submission/' + col[2] + '" class="uoj-score" style="color:' + getColOfScore(col[0]) + '">';
td_content += col[0];
td_content += '</a>';
td_title += "得分:" + col[0] + " 分";
td_title += "\n" + col[3] + " 次有效提交";
if (col[5] > 0) {
td_content += ' + ';
td_title += "\n" + "因封榜有 " + col[5] + " 次提交结果未知";
}
} else {
td_title += "封榜后提交了 " + col[5] + " 次,结果未知";
}
if (col[5] > 0) {
td_content += '<strong class="text-muted">?</strong>';
}
td_content += '</div>';
if (col[0] > 0) {
let orig_penalty = col[1] - col[4] * 60 * 20;
td_content += '<div><small>' + getPenaltyTimeStr(orig_penalty) + '</small></div>';
if (col[4] > 0) {
td_title += "\n" + col[4] + " 次提交计入罚时";
}
td_title += "\n" + "罚时:" + orig_penalty;
if (col[4] > 0) {
td_title += " + " + col[4] + " × 1200 = " + col[1];
}
td_title += ",即 " + getPenaltyTimeStr(orig_penalty);
}
if (col[4] > 0) {
td_content += '<div><small>';
td_content += '(+' + col[4] + ')';
td_content += '</small></div>';
}
}
if (meta.stat[problems[i]].earliest === col[2]) {
$(td).addClass('first-blood table-success');
}
return $(td).attr('title', td_title).html(td_content);
}
// standings
function showStandings() {
if (contest_rule == 'OI' || contest_rule == 'IOI' || after_contest) {
2023-02-07 12:41:37 +00:00
$("#standings").long_table(
standings,
1,
'<tr>' +
'<th style="width:5em">#</th>' +
'<th style="width:14em">'+uojLocale('username')+'</th>' +
'<th style="width:5em">'+uojLocale('contests::total score')+'</th>' +
$.map(problems, function(col, idx) {
return '<th style="width:8em;">' + '<a href="/contest/' + contest_id + '/problem/' + col + '">' + String.fromCharCode('A'.charCodeAt(0) + idx) + '</a>' + '</th>';
}).join('') +
'</tr>',
function(row) {
var col_tr = '';
if (myname != row[2][0]) {
col_tr += '<tr>';
} else {
col_tr += '<tr class="table-warning">';
}
col_tr += '<td>' + row[3] + '</td>';
col_tr += '<td>' + getUserLink(row[2][0], row[2][1], row[2][3]) + '</td>';
col_tr += '<td>' + '<div><span class="uoj-score" data-max="' + problems.length * 100 + '" style="color:' + getColOfScore(row[0] / problems.length) + '">' + row[0] + '</span></div>' + (after_contest ? '' : '<div class="small">' + getPenaltyTimeStr(row[1]) + '</div>') + '</td>';
2023-02-07 12:41:37 +00:00
for (var i = 0; i < problems.length; i++) {
col_tr += '<td>';
col = score[row[2][0]][i];
if (col != undefined) {
col_tr += '<div><a href="/submission/' + col[2] + '" class="uoj-score" style="color:' + getColOfScore(col[0]) + '">' + col[0] + '</a></div>';
if (!after_contest) {
if (standings_version < 2) {
2023-02-07 12:41:37 +00:00
col_tr += '<div class="small">' + getPenaltyTimeStr(col[1]) + '</div>';
} else {
if (col[0] > 0) {
col_tr += '<div class="small">' + getPenaltyTimeStr(col[1]) + '</div>';
}
2023-02-07 12:41:37 +00:00
}
}
}
col_tr += '</td>';
}
col_tr += '</tr>';
return col_tr;
}, {
div_classes: standings_config.div_classes ? standings_config.div_classes : ['table-responsive', 'card', 'my-3'],
table_classes: standings_config.table_classes ? standings_config.table_classes : ['table', 'table-bordered', 'text-center', 'align-middle', 'uoj-table', 'uoj-standings-table', 'mb-0'],
page_len: standings_config.page_len ? standings_config.page_len : 50,
top_pagination: true,
print_after_table: function() {
return '<div class="card-footer bg-transparent text-end text-muted">' + uojLocale("contests::n participants", standings.length) + '</div>';
}
}
);
} else if (contest_rule == 'ACM') {
var meta = getACMStandingsMeta();
var header = $('<tr />');
for (let i = -3; i < problems.length; i++) {
header.append(setACMStandingsTH(document.createElement('th'), i, meta));
}
$("#standings").long_table(
standings,
1,
header,
function(row) {
var tr = $('<tr />'); // .css('height', '57px');
if (myname == row[2][0]) {
tr.addClass('table-warning');
}
for (let i = -3; i < problems.length; i++) {
tr.append(setACMStandingsTD(document.createElement('td'), row, i, meta));
}
return tr;
}, {
div_classes: standings_config.div_classes ? standings_config.div_classes : ['table-responsive', 'card', 'my-3'],
table_classes: standings_config.table_classes ? standings_config.table_classes : ['table', 'table-bordered', 'text-center', 'align-middle', 'uoj-table', 'uoj-standings-table', 'mb-0'],
page_len: standings_config.page_len ? standings_config.page_len : 50,
top_pagination: true,
print_after_table: function() {
return '<div class="card-footer bg-transparent text-end text-muted">' + uojLocale("contests::n participants", standings.length) + '</div>';
}
}
);
}
}
2023-02-02 03:19:35 +00:00
// PDF
$(document).ready(function() {
$('div[data-pdf]').each(function() {
$(this).append(
$('<div class="uoj-pdf-loading-spinner border d-flex flex-column justify-content-center align-items-center" style="width: 100%; height: 350px;" />')
.append('<div class="spinner-border text-muted" style="width: 3rem; height: 3rem;" />')
.append('<div class="mt-3">Loading PDF...</div>')
);
});
if ($('div[data-pdf]').length > 0) {
$LAB.script('/js/pdf.js').wait(function() {
pdfjsLib.GlobalWorkerOptions.workerSrc = '/js/pdf.worker.js';
2023-02-02 03:19:35 +00:00
// Support HiDPI-screens.
var outputScale = window.devicePixelRatio || 1;
2023-02-02 03:19:35 +00:00
$('div[data-pdf]').each(function() {
var _this = $(this);
var pdf_src = $(this).data('src');
2023-02-02 03:19:35 +00:00
$(this).css('width', '100%').css('height', '100%');
2023-02-02 03:19:35 +00:00
var task = pdfjsLib.getDocument({
url: pdf_src,
cMapUrl: '/fonts/pdfjs-cmaps/',
cMapPacked: true,
});
var id = 'pdf_' + task.docId;
2023-02-02 03:19:35 +00:00
$(this).attr('id', id + '_container');
2023-02-02 03:19:35 +00:00
task.promise.then(function(pdf) {
for (var i = 1; i <= pdf.numPages; i++) {
$(_this).append('<canvas id="' + id + '_page_' + i + '" class="pdf-page-canvas"></canvas>');
2023-02-02 03:19:35 +00:00
pdf.getPage(i).then(function(page) {
var viewport = page.getViewport({
scale: 2.5,
});
2023-02-02 03:19:35 +00:00
var canvas = document.getElementById(id + '_page_' + page.pageNumber);
2023-02-02 03:19:35 +00:00
canvas.height = Math.floor(viewport.height * outputScale);
canvas.width = Math.floor(viewport.width * outputScale);
2023-02-02 03:19:35 +00:00
var transform = outputScale !== 1
? [outputScale, 0, 0, outputScale, 0, 0]
: null;
2023-02-02 03:19:35 +00:00
page.render({
canvasContext: canvas.getContext('2d'),
viewport: viewport,
transform: transform,
});
2023-02-02 03:19:35 +00:00
});
}
2023-02-02 03:19:35 +00:00
$('.uoj-pdf-loading-spinner', _this).remove();
});
2023-02-02 03:19:35 +00:00
});
});
}
2023-02-02 03:19:35 +00:00
});
2023-01-11 02:48:20 +00:00
// Tooltip
$(document).ready(function() {
2023-01-16 07:34:51 +00:00
bootstrap.Tooltip.jQueryInterface.call($('[data-bs-toggle="tooltip"]'));
2023-01-11 02:48:20 +00:00
});
// Popovers
$(document).ready(function() {
2023-01-16 07:34:51 +00:00
bootstrap.Popover.jQueryInterface.call($('[data-bs-toggle="popover"]'));
});
2023-01-11 02:48:20 +00:00
// Copy button
$(document).ready(function() {
$('.markdown-body pre, .copy-button-container pre').each(function () {
var thisEl = $(this);
$(this).wrap(
$('<div class="wrapped-copy-button-container" style="position: relative;"></div>')
).parent().prepend(
$(
'<div style="position: absolute; right: 0; top: 0; margin-top: 0.75rem; margin-right: 0.75rem; font-size: 0.85em;"></div>'
).append(
$('<button style="position: relative; background: transparent; border: 0;"></button>')
.click(function () {
navigator.clipboard
.writeText($(thisEl).text())
.then(() => {
$(this).html('<i class="bi bi-check2 text-success"></i>');
setTimeout(() => {
$(this).html('<i class="bi bi-clipboard text-muted"></i>');
}, 1000);
})
.catch(() => {
$(this).html('<i class="bi bi-x-lg text-danger"></i>');
setTimeout(() => {
$(this).html('<i class="bi bi-clipboard text-muted"></i>');
}, 1000);
});
})
.append('<i class="bi bi-clipboard text-muted"></i>')
)
);
});
});
2023-02-07 11:36:48 +00:00
2023-02-23 10:28:20 +00:00
/**
* Fallback user avatar
*/
2023-02-07 11:36:48 +00:00
$(document).ready(function() {
$('img.uoj-user-avatar').on('error', function() {
2023-02-23 10:28:20 +00:00
// same as gravatar d=mm
2023-02-07 11:36:48 +00:00
$(this).attr('src', 'data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCA4NzIgODcyIj48cGF0aCBmaWxsPSIjZmZmIiBkPSJNMCAwaDg3MnY4NzJIMHoiLz48cGF0aCBmaWxsPSIjYzVjNWM1IiBkPSJNMCAwdjg3MmgxMTBhMzI3IDM4MyAwIDAxMjM2LTM0NSAxOTUgMTk1IDAgMDEtMTA0LTE3MiAxOTUgMTk1IDAgMDExOTUtMTk1IDE5NSAxOTUgMCAwMTE5NSAxOTUgMTk1IDE5NSAwIDAxLTEwNiAxNzMgMzI3IDM4MyAwIDAxMjM2IDM0NGgxMTBWMHoiLz48L3N2Zz4=');
});
});
2023-02-23 10:28:20 +00:00
function getPreferredTheme() {
if (!('localStorage' in window)) return 'light';
var storedTheme = localStorage.getItem('theme');
if (storedTheme) {
return storedTheme;
}
return window.matchMedia('(prefers-color-scheme: dark)').matches ? 'dark' : 'light';
}
/**
* Theme toggler
*/
(function() {
if (!('localStorage' in window)) return;
var storedTheme = localStorage.getItem('theme');
function setTheme(theme) {
if (theme === 'auto' && window.matchMedia('(prefers-color-scheme: dark)').matches) {
document.documentElement.setAttribute('data-bs-theme', 'dark');
update_monaco_theme('dark');
} else {
document.documentElement.setAttribute('data-bs-theme', theme);
update_monaco_theme(theme == 'auto' ? 'light' : theme);
}
}
setTheme(getPreferredTheme());
function showActiveTheme(theme) {
var currentIcon = $('.theme-icon-active').attr('data-icon');
var newIcon = $('[data-bs-theme-value="' + theme +'"] .theme-icon').attr('data-icon');
$('[data-bs-theme-value]').removeClass('active');
$('[data-bs-theme-value="' + theme +'"]').addClass('active');
$('.theme-icon-active')
.removeClass(currentIcon)
.addClass(newIcon)
.attr('data-icon', newIcon);
}
window.matchMedia('(prefers-color-scheme: dark)').addEventListener('change', function() {
if (storedTheme !== 'light' || storedTheme !== 'dark') {
setTheme(getPreferredTheme());
}
});
$(document).ready(function() {
showActiveTheme(getPreferredTheme());
$('[data-bs-theme-value]').click(function() {
var theme = $(this).data('bs-theme-value');
localStorage.setItem('theme', theme);
setTheme(theme);
showActiveTheme(theme);
});
});
})();