Skip to content

Commit

Permalink
Added support for public sample testcases.
Browse files Browse the repository at this point in the history
Contestants can view testcases marked as sample as well as their
program output on these cases.

WARNING: this can and will leak information about the problem like
timelimit and more.
  • Loading branch information
rf232 authored and eldering committed Dec 5, 2012
1 parent 1749d77 commit 177a655
Show file tree
Hide file tree
Showing 5 changed files with 105 additions and 7 deletions.
1 change: 1 addition & 0 deletions sql/mysql_db_structure.sql
Expand Up @@ -358,6 +358,7 @@ CREATE TABLE `testcase` (
`probid` varchar(8) NOT NULL COMMENT 'Corresponding problem ID',
`rank` int(4) NOT NULL COMMENT 'Determines order of the testcases in judging',
`description` varchar(255) default NULL COMMENT 'Description of this testcase',
`sample` tinyint(1) unsigned NOT NULL DEFAULT '0' COMMENT 'Sample testcases can be shared with teams.',
PRIMARY KEY (`testcaseid`),
UNIQUE KEY `rank` (`probid`,`rank`),
KEY `probid` (`probid`),
Expand Down
6 changes: 5 additions & 1 deletion sql/upgrade/upgrade_to-online_judge.sql
Expand Up @@ -8,12 +8,16 @@
--

-- @UPGRADE-CHECK@
SELECT 1;
ALTER TABLE `testcase` ADD COLUMN `sample` tinyint(1) default NULL;
ALTER TABLE `testcase` DROP COLUMN `sample`;

--
-- Create additional structures
--

ALTER TABLE `testcase`
ADD COLUMN `sample` tinyint(1) unsigned NOT NULL default '0' COMMENT 'Sample testcases can be shared with teams.' AFTER `description`;

--
-- Transfer data from old to new structure
--
Expand Down
25 changes: 25 additions & 0 deletions www/js/domjudge.js
Expand Up @@ -62,6 +62,31 @@ function hideTcDescEdit(descid)
node.parentNode.appendChild(span);
}

// make corresponding testcase sample dropdown editable
function editTcSample(tcid)
{
var node = document.getElementById('sample_' + tcid + '_');
node.parentNode.setAttribute('onclick', '');
var remove = node.nextSibling;
while (remove.nodeName == '#text')
remove = remove.nextSibling;
node.parentNode.removeChild(remove);
node.style.display = 'block';
node.setAttribute('name', 'sample[' + tcid + ']');
}

// hides sample dropdown field if javascript is enabled
function hideTcSample(tcid, str)
{
var node = document.getElementById('sample_' + tcid + '_');
node.style.display = 'none';
node.setAttribute('name', 'invalid');

var span = document.createElement('span');
span.innerHTML = str;
node.parentNode.appendChild(span);
}

// Autodetection of problem, language in websubmit
function detectProblemLanguage(filename)
{
Expand Down
29 changes: 24 additions & 5 deletions www/jury/testcase.php
Expand Up @@ -128,6 +128,14 @@
}
}

if ( isset($_POST['sample'][$rank]) ) {
$DB->q('UPDATE testcase SET sample = %i WHERE probid = %s
AND rank = %i', $_POST['sample'][$rank], $probid, $rank);
$result .= "<li>Set testcase $rank to be " .
($_POST['sample'][$rank] ? "" : "not ") .
"a sample testcase</li>\n";
}

if ( isset($_POST['description'][$rank]) ) {
$DB->q('UPDATE testcase SET description = %s WHERE probid = %s
AND rank = %i', $_POST['description'][$rank], $probid, $rank);
Expand All @@ -154,10 +162,11 @@

if ( !empty($content['input']) && !empty($content['output']) ) {
$DB->q("INSERT INTO testcase
(probid,rank,md5sum_input,md5sum_output,input,output,description)
VALUES (%s,%i,%s,%s,%s,%s,%s)",
(probid,rank,md5sum_input,md5sum_output,input,output,description,sample)
VALUES (%s,%i,%s,%s,%s,%s,%s,%i)",
$probid, $rank, md5(@$content['input']), md5(@$content['output']),
@$content['input'], @$content['output'], @$_POST['add_desc']);
@$content['input'], @$content['output'], @$_POST['add_desc'],
@$_POST['add_sample']);
auditlog('testcase', $probid, 'added', "rank $rank");

$result .= "<li>Added new testcase $rank from " .
Expand All @@ -172,7 +181,8 @@
echo "<ul>\n$result</ul>\n\n";

// Reload testcase data after updates
$data = $DB->q('KEYTABLE SELECT rank AS ARRAYKEY, testcaseid, rank, description,
$data = $DB->q('KEYTABLE SELECT rank AS ARRAYKEY, testcaseid, rank,
description, sample,
OCTET_LENGTH(input) AS size_input, md5sum_input,
OCTET_LENGTH(output) AS size_output, md5sum_output
FROM testcase WHERE probid = %s ORDER BY rank', $probid);
Expand All @@ -196,7 +206,7 @@
<th scope="col">size</th><th scope="col">md5</th>
<?php
if ( IS_ADMIN ) echo '<th scope="col">upload new</th>';
?><th scope="col">description</th>
?><th scope="col">sample</th><th scope="col">description</th>
</tr></thead>
<tbody>
<?php
Expand All @@ -222,6 +232,12 @@
}
if ( $inout=='input' ) {
if ( IS_ADMIN ) {
echo "<td rowspan=\"2\" align=\"center]\" onclick=\"editTcSample($rank)\">" .
addSelect("sample[$rank]",array("no", "yes"), $row['sample'], true) . "</td>";

// hide sample dropdown field if javascript is enabled
echo "<script type=\"text/javascript\" language=\"JavaScript\">" .
"hideTcSample($rank, '". printyn($row['sample'])."');</script>";
echo "<td rowspan=\"2\" class=\"testdesc\" onclick=\"editTcDesc($rank)\">" .
"<textarea id=\"tcdesc_$rank\" name=\"description[$rank]\" cols=\"50\" rows=\"2\">" .
htmlspecialchars($row['description']) . "</textarea></td>" .
Expand All @@ -235,6 +251,8 @@
echo "<script type=\"text/javascript\" language=\"JavaScript\">" .
"hideTcDescEdit($rank);</script>";
} else {
echo "<td rowspan=\"2\" align=\"center\">" .
printyn($row['issample']) . "</td>";
echo "<td rowspan=\"2\" class=\"testdesc\">" .
htmlspecialchars($row['description']) . "</td>";
}
Expand All @@ -252,6 +270,7 @@
<table>
<tr><td>Input testdata: </td><td><?php echo addFileField('add_input') ?></td></tr>
<tr><td>Output testdata:</td><td><?php echo addFileField('add_output') ?></td></tr>
<tr><td>Sample testcase:</td><td><?php echo addSelect('add_sample', array("no","yes"), 0, true);?></td></tr>
<tr><td>Description: </td><td><?php echo addInput('add_desc','',30); ?></td></tr>
</table>
<?php
Expand Down
51 changes: 50 additions & 1 deletion www/team/submission_details.php
Expand Up @@ -15,7 +15,7 @@

// select also on teamid so we can only select our own submissions
$row = $DB->q('MAYBETUPLE SELECT p.probid, p.name AS probname, submittime,
s.valid, l.name AS langname, result, output_compile, verified
s.valid, l.name AS langname, result, output_compile, verified, judgingid
FROM judging j
LEFT JOIN submission s USING (submitid)
LEFT JOIN language l USING (langid)
Expand Down Expand Up @@ -75,4 +75,53 @@
echo "<p class=\"nodata\">Compilation output is disabled.</p>\n";
}

if ( @$row['result']!='compiler-error' ) {
$runs = $DB->q('SELECT r.*, t.rank, t.description FROM testcase t
LEFT JOIN judging_run r ON ( r.testcaseid = t.testcaseid AND
r.judgingid = %i )
WHERE t.probid = %s AND t.sample = 1 ORDER BY rank',
$row['judgingid'], $row['probid']);

$runinfo = $runs->gettable();
echo '<h3>Run(s) on the provided sample data</h3>';

foreach ( $runinfo as $run ) {
echo "<h4 id=\"run-$run[rank]\">Run $run[rank]</h4>\n\n";
if ( $run['runresult']===NULL ) {
echo "<p class=\"nodata\">Run not finished yet.</p>\n";
continue;
}
echo "<table>\n" .
"<tr><td>Description:</td><td>" .
htmlspecialchars($run['description']) . "</td></tr>" .
"<tr><td>Runtime:</td><td>$run[runtime] sec</td></tr>" .
"<tr><td>Result: </td><td><span class=\"sol sol_" .
( $run['runresult']=='correct' ? '' : 'in' ) .
"correct\">$run[runresult]</span></td></tr>" .
"</table>\n\n";
echo "<h5>Program output</h5>\n";
if ( @$run['output_run'] ) {
echo "<pre class=\"output_text\">".
htmlspecialchars($run['output_run'])."</pre>\n\n";
} else {
echo "<p class=\"nodata\">There was no program output.</p>\n";
}
echo "<h5>Diff output</h5>\n";
if ( @$run['output_diff'] ) {
echo "<pre class=\"output_text\">";
echo parseDiff($run['output_diff']);
echo "</pre>\n\n";
} else {
echo "<p class=\"nodata\">There was no diff output.</p>\n";
}
echo "<h5>Error output (info/debug/errors)</h5>\n";
if ( @$run['output_error'] ) {
echo "<pre class=\"output_text\">".
htmlspecialchars($run['output_error'])."</pre>\n\n";
} else {
echo "<p class=\"nodata\">There was no stderr output.</p>\n";
}
}
}

require(LIBWWWDIR . '/footer.php');

0 comments on commit 177a655

Please sign in to comment.