function show_pset_table($pset) { global $Conf, $Me, $Now, $Profile, $LastPsetFix; echo '<div id="', $pset->urlkey, '">'; echo "<h3>", htmlspecialchars($pset->title), "</h3>"; if ($Me->privChair) { show_pset_actions($pset); } if ($pset->disabled) { echo "</div>\n"; return; } $t0 = $Profile ? microtime(true) : 0; // load students if ($Conf->opt("restrictRepoView")) { $view = "l2.link repoviewable"; $viewjoin = "left join ContactLink l2 on (l2.cid=c.contactId and l2.type=" . LINK_REPOVIEW . " and l2.link=l.link)\n"; } else { $view = "4 repoviewable"; $viewjoin = ""; } $result = Dbl::qe("select c.contactId, c.firstName, c.lastName, c.email,\n\tc.huid, c.github_username, c.seascode_username, c.anon_username, c.extension, c.disabled, c.dropped, c.roles, c.contactTags,\n\tgroup_concat(pl.link) pcid, group_concat(rpl.link) rpcid,\n\tr.repoid, r.cacheid, r.heads, r.url, r.open, r.working, r.lastpset, r.snapcheckat, {$view},\n\trg.gradehash, rg.gradercid, rg.placeholder, rg.placeholder_at\n\tfrom ContactInfo c\n\tleft join ContactLink l on (l.cid=c.contactId and l.type=" . LINK_REPO . " and l.pset={$pset->id})\n\t{$viewjoin}\n\tleft join Repository r on (r.repoid=l.link)\n\tleft join ContactLink pl on (pl.cid=c.contactId and pl.type=" . LINK_PARTNER . " and pl.pset={$pset->id})\n\tleft join ContactLink rpl on (rpl.cid=c.contactId and rpl.type=" . LINK_BACKPARTNER . " and rpl.pset={$pset->id})\n\tleft join RepositoryGrade rg on (rg.repoid=r.repoid and rg.pset={$pset->id})\n\twhere (c.roles&" . Contact::ROLE_PCLIKE . ")=0\n\tand (rg.repoid is not null or not c.dropped)\n\tgroup by c.contactId, r.repoid"); $t1 = $Profile ? microtime(true) : 0; $anonymous = $pset->anonymous; if (req("anonymous") !== null && $Me->privChair) { $anonymous = !!req("anonymous"); } $students = array(); while ($result && ($s = Contact::fetch($result))) { $s->set_anonymous($anonymous); Contact::set_sorter($s, req("sort")); $students[$s->contactId] = $s; // maybe lastpset links are out of order if ($s->lastpset < $pset) { $LastPsetFix = true; } } uasort($students, "Contact::compare"); $checkbox = $Me->privChair || !$pset->gitless && $pset->runners; $rows = array(); $max_ncol = 0; $incomplete = array(); $pcmembers = pcMembers(); $jx = []; foreach ($students as $s) { if (!$s->visited) { $row = (object) ["student" => $s, "text" => "", "ptext" => []]; $j = render_pset_row($pset, $students, $s, $row, $pcmembers, $anonymous); if ($s->pcid) { foreach (array_unique(explode(",", $s->pcid)) as $pcid) { if (isset($students[$pcid])) { $jj = render_pset_row($pset, $students, $students[$pcid], $row, $pcmembers, $anonymous); $j["partners"][] = $jj; } } } if ($row->sortprefix) { $j["boring"] = true; } $jx[$row->sortprefix . $s->sorter] = $j; $max_ncol = max($max_ncol, $row->ncol); if ($s->incomplete) { $u = $Me->user_linkpart($s); $incomplete[] = '<a href="' . hoturl("pset", array("pset" => $pset->urlkey, "u" => $u, "sort" => req("sort"))) . '">' . htmlspecialchars($u) . '</a>'; } } } if (count($incomplete)) { echo '<div id="incomplete_pset', $pset->id, '" style="display:none" class="merror">', '<strong>', htmlspecialchars($pset->title), '</strong>: ', 'Your grading is incomplete. Missing grades: ', join(", ", $incomplete), '</div>', '<script>jQuery("#incomplete_pset', $pset->id, '").remove().show().appendTo("#incomplete_notices")</script>'; } if ($checkbox) { echo Ht::form_div(hoturl_post("index", array("pset" => $pset->urlkey, "save" => 1))); } $sort_key = $anonymous ? "anon_username" : "username"; usort($jx, function ($a, $b) use($sort_key) { if (get($a, "boring") != get($b, "boring")) { return get($a, "boring") ? 1 : -1; } return strcmp($a[$sort_key], $b[$sort_key]); }); echo '<table class="s61', $anonymous ? " s61anonymous" : "", '" id="pa-pset' . $pset->id . '"></table>'; $jd = ["checkbox" => $checkbox, "anonymous" => $anonymous, "grade_keys" => array_keys($pset->grades), "gitless" => $pset->gitless, "gitless_grades" => $pset->gitless_grades, "urlpattern" => hoturl("pset", ["pset" => $pset->urlkey, "u" => "@", "sort" => req("sort")])]; $i = $nintotal = $last_in_total = 0; foreach ($pset->grades as $ge) { if (!$ge->no_total) { ++$nintotal; $last_in_total = $ge->name; } ++$i; } if ($nintotal > 1) { $jd["need_total"] = true; } else { if ($nintotal == 1) { $jd["total_key"] = $last_in_total; } } echo Ht::unstash(), '<script>pa_render_pset_table(', $pset->id, ',', json_encode($jd), ',', json_encode(array_values($jx)), ')</script>'; if ($Me->privChair && !$pset->gitless_grades) { echo "<div class='g'></div>"; $sel = array("none" => "N/A"); foreach (pcMembers() as $pcm) { $sel[$pcm->email] = Text::name_html($pcm); } $sel["__random__"] = "Random"; echo '<span class="nb" style="padding-right:2em">', Ht::select("grader", $sel, "none"), Ht::submit("setgrader", "Set grader"), '</span>'; } if (!$pset->gitless) { $sel = array(); foreach ($pset->runners as $r) { if ($Me->can_run($pset, $r)) { $sel[$r->name] = htmlspecialchars($r->title); } } if (count($sel)) { echo '<span class="nb" style="padding-right:2em">', Ht::select("runner", $sel), Ht::submit("runmany", "Run all"), '</span>'; } } if ($checkbox) { echo "</div></form>\n"; } if ($Profile) { $t2 = microtime(true); echo sprintf("<div>Δt %.06f DB, %.06f total</div>", $t1 - $t0, $t2 - $t0); } echo "</div>\n"; }
private function header_head($title) { global $Me, $ConfSitePATH, $CurrentList; echo "<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n<meta http-equiv=\"Content-Type\" content=\"text/html; charset=utf-8\" />\n<meta http-equiv=\"Content-Style-Type\" content=\"text/css\" />\n<meta http-equiv=\"Content-Script-Type\" content=\"text/javascript\" />\n<meta http-equiv=\"Content-Language\" content=\"en\" />\n<meta name=\"google\" content=\"notranslate\" />\n"; if (strstr($title, "<") !== false) { $title = preg_replace("/<([^>\"']|'[^']*'|\"[^\"]*\")*>/", "", $title); } echo $this->opt("fontScript", ""); echo $this->make_css_link("stylesheets/style.css"), "\n"; if ($this->opt("mobileStylesheet")) { echo '<meta name="viewport" content="width=device-width, initial-scale=1">', "\n"; echo $this->make_css_link("stylesheets/mobile.css", "screen and (max-width: 768px)"), "\n"; } foreach (mkarray($this->opt("stylesheets", [])) as $css) { echo $this->make_css_link($css), "\n"; } // favicon $favicon = $this->opt("favicon"); if ($favicon) { if (strpos($favicon, "://") === false && $favicon[0] != "/") { if ($this->opt["assetsUrl"] && substr($favicon, 0, 7) === "images/") { $favicon = $this->opt["assetsUrl"] . $favicon; } else { $favicon = Navigation::siteurl() . $favicon; } } if (substr($favicon, -4) == ".png") { echo "<link rel=\"icon\" type=\"image/png\" href=\"{$favicon}\" />\n"; } else { if (substr($favicon, -4) == ".ico") { echo "<link rel=\"shortcut icon\" href=\"{$favicon}\" />\n"; } else { if (substr($favicon, -4) == ".gif") { echo "<link rel=\"icon\" type=\"image/gif\" href=\"{$favicon}\" />\n"; } else { echo "<link rel=\"icon\" href=\"{$favicon}\" />\n"; } } } } // jQuery if (isset($this->opt["jqueryUrl"])) { $jquery = $this->opt["jqueryUrl"]; } else { if ($this->opt("jqueryCdn")) { $jquery = "//code.jquery.com/jquery-1.12.3.min.js"; } else { $jquery = "scripts/jquery-1.12.3.min.js"; } } Ht::stash_html($this->make_script_file($jquery, true) . "\n"); Ht::stash_html($this->make_script_file("scripts/jquery.color-2.1.2.min.js", true) . "\n"); Ht::stash_html($this->make_script_file("scripts/jquery.flot.min.js", true) . "\n"); //Ht::stash_html($this->make_script_file("scripts/ZeroClipboard.min.js", true) . "\n"); // Javascript settings to set before script.js Ht::stash_script("siteurl=" . json_encode(Navigation::siteurl()) . ";siteurl_suffix=\"" . Navigation::php_suffix() . "\""); if (session_id() !== "") { Ht::stash_script("siteurl_postvalue=\"" . post_value() . "\""); } if (@$CurrentList && ($list = SessionList::lookup($CurrentList))) { Ht::stash_script("hotcrp_list={num:{$CurrentList},id:\"" . addcslashes($list->listid, "\n\r\\\"/") . "\"}"); } if ($urldefaults = hoturl_defaults()) { Ht::stash_script("siteurl_defaults=" . json_encode($urldefaults) . ";"); } Ht::stash_script("assetsurl=" . json_encode($this->opt["assetsUrl"]) . ";"); $huser = (object) array(); if ($Me && $Me->email) { $huser->email = $Me->email; } if ($Me && $Me->is_pclike()) { $huser->is_pclike = true; } Ht::stash_script("hotcrp_user="******"ZeroClipboard.setDefaults({moviePath:\"" . Navigation::siteurl() . "cacheable" . Navigation::php_suffix() . "?file=scripts/ZeroClipboard.swf&mtime=" . filemtime("$ConfSitePATH/scripts/ZeroClipboard.swf") . "\"})"); // script.js if (!$this->opt("noDefaultScript")) { Ht::stash_html($this->make_script_file("scripts/script.js") . "\n"); } echo Ht::unstash(); echo "<title>"; if ($title) { echo $title, " - "; } echo htmlspecialchars($this->short_name), "</title>\n</head>\n"; }