You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
485 lines
20 KiB
485 lines
20 KiB
<% include util %> |
|
<% |
|
if (typeof contest === 'undefined') contest = null; |
|
if (contest) { |
|
this.title = this.alpha(pid) + '. ' + syzoj.utils.removeTitleTag(problem.title) + ' - ' + contest.title + ' - 比赛'; |
|
} else { |
|
this.title = problem.title + ' - 题目'; |
|
} |
|
%> |
|
<% include header %> |
|
<style> |
|
.ace_cursor { |
|
border-left-width: 1px !important; |
|
color: #000 !important; |
|
} |
|
|
|
#languages-menu::-webkit-scrollbar, #testcase-menu::-webkit-scrollbar { |
|
width: 0px; |
|
background: transparent; |
|
} |
|
|
|
div[class*=ace_br] { |
|
border-radius: 0 !important; |
|
} |
|
</style> |
|
<script src="/libs/ace/ace.js"></script> |
|
<div class="ui center aligned grid"> |
|
<div class="row"> |
|
<h1 class="ui header"> |
|
<% if (contest) { %> |
|
<%= this.alpha(pid) %>. <%= syzoj.utils.removeTitleTag(problem.title) %> |
|
<% } else { %> |
|
#<%= problem.id %>. <%= problem.title %><% if (problem.allowedEdit && !problem.is_public) { %><span class="ui tiny red label">未公开</span><% } %> |
|
<% } %> |
|
</h1> |
|
</div> |
|
<% if (problem.type !== 'submit-answer') { %> |
|
<div class="row" style="margin-top: -15px"> |
|
<span class="ui label">内存限制:<%= problem.memory_limit %> MiB</span> |
|
<span class="ui label">时间限制:<%= problem.time_limit %> ms</span> |
|
<% if (problem.file_io) { %> |
|
<span class="ui label">输入文件: <%= problem.file_io_input_name %></span> |
|
<span class="ui label">输出文件: <%= problem.file_io_output_name %></span> |
|
<% } else { %> |
|
<span class="ui label">标准输入输出</span> |
|
<% } %> |
|
</div> |
|
<% } %> |
|
<div class="row" style="margin-top: -<%= problem.type === 'submit-answer' ? 15 : 23 %>px"> |
|
<span class="ui label">题目类型:<%= { 'submit-answer': '答案提交', 'interaction': '交互', 'traditional': '传统' }[problem.type] %></span> |
|
<span class="ui label">评测方式:<%= (testcases && !testcases.error) ? (testcases.spj ? 'Special Judge' : '文本比较') : '无测试数据' %></span> |
|
</div> |
|
<% if (!contest) { %> |
|
<div class="row" style="margin-top: -23px"> |
|
<span class="ui label">上传者: |
|
<% if (problem.is_anonymous && !problem.allowedManage) { %> |
|
匿名 |
|
<% } else { %> |
|
<a href="<%= syzoj.utils.makeUrl(['user', problem.user_id]) %>"><%= problem.user.username %></a> |
|
<% } %> |
|
</span> |
|
<% if (problem.allowedManage) { %> |
|
<span class="ui label">公开者: |
|
<% if (problem.publicizer) { %> |
|
<a href="<%= syzoj.utils.makeUrl(['user', problem.publicizer_id]) %>"><%= problem.publicizer.username %></a> |
|
<% } else { %> |
|
未知 |
|
<% } %> |
|
</span> |
|
<% } %> |
|
</div> |
|
<% } %> |
|
</div> |
|
<div class="ui grid"> |
|
<div class="row"> |
|
<div class="column"> |
|
<div class="ui buttons"> |
|
<% if (typeof contest !== 'undefined' && contest) { %> |
|
<% if (!contest.ended) { %> |
|
<a class="small ui primary button" href="#submit_code">提交</a> |
|
<% } else { %> |
|
<a class="small ui primary button" href="<%= syzoj.utils.makeUrl(['problem', problem.id]) %>">转到题库</a> |
|
<% } %> |
|
<a class="small ui positive button" href="<%= syzoj.utils.makeUrl(['contest', contest.id, 'submissions'], { problem_id: pid }) %>">提交记录</a> |
|
<% if (problem.additional_file) { %> |
|
<a class="small ui teal button" href="<%= syzoj.utils.makeUrl(['contest', contest.id, pid, 'download', 'additional_file']) %>">附加文件</a> |
|
<% } %> |
|
<a href="<%= syzoj.utils.makeUrl(['contest', contest.id]) %>" class="ui orange button">返回比赛</a> |
|
<% } else { %> |
|
<% if (testcases && !testcases.error) { %> |
|
<a class="small ui primary button" href="#submit_code">提交</a> |
|
<% } %> |
|
<a class="small ui positive button" href="<%= syzoj.utils.makeUrl(['submissions'], { problem_id: problem.id }) %>">提交记录</a> |
|
<a class="small ui orange button" href="<%= syzoj.utils.makeUrl(['problem', problem.id, 'statistics', problem.type === 'submit-answer' ? 'min' : 'fastest']) %>">统计</a> |
|
<a class="small ui brown button" href="<%= syzoj.utils.makeUrl(['problem', problem.id, 'discussion']) %>" style="position: relative; "> |
|
讨论 |
|
<% if (discussionCount) { %> |
|
<div class="floating ui red tiny circular label"><%= discussionCount %></div> |
|
<% } %> |
|
</a> |
|
<a class="small ui yellow button" href="<%= syzoj.utils.makeUrl(['problem', problem.id, 'testdata']) %>">测试数据</a> |
|
<% if (problem.additional_file) { %> |
|
<a class="small ui teal button" href="<%= syzoj.utils.makeUrl(['problem', problem.id, 'download', 'additional_file']) %>">附加文件</a> |
|
<% } %> |
|
<% } %> |
|
</div> |
|
<% if (!contest) { %> |
|
<div class="ui buttons right floated"> |
|
<% if (problem.allowedEdit) { %> |
|
<a class="small ui button" href="<%= syzoj.utils.makeUrl(['problem', problem.id, 'edit']) %>">编辑</a> |
|
<a class="small ui button" href="<%= syzoj.utils.makeUrl(['problem', problem.id, 'manage']) %>">管理</a> |
|
<% } %> |
|
<% if (problem.allowedManage) { %> |
|
<% if (problem.is_public) { %> |
|
<a class="small ui button" id="dis_public" href-post="<%= syzoj.utils.makeUrl(['problem', problem.id, 'dis_public']) %>">取消公开</a> |
|
<% } else { %> |
|
<a class="small ui button" id="public" href-post="<%= syzoj.utils.makeUrl(['problem', problem.id, 'public']) %>">公开</a> |
|
<% } %> |
|
<div class="ui basic modal" id="modal-delete"> |
|
<div class="ui icon header"> |
|
<i class="trash icon"></i> |
|
<p style="margin-top: 15px; ">删除题目</p> |
|
</div> |
|
<div class="content" style="text-align: center; "> |
|
<p>确认删除此题目吗?提交记录、讨论以及测试数据将一并删除。<br> |
|
删除题目导致的修改用户提交、通过数量可能会耗费一些时间。</p> |
|
<b>警告:删除比赛中的题目会导致系统错乱!请确认没有比赛使用此题目。</b> |
|
</div> |
|
<div class="actions"> |
|
<div class="ui red basic cancel inverted button"> |
|
<i class="remove icon"></i> |
|
否 |
|
</div> |
|
<a class="ui green ok inverted button" href-post="<%= syzoj.utils.makeUrl(['problem', problem.id, 'delete']) %>"> |
|
<i class="checkmark icon"></i> |
|
是 |
|
</a> |
|
</div> |
|
</div> |
|
<div class="small ui red button" onclick="$('#modal-delete').modal('show')">删除</div> |
|
<% } %> |
|
</div> |
|
<% } %> |
|
</div> |
|
</div> |
|
<% if (problem.description) { %> |
|
<div class="row"> |
|
<div class="column"> |
|
<h4 class="ui top attached block header">题目描述</h4> |
|
<div class="ui bottom attached segment font-content"><%- problem.description %></div> |
|
</div> |
|
</div> |
|
<% } %> |
|
<% if (problem.input_format) { %> |
|
<div class="row"> |
|
<div class="column"> |
|
<h4 class="ui top attached block header">输入格式</h4> |
|
<div class="ui bottom attached segment font-content"><%- problem.input_format %></div> |
|
</div> |
|
</div> |
|
<% } %> |
|
<% if (problem.output_format) { %> |
|
<div class="row"> |
|
<div class="column"> |
|
<h4 class="ui top attached block header">输出格式</h4> |
|
<div class="ui bottom attached segment font-content"><%- problem.output_format %></div> |
|
</div> |
|
</div> |
|
<% } %> |
|
<% if (problem.example) { %> |
|
<div class="row"> |
|
<div class="column"> |
|
<h4 class="ui top attached block header">样例</h4> |
|
<div class="ui bottom attached segment font-content"><%- problem.example %></div> |
|
</div> |
|
</div> |
|
<% } %> |
|
<% if (problem.limit_and_hint) { %> |
|
<div class="row"> |
|
<div class="column"> |
|
<h4 class="ui top attached block header">数据范围与提示</h4> |
|
<div class="ui bottom attached segment font-content"><%- problem.limit_and_hint %></div> |
|
</div> |
|
</div> |
|
<% } %> |
|
<% if (problem.tags && problem.tags.length && (typeof contest === 'undefined' || !contest)) { %> |
|
<div class="row"> |
|
<div class="column"> |
|
<h4 class="ui block header" id="show_tag_title_div" style="margin-bottom: 0; margin-left: -1px; margin-right: -1px; "><a href="#" id="show_tag_button" style="color: #000; ">显示分类标签</a></h4> |
|
<div class="ui bottom attached segment" style="display: none; " id="show_tag_div"> |
|
<% for (let tag of problem.tags) { %> |
|
<a href="<%= syzoj.utils.makeUrl(['problems', 'tag', tag.id]) %>" class="ui medium <%= tag.color %> label"> |
|
<%= tag.name %> |
|
</a> |
|
<% } %> |
|
</div> |
|
</div> |
|
</div> |
|
<script> |
|
$(function () { |
|
$('#show_tag_button').click(function (e) { |
|
e.preventDefault(); |
|
$('#show_tag_title_div').addClass('top'); |
|
$('#show_tag_title_div').addClass('top attached'); |
|
$('#show_tag_title_div').text('分类标签'); |
|
$('#show_tag_div').css('display', ''); |
|
}) |
|
}); |
|
</script> |
|
<% } %> |
|
<% let noSubmit = false; %> |
|
<% |
|
if (typeof contest !== 'undefined' && contest && contest.ended || (!testcases || testcases.error)) { |
|
noSubmit = true; |
|
} |
|
%> |
|
<% if (!noSubmit) { %> |
|
<div class="row"> |
|
<div class="column"> |
|
<% |
|
let formUrl; |
|
if (contest) formUrl = syzoj.utils.makeUrl(['problem', problem.id, 'submit'], { contest_id: contest.id }); |
|
else formUrl = syzoj.utils.makeUrl(['problem', problem.id, 'submit']); |
|
%> |
|
<form class="ui form" action="<%= formUrl %>" method="post" onsubmit="return submit_code()" id="submit_code" enctype="multipart/form-data"> |
|
<% if (problem.type === 'submit-answer') { %> |
|
<% |
|
let cases = []; |
|
if (testcases && !testcases.error) { |
|
for (let subtasks of testcases) { |
|
for (let testcase of subtasks.cases) { |
|
cases.push(testcase.answer); |
|
} |
|
} |
|
} |
|
%> |
|
<script> |
|
var cases = <%- JSON.stringify(cases) %>, currCase = 0; |
|
</script> |
|
<div class="ui grid"> |
|
<% if (testcases) { %> |
|
<div class="four wide column" style="margin-right: -25px; "> |
|
<div class="ui attached vertical fluid pointing menu" id="testcase-menu" style="height: 370px; overflow-y: scroll; overflow-x: hidden; "> |
|
<% for (let i = 0; i < cases.length; i++) { %> |
|
<a class="item<%= i === 0 ? ' active' : '' %>" data-value="<%= i %>"> |
|
<%= cases[i] %> |
|
</a> |
|
<% } %> |
|
</div> |
|
</div> |
|
<div class="twelve wide stretched column" style="position: relative; padding-left: 0; margin-left: calc(-1rem - 1px); width: calc(75% + 1rem + 12px) !important; "> |
|
<% for (let i = 0; i < cases.length; i++) { %> |
|
<div id="editor-<%= i %>" style="position: absolute; width: 100%; height: calc(100% - 28px); border: 1px solid #D4D4D5; <%= i === 0 ? '' : 'visibility: hidden; ' %>"></div> |
|
<% } %> |
|
</div> |
|
<% } %> |
|
<input id="answer_by_editor" name="answer_by_editor" type="hidden"> |
|
<script> |
|
var editors = []; |
|
for (var i = 0; i < cases.length; i++) { |
|
var editor = ace.edit("editor-" + i); |
|
var lastSubmitted = ''; |
|
|
|
editor.setTheme("ace/theme/tomorrow"); |
|
// editor.getSession().setMode("ace/mode/" + $('#languages-menu .item.active').data('mode')); |
|
editor.getSession().setUseSoftTabs(false); |
|
|
|
editor.container.style.lineHeight = 1.6; |
|
editor.container.style.fontSize = '14px'; |
|
editor.container.style.fontFamily = "'Roboto Mono', 'Bitstream Vera Sans Mono', 'Menlo', 'Consolas', 'Lucida Console', monospace"; |
|
editor.setShowPrintMargin(false); |
|
editor.renderer.updateFontSize(); |
|
|
|
editors[i] = editor; |
|
} |
|
|
|
$(function () { |
|
$('#testcase-menu .item').click(function() { |
|
$(this) |
|
.addClass('active') |
|
.closest('.ui.menu') |
|
.find('.item') |
|
.not($(this)) |
|
.removeClass('active') |
|
; |
|
|
|
var x = $(this).attr('data-value'); |
|
if (currCase != x) { |
|
$('#editor-' + currCase).css('visibility', 'hidden'); |
|
$('#editor-' + x).css('visibility', 'visible'); |
|
currCase = x; |
|
} |
|
}); |
|
}); |
|
</script> |
|
<div class="inline fields" style="width: 100%; "> |
|
<div class="field" style="margin: 0 auto; "> |
|
<label for="answer">或者,上传答案(请使用 ZIP 格式压缩)</label> |
|
<input type="file" id="answer" name="answer"> |
|
</div> |
|
</div> |
|
</div> |
|
<div class="ui center aligned vertical segment" style="padding-bottom: 0; "><button type="submit" class="ui button">提交</button></div> |
|
<% } else { %> |
|
<input name="language" type="hidden" id="form"> |
|
<input name="code" type="hidden"> |
|
<div class="ui grid"> |
|
<div class="four wide column" style="margin-right: -25px; "> |
|
<div class="ui attached vertical fluid pointing menu" id="languages-menu" style="height: 370px; overflow-y: scroll; overflow-x: hidden; "> |
|
<% |
|
let language = Object.getOwnPropertyNames(syzoj.config.languages).shift(); |
|
if (state) { |
|
language = state.language; |
|
} else if (lastLanguage) language = lastLanguage; |
|
%> |
|
<% for (lang in syzoj.config.languages) { %> |
|
<a class="item<%= lang === language ? ' active' : '' %>" data-value="<%= lang %>" data-mode="<%= syzoj.config.languages[lang].editor %>"> |
|
<%= syzoj.config.languages[lang].show %> |
|
<div class="ui right floated" style="opacity: 0.4; margin-top: 8px; font-size: 0.7em; "><%= syzoj.config.languages[lang].version %></div> |
|
</a> |
|
<% } %> |
|
</div> |
|
</div> |
|
<div class="twelve wide stretched column" style="padding-left: 0; margin-left: calc(-1rem - 1px); width: calc(75% + 1rem + 1px + 25px) !important; "> |
|
<div id="editor" style="border: 1px solid #D4D4D5; "><% if (state) { %><%= state.code %><% } %></div> |
|
</div> |
|
<div class="inline fields" style="width: 100%; "> |
|
<div class="field" style="margin: 0 auto; "> |
|
<label for="answer">或者,上传代码文件</label> |
|
<input type="file" id="answer" name="answer"> |
|
</div> |
|
</div> |
|
</div> |
|
<div class="ui center aligned vertical segment" style="padding-bottom: 0; "> |
|
<button type="submit" class="ui button">提交</button> |
|
<div onclick="show_custom_test()" class="ui positive button">自定义测试</div> |
|
</div> |
|
<% } %> |
|
</form> |
|
</div> |
|
</div> |
|
<% } %> |
|
</div> |
|
|
|
<% if (problem.type !== 'submit-answer') { %> |
|
<script type="text/javascript"> |
|
var editor = ace.edit("editor"); |
|
var lastSubmitted = ''; |
|
|
|
editor.setTheme("ace/theme/tomorrow"); |
|
editor.getSession().setMode("ace/mode/" + $('#languages-menu .item.active').data('mode')); |
|
editor.getSession().setUseSoftTabs(false); |
|
|
|
editor.container.style.lineHeight = 1.6; |
|
editor.container.style.fontSize = '14px'; |
|
editor.container.style.fontFamily = "'Roboto Mono', 'Bitstream Vera Sans Mono', 'Menlo', 'Consolas', 'Lucida Console', monospace"; |
|
editor.setShowPrintMargin(false); |
|
editor.renderer.updateFontSize(); |
|
|
|
function submit_code() { |
|
if (!editor.getValue().trim()) return false; |
|
$('#submit_code input[name=language]').val($('#languages-menu .item.active').data('value')); |
|
lastSubmitted = editor.getValue(); |
|
$('#submit_code input[name=code]').val(editor.getValue()); |
|
return true; |
|
} |
|
|
|
$('#languages-menu')[0].scrollTop = $('#languages-menu .active')[0].offsetTop - $('#languages-menu')[0].firstElementChild.offsetTop; |
|
|
|
$(function () { |
|
$('#languages-menu .item').click(function() { |
|
$(this) |
|
.addClass('active') |
|
.closest('.ui.menu') |
|
.find('.item') |
|
.not($(this)) |
|
.removeClass('active') |
|
; |
|
editor.getSession().setMode("ace/mode/" + $(this).data('mode')); |
|
}); |
|
}); |
|
</script> |
|
|
|
<script src="https://cdn.staticfile.org/css-element-queries/0.4.0/ResizeSensor.min.js"></script> |
|
<div class="ui modal" id="modal-custom-test"> |
|
<div class="header"> |
|
自定义测试 |
|
</div> |
|
<div class="content" style="padding-bottom: 0; "> |
|
<div class="ui form"> |
|
<form id="form-custom-test" action="<%= syzoj.utils.makeUrl(['problem', problem.id, 'custom-test']) %>"> |
|
<input type="hidden" name="code"> |
|
<input type="hidden" name="language"> |
|
<div class="field"> |
|
<label>输入文件</label> |
|
<textarea name="input_file_textarea" style="font-family: 'Roboto Mono', 'Bitstream Vera Sans Mono', 'Menlo', 'Consolas', 'Lucida Console', monospace; "></textarea> |
|
</div> |
|
<div class="inline fields" style="width: 100%; "> |
|
<div class="field" style="margin: 0 auto; "> |
|
<label for="answer">或者,上传输入文件</label> |
|
<input type="file" name="input_file"> |
|
</div> |
|
</div> |
|
</form> |
|
</div> |
|
<div id="custom-test-result"></div> |
|
</div> |
|
<div class="actions" style="text-align: center; "> |
|
<div class="ui green button" id="submit-custom-test">提交</div> |
|
</div> |
|
</div> |
|
|
|
<script> |
|
var custom_test_id; |
|
|
|
$('#submit-custom-test').click(function () { |
|
$('#submit-custom-test').addClass('disabled'); |
|
|
|
var form = document.getElementById('form-custom-test'); |
|
$(form).find('[name=language]').val($('#languages-menu .item.active').data('value')); |
|
$(form).find('[name=code]').val(editor.getValue()); |
|
|
|
var code_upload = $('#answer')[0].cloneNode(true); |
|
code_upload.style.display = 'none'; |
|
code_upload.name = 'code_upload'; |
|
form.appendChild(code_upload); |
|
|
|
$.ajax({ |
|
url: form.action, |
|
type: 'post', |
|
data: new FormData(form), |
|
cache: false, |
|
contentType: false, |
|
processData: false, |
|
success: function (data) { |
|
custom_test_id = data.id; |
|
update_custom_test_result(); |
|
} |
|
}); |
|
|
|
form.removeChild(code_upload); |
|
}); |
|
|
|
function show_custom_test() { |
|
$('#modal-custom-test').modal('show'); |
|
new ResizeSensor($('#modal-custom-test'), function () { |
|
$(window).resize(); |
|
}); |
|
} |
|
|
|
function update_custom_test_result() { |
|
$.get('/custom-test/' + custom_test_id + '/ajax', function (data) { |
|
if (data.err) { |
|
alert(data.err); |
|
} |
|
|
|
if ($('#custom-test-result').html() !== data.html) { |
|
$('#custom-test-result').html(data.html); |
|
} |
|
|
|
if (data.pending) { |
|
setTimeout(function () { |
|
update_custom_test_result(); |
|
}, 500); |
|
} else { |
|
$('#submit-custom-test').removeClass('disabled'); |
|
} |
|
}); |
|
} |
|
</script> |
|
<% } else { %> |
|
<script> |
|
function submit_code() { |
|
var a = []; |
|
for (var i = 0; i < cases.length; i++) { |
|
a.push({ |
|
filename: cases[i], |
|
data: editors[i].getValue() |
|
}); |
|
} |
|
$('#answer_by_editor').val(JSON.stringify(a)); |
|
} |
|
</script> |
|
<% } %> |
|
<% include footer %>
|
|
|