problem_statistics.php 6.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169
  1. <?php
  2. if (!validateUInt($_GET['id']) || !($problem = queryProblemBrief($_GET['id']))) {
  3. become404Page();
  4. }
  5. $contest = validateUInt($_GET['contest_id']) ? queryContest($_GET['contest_id']) : null;
  6. if ($contest != null) {
  7. genMoreContestInfo($contest);
  8. if (!isContestProblemVisibleToUser($problem, $contest, $myUser)) {
  9. become404Page();
  10. }
  11. } else {
  12. if (!isProblemVisibleToUser($problem, $myUser)) {
  13. become404Page();
  14. }
  15. }
  16. function scoreDistributionData() {
  17. $data = array();
  18. $result = DB::select("select score, count(*) from submissions where problem_id = {$_GET['id']} and score is not null group by score");
  19. $is_res_empty = true;
  20. $has_score_0 = false;
  21. $has_score_100 = false;
  22. while ($row = DB::fetch($result, MYSQLI_NUM)) {
  23. if ($row[0] == 0) {
  24. $has_score_0 = true;
  25. } elseif ($row[0] == 100) {
  26. $has_score_100 = true;
  27. }
  28. $score = $row[0] * 100;
  29. $data[] = array('score' => $score, 'count' => $row[1]);
  30. }
  31. if (!$has_score_0) {
  32. array_unshift($data, array('score' => 0, 'count' => 0));
  33. }
  34. if (!$has_score_100) {
  35. $data[] = array('score' => 10000, 'count' => 0);
  36. }
  37. return $data;
  38. }
  39. $data = scoreDistributionData();
  40. $pre_data = $data;
  41. $suf_data = $data;
  42. for ($i = 0; $i < count($data); $i++) {
  43. $data[$i]['score'] /= 100;
  44. }
  45. for ($i = 1; $i < count($data); $i++) {
  46. $pre_data[$i]['count'] += $pre_data[$i - 1]['count'];
  47. }
  48. for ($i = count($data) - 1; $i > 0; $i--) {
  49. $suf_data[$i - 1]['count'] += $suf_data[$i]['count'];
  50. }
  51. $submissions_sort_by_choice = !isset($_COOKIE['submissions-sort-by-code-length']) ? 'time' : 'tot_size';
  52. ?>
  53. <?php
  54. $REQUIRE_LIB['morris'] = "";
  55. ?>
  56. <?php echoUOJPageHeader(HTML::stripTags($problem['title']) . ' - ' . UOJLocale::get('problems::statistics')) ?>
  57. <h1 class="page-header text-center"><?= $problem['title'] ?> <?= UOJLocale::get('problems::statistics') ?></h1>
  58. <?php if ($contest && !hasContestPermission($myUser, $contest) && $contest['cur_progress'] <= CONTEST_IN_PROGRESS): ?>
  59. <h2 class="text-center text-muted">比赛尚未结束</h2>
  60. <?php else: ?>
  61. <h2 class="text-center"><?= UOJLocale::get('problems::accepted submissions') ?></h2>
  62. <div class="text-right bot-buffer-sm">
  63. <div class="btn-group btn-group-sm">
  64. <a href="<?=$SERVER['REQUEST_URI']?>" class="<?=$submissions_sort_by_choice == 'time' ? 'btn btn-info btn-xs active' : 'btn btn-info btn-xs'?>" id="submissions-sort-by-run-time"><?= UOJLocale::get('problems::fastest') ?></a>
  65. <a href="<?=$SERVER['REQUEST_URI']?>" class="<?=$submissions_sort_by_choice == 'tot_size' ? 'btn btn-info btn-xs active' : 'btn btn-info btn-xs'?>" id="submissions-sort-by-code-length"><?= UOJLocale::get('problems::shortest') ?></a>
  66. </div>
  67. </div>
  68. <script type="text/javascript">
  69. $('#submissions-sort-by-run-time').click(function() {
  70. $.cookie('submissions-sort-by-run-time', '');
  71. $.removeCookie('submissions-sort-by-code-length');
  72. });
  73. $('#submissions-sort-by-code-length').click(function() {
  74. $.cookie('submissions-sort-by-code-length', '');
  75. $.removeCookie('submissions-sort-by-run-time');
  76. });
  77. </script>
  78. <?php if ($submissions_sort_by_choice == 'time'): ?>
  79. <?php echoSubmissionsList("best_ac_submissions.submission_id = submissions.id and best_ac_submissions.problem_id = {$problem['id']}", 'order by best_ac_submissions.used_time, best_ac_submissions.used_memory, best_ac_submissions.tot_size', array('judge_time_hidden' => '', 'table_name' => 'best_ac_submissions, submissions'), $myUser); ?>
  80. <?php else: ?>
  81. <?php echoSubmissionsList("best_ac_submissions.shortest_id = submissions.id and best_ac_submissions.problem_id = {$problem['id']}", 'order by best_ac_submissions.shortest_tot_size, best_ac_submissions.shortest_used_time, best_ac_submissions.shortest_used_memory', array('judge_time_hidden' => '', 'table_name' => 'best_ac_submissions, submissions'), $myUser); ?>
  82. <?php endif ?>
  83. <h2 class="text-center"><?= UOJLocale::get('problems::score distribution') ?></h2>
  84. <div id="score-distribution-chart" style="height: 250px;"></div>
  85. <script type="text/javascript">
  86. new Morris.Bar({
  87. element: 'score-distribution-chart',
  88. data: <?= json_encode($data) ?>,
  89. barColors: function(r, s, type) {
  90. return getColOfScore(r.label);
  91. },
  92. xkey: 'score',
  93. ykeys: ['count'],
  94. labels: ['number'],
  95. hoverCallback: function(index, options, content, row) {
  96. var scr = row.score;
  97. return '<div class="morris-hover-row-label">' + 'score: ' + scr + '</div>' +
  98. '<div class="morris-hover-point">' + '<a href="/submissions?problem_id=' + <?= $problem['id'] ?> + '&amp;min_score=' + scr + '&amp;max_score=' + scr + '">' + 'number: ' + row.count + '</a>' + '</div>';
  99. },
  100. resize: true
  101. });
  102. </script>
  103. <h2 class="text-center"><?= UOJLocale::get('problems::prefix sum of score distribution') ?></h2>
  104. <div id="score-distribution-chart-pre" style="height: 250px;"></div>
  105. <script type="text/javascript">
  106. new Morris.Line({
  107. element: 'score-distribution-chart-pre',
  108. data: <?= json_encode($pre_data) ?>,
  109. xkey: 'score',
  110. ykeys: ['count'],
  111. labels: ['number'],
  112. lineColors: function(row, sidx, type) {
  113. if (type == 'line') {
  114. return '#0b62a4';
  115. }
  116. return getColOfScore(row.src.score / 100);
  117. },
  118. xLabelFormat: function(x) {
  119. return (x.getTime() / 100).toString();
  120. },
  121. hoverCallback: function(index, options, content, row) {
  122. var scr = row.score / 100;
  123. return '<div class="morris-hover-row-label">' + 'score: &le;' + scr + '</div>' +
  124. '<div class="morris-hover-point">' + '<a href="/submissions?problem_id=' + <?= $problem['id'] ?> + '&amp;max_score=' + scr + '">' + 'number: ' + row.count + '</a>' + '</div>';
  125. },
  126. resize: true
  127. });
  128. </script>
  129. <h2 class="text-center"><?= UOJLocale::get('problems::suffix sum of score distribution') ?></h2>
  130. <div id="score-distribution-chart-suf" style="height: 250px;"></div>
  131. <script type="text/javascript">
  132. new Morris.Line({
  133. element: 'score-distribution-chart-suf',
  134. data: <?= json_encode($suf_data) ?>,
  135. xkey: 'score',
  136. ykeys: ['count'],
  137. labels: ['number'],
  138. lineColors: function(row, sidx, type) {
  139. if (type == 'line') {
  140. return '#0b62a4';
  141. }
  142. return getColOfScore(row.src.score / 100);
  143. },
  144. xLabelFormat: function(x) {
  145. return (x.getTime() / 100).toString();
  146. },
  147. hoverCallback: function(index, options, content, row) {
  148. var scr = row.score / 100;
  149. return '<div class="morris-hover-row-label">' + 'score: &ge;' + scr + '</div>' +
  150. '<div class="morris-hover-point">' + '<a href="/submissions?problem_id=' + <?= $problem['id'] ?> + '&amp;min_score=' + scr + '">' + 'number: ' + row.count + '</a>' + '</div>';
  151. },
  152. resize: true
  153. });
  154. </script>
  155. <?php endif ?>
  156. <?php echoUOJPageFooter() ?>