public function select_pc($pcids) { $this->pcm = $this->load = []; $pcids = array_flip($pcids); foreach (pcMembers() as $cid => $p) { if (isset($pcids[$cid])) { $this->pcm[$cid] = $p; $this->load[$cid] = 0; } } return count($this->pcm); }
public function json() { // find out who is light and who is heavy // (light => less than 0.66 * (80th percentile)) $nass = array(); foreach ($this->r as $cid => $x) { $nass[] = count($x); } sort($nass); $heavy_boundary = 0; if (count($nass)) { $heavy_boundary = 0.66 * $nass[(int) (0.8 * count($nass))]; } $contacts = pcMembers(); $need_contacts = []; foreach ($this->r as $cid => $x) { if (!isset($contacts[$cid]) && ctype_digit($cid)) { $need_contacts[] = $cid; } } if (count($need_contacts)) { $result = Dbl::q("select firstName, lastName, affiliation, email, contactId, roles, contactTags, disabled from ContactInfo where contactId ?a", $need_contacts); while ($result && ($row = Contact::fetch($result))) { $contacts[$row->contactId] = $row; } } $users = array(); $tags = $this->contact->can_view_reviewer_tags(); foreach ($this->r as $cid => $x) { if ($cid != "conflicts") { $users[$cid] = $u = (object) array(); $p = get($contacts, $cid); if ($p) { $u->name = Text::name_text($p); } if (count($x) < $heavy_boundary) { $u->light = true; } if ($p && $tags && ($t = $p->viewable_color_classes($this->contact))) { $u->color_classes = $t; } } } return (object) array("reviews" => $this->r, "deadlines" => $this->dl, "users" => $users); }
function run(Contact $user, $qreq, $ssel) { global $Conf, $Opt; $q = $Conf->paperQuery($user, array("paperId" => $ssel->selection(), "allReviewerPreference" => 1, "allConflictType" => 1, "topics" => 1)); $result = Dbl::qe_raw($q); $texts = array(); $pcm = pcMembers(); $has_conflict = $has_expertise = $has_topic_score = false; while ($prow = PaperInfo::fetch($result, $user)) { if (!$user->can_administer($prow, true)) { continue; } $conflicts = $prow->conflicts(); foreach ($pcm as $cid => $p) { $pref = $prow->reviewer_preference($p); $conf = get($conflicts, $cid); $tv = $prow->topicIds ? $prow->topic_interest_score($p) : 0; if ($pref || $conf || $tv) { $texts[$prow->paperId][] = array("paper" => $prow->paperId, "title" => $prow->title, "first" => $p->firstName, "last" => $p->lastName, "email" => $p->email, "preference" => $pref[0] ?: "", "expertise" => unparse_expertise($pref[1]), "topic_score" => $tv ?: "", "conflict" => $conf ? "conflict" : ""); $has_conflict = $has_conflict || $conf; $has_expertise = $has_expertise || $pref[1] !== null; $has_topic_score = $has_topic_score || $tv; } } } $headers = array("paper", "title", "first", "last", "email", "preference"); if ($has_expertise) { $headers[] = "expertise"; } if ($has_topic_score) { $headers[] = "topic_score"; } if ($has_conflict) { $headers[] = "conflict"; } downloadCSV($ssel->reorder($texts), $headers, "allprefs", ["selection" => true]); }
function pc_members_selector_options($include_none) { global $Opt; $sel = array(); if ($include_none) { $sel["0"] = is_string($include_none) ? $include_none : "None"; } $textarg = array("lastFirst" => @$Opt["sortByLastName"]); foreach (pcMembers() as $p) { $sel[htmlspecialchars($p->email)] = Text::name_html($p, $textarg); } return $sel; }
function topic_interest_map() { global $Me; if ($this->topic_interest_map_ !== null) { return $this->topic_interest_map_; } if ($this->contactId <= 0) { return array(); } if ($this->roles & self::ROLE_PCLIKE && $this !== $Me && ($pcm = pcMembers()) && $this === get($pcm, $this->contactId)) { $result = Dbl::qe("select contactId, topicId, interest from TopicInterest where interest!=0 order by contactId"); foreach ($pcm as $pc) { $pc->topic_interest_map_ = array(); } $pc = null; while ($row = edb_row($result)) { if (!$pc || $pc->contactId != $row[0]) { $pc = get($pcm, $row[0]); } if ($pc) { $pc->topic_interest_map_[(int) $row[1]] = (int) $row[2]; } } Dbl::free($result); } else { $result = Dbl::qe("select topicId, interest from TopicInterest where contactId={$this->contactId} and interest!=0"); $this->topic_interest_map_ = Dbl::fetch_iimap($result); } return $this->topic_interest_map_; }
public function save($sv, $si) { global $Conf; if ($si->name == "tag_vote" && $sv->has_savedv("tag_vote")) { // check allotments $pcm = pcMembers(); foreach (preg_split('/\\s+/', $sv->savedv("tag_vote")) as $t) { if ($t === "") { continue; } $base = substr($t, 0, strpos($t, "#")); $allotment = substr($t, strlen($base) + 1); $result = Dbl::q("select paperId, tag, tagIndex from PaperTag where tag like '%~" . sqlq_for_like($base) . "'"); $pvals = array(); $cvals = array(); $negative = false; while ($row = edb_row($result)) { $who = substr($row[1], 0, strpos($row[1], "~")); if ($row[2] < 0) { $sv->set_error(null, "Removed " . Text::user_html($pcm[$who]) . "’s negative “{$base}” vote for paper #{$row['0']}."); $negative = true; } else { $pvals[$row[0]] = defval($pvals, $row[0], 0) + $row[2]; $cvals[$who] = defval($cvals, $who, 0) + $row[2]; } } foreach ($cvals as $who => $what) { if ($what > $allotment) { $sv->set_error("tag_vote", Text::user_html($pcm[$who]) . " already has more than {$allotment} votes for tag “{$base}”."); } } $q = $negative ? " or (tag like '%~" . sqlq_for_like($base) . "' and tagIndex<0)" : ""; $Conf->qe("delete from PaperTag where tag='" . sqlq($base) . "'{$q}"); $q = array(); foreach ($pvals as $pid => $what) { $q[] = "({$pid}, '" . sqlq($base) . "', {$what})"; } if (count($q) > 0) { $Conf->qe("insert into PaperTag values " . join(", ", $q)); } } } if ($si->name == "tag_approval" && $sv->has_savedv("tag_approval")) { $pcm = pcMembers(); foreach (preg_split('/\\s+/', $sv->savedv("tag_approval")) as $t) { if ($t === "") { continue; } $result = $Conf->q("select paperId, tag, tagIndex from PaperTag where tag like '%~" . sqlq_for_like($t) . "'"); $pvals = array(); $negative = false; while ($row = edb_row($result)) { $who = substr($row[1], 0, strpos($row[1], "~")); if ($row[2] < 0) { $sv->set_error(null, "Removed " . Text::user_html($pcm[$who]) . "’s negative “{$t}” approval vote for paper #{$row['0']}."); $negative = true; } else { $pvals[$row[0]] = defval($pvals, $row[0], 0) + 1; } } $q = $negative ? " or (tag like '%~" . sqlq_for_like($t) . "' and tagIndex<0)" : ""; $Conf->qe("delete from PaperTag where tag='" . sqlq($t) . "'{$q}"); $q = array(); foreach ($pvals as $pid => $what) { $q[] = "({$pid}, '" . sqlq($t) . "', {$what})"; } if (count($q) > 0) { $Conf->qe("insert into PaperTag values " . join(", ", $q)); } } } TagInfo::invalidate_defined_tags(); }
public function pc_conflicts($email = false) { return array_intersect_key($this->conflicts($email), pcMembers()); }
public function content($pl, $row, $rowidx) { $y = []; $pcm = pcMembers(); foreach ($row->conflicts() as $id => $type) { if ($pc = get($pcm, $id)) { $y[$pc->sort_position] = $pl->contact->reviewer_html_for($pc); } } ksort($y); return join(", ", $y); }
$pl_text = $pl->table_html("editReviewPreference", array("class" => "pltable_full", "table_id" => "foldpl", "attributes" => array("data-fold-session" => "pfdisplay.\$"), "footer_extra" => "<div id='plactr'>" . Ht::submit("update", "Save changes", array("class" => "hb")) . "</div>", "list_properties" => ["revprefs" => true])); // DISPLAY OPTIONS echo "<table id='searchform' class='tablinks1'>\n<tr><td>"; // <div class='tlx'><div class='tld1'>"; $showing_au = !$Conf->subBlindAlways() && strpos($pldisplay, " au ") !== false; $showing_anonau = (!$Conf->subBlindNever() || $Me->privChair) && strpos($pldisplay, " anonau ") !== false; echo Ht::form_div(hoturl("reviewprefs"), array("method" => "get", "id" => "redisplayform", "class" => $showing_au || $showing_anonau && $Conf->subBlindAlways() ? "fold10o" : "fold10c")), "<table>"; if ($Me->privChair) { echo "<tr><td class='lxcaption'><strong>Preferences:</strong> </td><td class='lentry'>"; $prefcount = array(); $result = $Conf->qe("select contactId, count(preference) from PaperReviewPreference where preference!=0 group by contactId"); while ($row = edb_row($result)) { $prefcount[$row[0]] = $row[1]; } $revopt = pc_members_selector_options(false); foreach (pcMembers() as $pcm) { if (!@$prefcount[$pcm->contactId]) { $revopt[htmlspecialchars($pcm->email)] .= " (no preferences)"; } } if (!isset($revopt[htmlspecialchars($reviewer_contact->email)])) { $revopt[htmlspecialchars($reviewer_contact->email)] = Text::name_html($Me) . " (not on PC)"; } echo Ht::select("reviewer", $revopt, htmlspecialchars($reviewer_contact->email), array("onchange" => "\$\$(\"redisplayform\").submit()")), "<div class='g'></div></td></tr>\n"; } echo "<tr><td class='lxcaption'><strong>Search:</strong></td><td class='lentry'><input type='text' size='32' name='q' value=\"", htmlspecialchars(defval($_REQUEST, "q", "")), "\" /><span class='sep'></span></td>", "<td>", Ht::submit("redisplay", "Redisplay"), "</td>", "</tr>\n"; $show_data = array(); if (!$Conf->subBlindAlways() && ($Conf->subBlindNever() || $pl->any->openau)) { $show_data[] = '<span class="sep">' . Ht::checkbox("showau", 1, strpos($pldisplay, " au ") !== false, array("disabled" => !$Conf->subBlindNever() && !$pl->any->openau, "onchange" => "plinfo('au',this)", "id" => "showau")) . " " . Ht::label("Authors") . '</span>'; } if (!$Conf->subBlindNever() && $Me->privChair) {
function run(Contact $user, $qreq, $ssel) { global $Conf; $allConflictTypes = Conflict::$type_descriptions; $allConflictTypes[CONFLICT_CHAIRMARK] = "Chair-confirmed"; $allConflictTypes[CONFLICT_AUTHOR] = "Author"; $allConflictTypes[CONFLICT_CONTACTAUTHOR] = "Contact"; $result = Dbl::qe_raw($Conf->paperQuery($user, ["paperId" => $ssel->selection(), "allConflictType" => 1])); $pcm = pcMembers(); $texts = array(); while ($prow = PaperInfo::fetch($result, $user)) { if ($user->can_view_conflicts($prow, true)) { $m = []; foreach ($prow->conflicts() as $cid => $c) { if (isset($pcm[$cid])) { $pc = $pcm[$cid]; $m[$pc->sort_position] = [$prow->paperId, $prow->title, $pc->firstName, $pc->lastName, $pc->email, get($allConflictTypes, $c->conflictType, "Conflict")]; } } if ($m) { ksort($m); $texts[$prow->paperId] = $m; } } } downloadCSV($ssel->reorder($texts), ["paper", "title", "first", "last", "email", "conflicttype"], "pcconflicts"); }
private static function _pcContactIdsWithTag($tag) { if ($tag === "pc") { return array_keys(pcMembers()); } $a = array(); foreach (pcMembers() as $cid => $pc) { if ($pc->has_tag($tag)) { $a[] = $cid; } } return $a; }
private function _prepare_reviewer_color(Contact $user) { $this->reviewer_color = array(); foreach (pcMembers() as $p) { $this->reviewer_color[$p->contactId] = TagInfo::color_classes($p->viewable_tags($user)); } }
public static function check_tagmap($cid, $tag) { if (($a = get(self::$tagmap, $tag)) === null) { $a = array(); foreach (pcMembers() as $pc) { if (($v = $pc->tag_value($tag)) !== false) { $a[$pc->contactId] = $v ?: true; } } self::$tagmap[$tag] = $a; } return get($a, $cid) ?: false; }
function paper_tag_normalize($prow) { $t = array(); $pcm = pcMembers(); foreach (explode(" ", $prow->all_tags_text()) as $tag) { if (($twiddle = strpos($tag, "~")) > 0 && ($c = @$pcm[substr($tag, 0, $twiddle)])) { $at = strpos($c->email, "@"); $tag = ($at ? substr($c->email, 0, $at) : $c->email) . substr($tag, $twiddle); } if (strlen($tag) > 2 && substr($tag, strlen($tag) - 2) == "#0") { $tag = substr($tag, 0, strlen($tag) - 2); } if ($tag) { $t[] = $tag; } } usort($t, "tag_normalize_compare"); return $t; }
public function stash_hotcrp_pc(Contact $user) { if (!Ht::mark_stash("hotcrp_pc")) { return; } $sortbylast = opt("sortByLastName"); $hpcj = $list = []; foreach (pcMembers() as $pcm) { $hpcj[$pcm->contactId] = $j = (object) ["name" => $user->name_html_for($pcm), "email" => $pcm->email]; if ($color_classes = $user->reviewer_color_classes_for($pcm)) { $j->color_classes = $color_classes; } if ($sortbylast && $pcm->lastName) { $r = Text::analyze_name($pcm); if (strlen($r->lastName) !== strlen($r->name)) { $j->lastpos = strlen(htmlspecialchars($r->firstName)) + 1; } if ($r->nameAmbiguous && $r->name && $r->email) { $j->emailpos = strlen(htmlspecialchars($r->name)) + 1; } } $list[] = $pcm->contactId; } $hpcj["__order__"] = $list; if ($sortbylast) { $hpcj["__sort__"] = "last"; } Ht::stash_script("hotcrp_pc=" . json_encode($hpcj) . ";"); }
if (is_array($qreq->papx)) { foreach ($qreq->papx as $p) { if (($p = cvtint($p)) > 0 && !isset($qreq->assrev[$p])) { $qreq->assrev[$p] = 0; } } } if (is_array($qreq->p) && $qreq->kind == "c") { foreach ($qreq->p as $p) { if (($p = cvtint($p)) > 0) { $qreq->assrev[$p] = -1; } } } $qreq->rev_roundtag = (string) $Conf->sanitize_round_name($qreq->rev_roundtag); $pcm = pcMembers(); $reviewer = cvtint($qreq->reviewer); if ($reviewer <= 0) { $reviewer = $Me->contactId; } if ($reviewer <= 0 || !isset($pcm[$reviewer])) { $reviewer = 0; } function saveAssignments($qreq, $reviewer) { global $Conf, $Me, $Now, $pcm; $reviewer_contact = $pcm[$reviewer]; $round_number = null; if (!count($qreq->assrev)) { return; }
function reviewTable($prow, $rrows, $crows, $rrow, $mode, $proposals = null) { global $Conf, $Me; $subrev = array(); $nonsubrev = array(); $foundRrow = $foundMyReview = $notShown = 0; $conflictType = $Me->view_conflict_type($prow); $allow_admin = $Me->allow_administer($prow); $admin = $Me->can_administer($prow); $hideUnviewable = $conflictType > 0 && !$admin || !$Me->act_pc($prow) && !$Conf->setting("extrev_view"); $show_colors = $Me->can_view_reviewer_tags($prow); $tagger = $show_colors ? new Tagger($Me) : null; $xsep = ' <span class="barsep">·</span> '; $want_scores = $mode !== "assign" && $mode !== "edit" && $mode !== "re"; $want_requested_by = false; $want_retract = false; $pcm = pcMembers(); $score_header = array(); // actual rows foreach ($rrows as $rr) { $highlight = $rrow && $rr->reviewId == $rrow->reviewId; $foundRrow += $highlight; if ($Me->is_my_review($rr)) { $foundMyReview++; } $canView = $Me->can_view_review($prow, $rr, null); // skip unsubmitted reviews if (!$canView && $hideUnviewable) { if ($rr->reviewNeedsSubmit == 1 && $rr->reviewModified) { $notShown++; } continue; } $t = ""; $tclass = $rrow && $highlight ? "hilite" : ""; // review ID $id = "Review"; if ($rr->reviewSubmitted) { $id .= " #" . $prow->paperId . unparseReviewOrdinal($rr->reviewOrdinal); } else { if ($rr->reviewType == REVIEW_SECONDARY && $rr->reviewNeedsSubmit <= 0) { $id .= " (delegated)"; } else { if ($rr->reviewModified > 0) { $id .= " (in progress)"; } else { $id .= " (not started)"; } } } $rlink = unparseReviewOrdinal($rr); if ($rrow && $rrow->reviewId == $rr->reviewId) { if ($Me->contactId == $rr->contactId && !$rr->reviewSubmitted) { $id = "Your {$id}"; } $t .= '<td><a href="' . hoturl("review", "p={$prow->paperId}&r={$rlink}") . '" class="q"><b>' . $id . '</b></a></td>'; } else { if (!$canView) { $t .= "<td>{$id}</td>"; } else { if ($rrow || $rr->reviewModified <= 0 || ($mode === "re" || $mode === "assign") && $Me->can_review($prow, $rr)) { $t .= '<td><a href="' . hoturl("review", "p={$prow->paperId}&r={$rlink}") . '">' . $id . '</a></td>'; } else { if (Navigation::page() !== "paper") { $t .= '<td><a href="' . hoturl("paper", "p={$prow->paperId}#r{$rlink}") . '">' . $id . '</a></td>'; } else { $t .= '<td><a href="#r' . $rlink . '">' . $id . '</a></td>'; } } } } // primary/secondary glyph if ($conflictType > 0 && !$admin) { $rtype = ""; } else { if ($rr->reviewType > 0) { $rtype = review_type_icon($rr->reviewType); if ($admin && $mode === "assign") { $rtype .= _review_table_round_selector($prow, $rr); } else { if ($rr->reviewRound > 0 && $Me->can_view_review_round($prow, $rr)) { $rtype .= ' <span class="revround" title="Review round">' . htmlspecialchars($Conf->round_name($rr->reviewRound, true)) . "</span>"; } } } else { $rtype = ""; } } // reviewer identity $showtoken = $rr->reviewToken && $Me->can_review($prow, $rr); if (!$Me->can_view_review_identity($prow, $rr, null)) { $t .= $rtype ? "<td>{$rtype}</td>" : '<td class="empty"></td>'; } else { if (!$showtoken || !Contact::is_anonymous_email($rr->email)) { $n = $Me->name_html_for($rr); } else { $n = "[Token " . encode_token((int) $rr->reviewToken) . "]"; } if ($allow_admin) { $n .= _review_table_actas($rr); } $t .= '<td class="rl"><span class="taghl">' . $n . '</span>' . ($rtype ? " {$rtype}" : "") . "</td>"; if ($show_colors && (get($rr, "contactRoles") || get($rr, "contactTags"))) { $tags = Contact::roles_all_contact_tags(get($rr, "contactRoles"), get($rr, "contactTags")); $tags = Tagger::strip_nonviewable($tags, $Me); if ($tags && ($color = TagInfo::color_classes($tags))) { $tclass = $color; } } } // requester if ($mode === "assign") { if (($conflictType <= 0 || $admin) && $rr->reviewType == REVIEW_EXTERNAL && !$showtoken) { $t .= '<td style="font-size:smaller">'; if ($rr->requestedBy == $Me->contactId) { $t .= "you"; } else { if ($u = get($pcm, $rr->requestedBy)) { $t .= $Me->reviewer_html_for($rr->requestedBy); } else { $t .= Text::user_html([$rr->reqFirstName, $rr->reqLastName, $rr->reqEmail]); } } $t .= '</td>'; $want_requested_by = true; } else { $t .= '<td class="empty"></td>'; } } // actions if ($mode === "assign" && ($conflictType <= 0 || $admin) && $rr->reviewType == REVIEW_EXTERNAL && $rr->reviewModified <= 0 && ($rr->requestedBy == $Me->contactId || $admin)) { $t .= '<td>' . _retract_review_request_form($prow, $rr) . '</td>'; } // scores $scores = array(); if ($want_scores && $canView) { $view_score = $Me->view_score_bound($prow, $rr); $rf = ReviewForm::get(); foreach ($rf->forder as $fid => $f) { if (!$f->has_options || $f->view_score <= $view_score || $f->round_mask && !$f->is_round_visible($rr)) { /* do nothing */ } else { if ($rr->{$fid}) { if (!get($score_header, $fid)) { $score_header[$fid] = "<th>" . $f->web_abbreviation() . "</th>"; } $scores[$fid] = '<td class="revscore" data-rf="' . $f->uid . '">' . $f->unparse_value($rr->{$fid}, ReviewField::VALUE_SC) . '</td>'; } else { if (get($score_header, $fid) === null) { $score_header[$fid] = ""; } } } } } // affix if (!$rr->reviewSubmitted) { $nonsubrev[] = array($tclass, $t, $scores); } else { $subrev[] = array($tclass, $t, $scores); } } // proposed review rows if ($proposals) { foreach ($proposals as $rr) { $t = ""; // review ID $t = "<td>Proposed review</td>"; // reviewer identity $t .= "<td>" . Text::user_html($rr); if ($allow_admin) { $t .= _review_table_actas($rr); } $t .= "</td>"; // requester if ($conflictType <= 0 || $admin) { $t .= '<td style="font-size:smaller">'; if ($rr->requestedBy == $Me->contactId) { $t .= "you"; } else { if ($u = get($pcm, $rr->requestedBy)) { $t .= $Me->reviewer_html_for($rr->requestedBy); } else { $t .= Text::user_html([$rr->reqFirstName, $rr->reqLastName, $rr->reqEmail]); } } $t .= '</td>'; $want_requested_by = true; } $t .= '<td>'; if ($admin) { $t .= '<small>' . Ht::form(hoturl_post("assign", "p={$prow->paperId}")) . '<div class="inline">' . Ht::hidden("name", $rr->name) . Ht::hidden("email", $rr->email) . Ht::hidden("reason", $rr->reason); if ($rr->reviewRound !== null) { if ($rr->reviewRound == 0) { $rname = "unnamed"; } else { $rname = $Conf->round_name($rr->reviewRound); } if ($rname) { $t .= Ht::hidden("round", $rname); } } $t .= Ht::submit("add", "Approve review", array("style" => "font-size:smaller")) . ' ' . Ht::submit("deny", "Deny request", array("style" => "font-size:smaller")) . '</div></form>'; } else { if ($rr->reqEmail === $Me->email) { $t .= _retract_review_request_form($prow, $rr); } } $t .= '</td>'; // affix $nonsubrev[] = array("", $t); } } // unfinished review notification $notetxt = ""; if ($conflictType >= CONFLICT_AUTHOR && !$admin && $notShown && $Me->can_view_review($prow, null, null)) { if ($notShown == 1) { $t = "1 review remains outstanding."; } else { $t = "{$notShown} reviews remain outstanding."; } $t .= '<br /><span class="hint">You will be emailed if new reviews are submitted or existing reviews are changed.</span>'; $notetxt = '<div class="revnotes">' . $t . "</div>"; } // completion if (count($nonsubrev) + count($subrev)) { if ($want_requested_by) { array_unshift($score_header, '<th class="revsl">Requester</th>'); } $score_header_text = join("", $score_header); $t = "<table class=\"reviewers"; if ($score_header_text) { $t .= " reviewers_scores"; } if ($list = SessionList::active()) { $t .= " has_hotcrp_list\" data-hotcrp-list=\"" . $list->listno; } $t .= "\">\n"; if ($score_header_text) { $t .= '<tr><td class="empty" colspan="2"></td>' . $score_header_text . "</tr>\n"; } foreach (array_merge($subrev, $nonsubrev) as $r) { $t .= '<tr class="rl' . ($r[0] ? " {$r['0']}" : "") . '">' . $r[1]; if (get($r, 2)) { foreach ($score_header as $fid => $header_needed) { if ($header_needed) { $x = get($r[2], $fid); $t .= $x ?: "<td class=\"revscore rs_{$fid}\"></td>"; } } } else { if (count($score_header)) { $t .= '<td colspan="' . count($score_header) . '"></td>'; } } $t .= "</tr>\n"; } if ($score_header_text) { $Conf->footerScript("review_form.score_tooltips(\$(\"table.reviewers_scores\"))", "score_tooltips"); } return $t . "</table>\n" . $notetxt; } else { return $notetxt; } }
private static function status_papers($status, $tracker, $acct) { global $Conf; $pids = array_slice($tracker->ids, $tracker->position, 3); $pc_conflicts = $acct->privChair || $acct->tracker_kiosk_state; $col = $j = ""; if ($pc_conflicts) { $col = ", allconfs.conflictIds"; $j = "left join (select paperId, group_concat(contactId) conflictIds from PaperConflict where paperId in (" . join(",", $pids) . ") group by paperId) allconfs on (allconfs.paperId=p.paperId)\n\t\t"; $pcm = pcMembers(); } $result = $Conf->qe("select p.paperId, p.title, p.paperFormat, p.leadContactId, p.managerContactId, r.reviewType, conf.conflictType{$col}\n from Paper p\n left join PaperReview r on (r.paperId=p.paperId and " . ($acct->contactId ? "r.contactId={$acct->contactId}" : "false") . ")\n left join PaperConflict conf on (conf.paperId=p.paperId and " . ($acct->contactId ? "conf.contactId={$acct->contactId}" : "false") . ")\n {$j}where p.paperId in (" . join(",", $pids) . ")"); $papers = array(); while ($row = PaperInfo::fetch($result, $acct)) { $papers[$row->paperId] = $p = (object) array(); if (($acct->privChair || !$row->conflictType || !get($status, "hide_conflicts")) && $acct->tracker_kiosk_state != 1) { $p->pid = (int) $row->paperId; $p->title = $row->title; if ($format = $row->title_format()) { $p->format = $format; } } if ($acct->contactId > 0 && $row->managerContactId == $acct->contactId) { $p->is_manager = true; } if ($row->reviewType) { $p->is_reviewer = true; } if ($row->conflictType) { $p->is_conflict = true; } if ($acct->contactId > 0 && $row->leadContactId == $acct->contactId) { $p->is_lead = true; } if ($pc_conflicts) { $p->pc_conflicts = array(); foreach (explode(",", (string) $row->conflictIds) as $cid) { if ($pc = get($pcm, $cid)) { $p->pc_conflicts[$pc->sort_position] = (object) array("email" => $pc->email, "name" => Text::name_text($pc)); } } ksort($p->pc_conflicts); $p->pc_conflicts = array_values($p->pc_conflicts); } } Dbl::free($result); $status->papers = array(); foreach ($pids as $pid) { $status->papers[] = $papers[$pid]; } }
$pctyp_sel[] = array($pctag, "pc_tags_members(\"{$tagname}\")", "#{$pctag}"); } } } $pctyp_sel[] = array("__flip__", -1, "flip"); $sep = ""; foreach ($pctyp_sel as $pctyp) { echo $sep, "<a href='#pc_", $pctyp[0], "' onclick='", "papersel(", $pctyp[1], ",\"pcs[]\");\$\$(\"pctyp_sel\").checked=true;return false'>", $pctyp[2], "</a>"; $sep = ", "; } echo ")</td></tr>\n<tr><td></td><td>"; $summary = []; $tagger = new Tagger($Me); $nrev = new AssignmentCountSet(); $nrev->load_rev(); foreach (pcMembers() as $p) { $t = '<div class="ctelt"><div class="ctelti'; if ($k = $p->viewable_color_classes($Me)) { $t .= ' ' . $k; } $t .= '"><table><tr><td class="nw">' . Ht::checkbox("pcs[]", $p->contactId, isset($pcsel[$p->contactId]), ["id" => "pcsel" . (count($summary) + 1), "onclick" => "rangeclick(event,this);\$\$('pctyp_sel').checked=true"]) . ' </td><td><span class="taghl">' . $Me->name_html_for($p) . '</span>' . AssignmentSet::review_count_report($nrev, null, $p, "") . "</td></tr></table><hr class=\"c\" />\n</div></div>"; $summary[] = $t; } echo '<div class="pc_ctable">', join("", $summary), "</div>\n", "</td></tr></table>\n"; // Bad pairs function bpSelector($i, $which) { static $badPairSelector, $Qreq; if (!$badPairSelector) { $badPairSelector = pc_members_selector_options("(PC member)"); }
function echo_grader() { global $Me, $User, $Pset, $Info; $gradercid = $Info->gradercid(); if ($Info->is_grading_commit() && $Me->can_see_grader($Pset, $User)) { $pcm = pcMembers(); $gpc = get($pcm, $gradercid); $value_post = ""; if ($Me->can_set_grader($Pset, $User)) { $sel = array(); if (!$gpc) { $sel["none"] = "(None)"; $sel[] = null; } foreach (pcMembers() as $pcm) { $sel[$pcm->email] = Text::name_html($pcm); } $value = Ht::form($Info->hoturl_post("pset", array("setgrader" => 1))) . "<div>" . Ht::select("grader", $sel, $gpc ? $gpc->email : "none", array("onchange" => "setgrader61(this)")); $value_post = "<span class=\"ajaxsave61\"></span></div></form>"; } else { if (isset($pcm[$gradercid])) { $value = Text::name_html($pcm[$gradercid]); } else { $value = "???"; } } if ($Me->privChair) { $value .= " " . become_user_link($gpc); } ContactView::echo_group("grader", $value . $value_post); } }
public function apply(Contact $user, $pj, $opj, $qreq, $action) { global $Conf; // Title, abstract, collaborators foreach (array("title", "abstract", "collaborators") as $k) { if (isset($qreq[$k])) { $pj->{$k} = $qreq[$k]; } } // Authors $bad_author = ["name" => "Name", "email" => "Email", "aff" => "Affiliation"]; $authors = array(); foreach ($qreq as $k => $v) { if (preg_match('/\\Aau(name|email|aff)(\\d+)\\z/', $k, $m) && ($v = simplify_whitespace($v)) !== "" && $v !== $bad_author[$m[1]]) { $au = $authors[$m[2]] = get($authors, $m[2]) ?: (object) array(); $x = $m[1] == "aff" ? "affiliation" : $m[1]; $au->{$x} = $v; } } if (!empty($authors)) { ksort($authors, SORT_NUMERIC); $pj->authors = array_values($authors); } // Contacts if ($qreq->setcontacts || $qreq->has_contacts) { PaperSaver::replace_contacts($pj, $qreq); } else { if (!$opj) { $pj->contacts = array($user); } } // Status if ($action === "submit") { $pj->submitted = true; } else { if ($action === "final") { $pj->final_submitted = true; } else { $pj->submitted = false; } } // Paper upload if ($qreq->_FILES->paperUpload) { if ($action === "final") { $pj->final = Filer::file_upload_json($qreq->_FILES->paperUpload); } else { if ($action === "update" || $action === "submit") { $pj->submission = Filer::file_upload_json($qreq->_FILES->paperUpload); } } } // Blindness if ($action !== "final" && $Conf->subBlindOptional()) { $pj->nonblind = !$qreq->blind; } // Topics if ($qreq->has_topics) { $pj->topics = (object) array(); foreach ($Conf->topic_map() as $tid => $tname) { if (+$qreq["top{$tid}"] > 0) { $pj->topics->{$tname} = true; } } } // Options if (!isset($pj->options)) { $pj->options = (object) []; } foreach (PaperOption::option_list() as $o) { if ($qreq["has_opt{$o->id}"] && (!$o->final || $action === "final")) { $okey = $o->abbr; $pj->options->{$okey} = $o->parse_request(get($pj->options, $okey), $qreq, $user, $pj); } } if (!count(get_object_vars($pj->options))) { unset($pj->options); } // PC conflicts if ($Conf->setting("sub_pcconf") && ($action !== "final" || $user->privChair) && $qreq->has_pcconf) { $cmax = $user->privChair ? CONFLICT_CHAIRMARK : CONFLICT_MAXAUTHORMARK; $pj->pc_conflicts = (object) array(); foreach (pcMembers() as $pcid => $pc) { $ctype = cvtint($qreq["pcc{$pcid}"], 0); $ctype = max(min($ctype, $cmax), 0); if ($ctype) { $email = $pc->email; $pj->pc_conflicts->{$email} = Conflict::$type_names[$ctype]; } } } }
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"; }
function pcByEmail($email) { $pc = pcMembers(); foreach ($pc as $id => $row) { if ($row->email == $email) { return $row; } } return null; }
static function pcassignments_csv_data($user, $selection) { global $Conf; $pcm = pcMembers(); $round_list = $Conf->round_list(); $reviewnames = array(REVIEW_PC => "pcreview", REVIEW_SECONDARY => "secondary", REVIEW_PRIMARY => "primary"); $any_round = false; $texts = array(); $result = Dbl::qe_raw($Conf->paperQuery($user, array("paperId" => $selection, "assignments" => 1))); while ($prow = PaperInfo::fetch($result, $user)) { if (!$user->allow_administer($prow)) { $texts[] = array(); $texts[] = array("paper" => $prow->paperId, "action" => "none", "title" => "You cannot override your conflict with this paper"); } else { if ($prow->all_reviewers()) { $texts[] = array(); $texts[] = array("paper" => $prow->paperId, "action" => "clearreview", "email" => "#pc", "round" => "any", "title" => $prow->title); foreach ($prow->all_reviewers() as $cid) { if (($pc = get($pcm, $cid)) && ($rtype = $prow->review_type($cid)) >= REVIEW_PC) { $round = $prow->review_round($cid); $round_name = $round ? $round_list[$round] : "none"; $any_round = $any_round || $round != 0; $texts[] = array("paper" => $prow->paperId, "action" => $reviewnames[$rtype], "email" => $pc->email, "round" => $round_name); } } } } } $header = array("paper", "action", "email"); if ($any_round) { $header[] = "round"; } $header[] = "title"; return [$header, $texts]; }
function echo_unparse_display() { $this->set_my_conflicts(); $bypaper = array(); foreach ($this->assigners as $assigner) { if ($text = $assigner->unparse_display($this)) { $c = $assigner->contact; if ($c && !isset($c->sorter)) { Contact::set_sorter($c); } arrayappend($bypaper[$assigner->pid], (object) array("text" => $text, "sorter" => $c ? $c->sorter : $text)); } } AutoassignmentPaperColumn::$header = "Assignment"; $assinfo = array(); PaperColumn::register(new AutoassignmentPaperColumn()); foreach ($bypaper as $pid => $list) { uasort($list, "Contact::compare"); $t = ""; foreach ($list as $x) { $t .= ($t ? ", " : "") . '<span class="nw">' . $x->text . '</span>'; } if (isset($this->my_conflicts[$pid])) { if ($this->my_conflicts[$pid] !== true) { $t = '<em>Hidden for conflict</em>'; } else { $t = PaperList::wrapChairConflict($t); } } $assinfo[$pid] = $t; } ksort($assinfo); AutoassignmentPaperColumn::$info = $assinfo; if ($this->unparse_search) { $query_order = "(" . $this->unparse_search . ") THEN HEADING:none " . join(" ", array_keys($assinfo)); } else { $query_order = count($assinfo) ? join(" ", array_keys($assinfo)) : "NONE"; } foreach ($this->unparse_columns as $k => $v) { $query_order .= " show:{$k}"; } $query_order .= " show:autoassignment"; $search = new PaperSearch($this->contact, array("t" => defval($_REQUEST, "t", "s"), "q" => $query_order)); $plist = new PaperList($search); echo $plist->table_html("reviewers", ["nofooter" => 1]); $deltarev = new AssignmentCountSet(); foreach ($this->assigners as $assigner) { $assigner->account($deltarev); } if (count(array_intersect_key($deltarev->bypc, pcMembers()))) { $summary = []; $tagger = new Tagger($this->contact); $nrev = new AssignmentCountSet(); $deltarev->rev && $nrev->load_rev(); $deltarev->lead && $nrev->load_lead(); $deltarev->shepherd && $nrev->load_shepherd(); foreach (pcMembers() as $p) { if ($deltarev->get($p->contactId)->ass) { $t = '<div class="ctelt"><div class="ctelti'; if ($k = $p->viewable_color_classes($this->contact)) { $t .= ' ' . $k; } $t .= '"><span class="taghl">' . $this->contact->name_html_for($p) . "</span>: " . plural($deltarev->get($p->contactId)->ass, "assignment") . self::review_count_report($nrev, $deltarev, $p, "After assignment: ") . "<hr class=\"c\" /></div></div>"; $summary[] = $t; } } if (count($summary)) { echo "<div class=\"g\"></div>\n", "<h3>Summary</h3>\n", '<div class="pc_ctable">', join("", $summary), "</div>\n"; } } }
function pcAssignments() { global $Conf, $Me, $prow; $pcm = pcMembers(); $rname = (string) $Conf->sanitize_round_name(@$_REQUEST["rev_roundtag"]); $round_number = null; $where = array("(ContactInfo.roles&" . Contact::ROLE_PC . ")!=0"); if (@$_REQUEST["reviewer"] && isset($pcm[$_REQUEST["reviewer"]])) { $where[] = "ContactInfo.contactId='" . $_REQUEST["reviewer"] . "'"; } Dbl::qe_raw("lock tables PaperReview write, PaperReviewRefused write, PaperConflict write, ContactInfo read, ActionLog write, Settings write"); // don't record separate PC conflicts on author conflicts $result = Dbl::qe_raw("select ContactInfo.contactId,\n PaperConflict.conflictType, reviewType, reviewModified, reviewId\n from ContactInfo\n left join PaperConflict on (PaperConflict.contactId=ContactInfo.contactId and PaperConflict.paperId={$prow->paperId})\n left join PaperReview on (PaperReview.contactId=ContactInfo.contactId and PaperReview.paperId={$prow->paperId})\n where " . join(" and ", $where)); while ($row = edb_orow($result)) { $pctype = defval($_REQUEST, "pcs{$row->contactId}", 0); if ($row->conflictType >= CONFLICT_AUTHOR) { continue; } // manage conflicts if ($row->conflictType && $pctype >= 0) { Dbl::qe_raw("delete from PaperConflict where paperId={$prow->paperId} and contactId={$row->contactId}"); } else { if (!$row->conflictType && $pctype < 0) { Dbl::qe_raw("insert into PaperConflict (paperId, contactId, conflictType) values ({$prow->paperId}, {$row->contactId}, " . CONFLICT_CHAIRMARK . ")"); } } // manage assignments $pctype = max($pctype, 0); if ($pctype != $row->reviewType && ($pctype == 0 || $pctype == REVIEW_PRIMARY || $pctype == REVIEW_SECONDARY || $pctype == REVIEW_PC) && ($pctype == 0 || $pcm[$row->contactId]->can_accept_review_assignment($prow))) { if ($pctype != 0 && $round_number === null) { $round_number = $Conf->round_number($rname, true); } $Me->assign_review($prow->paperId, $row->contactId, $pctype, array("round_number" => $round_number)); } } }
function show_pset_table($pset) { global $Conf, $Me, $Now, $Opt, $Profile, $LastPsetFix; echo '<div id="', $pset->urlkey, '">'; echo "<h3>", htmlspecialchars($pset->title), "</h3>"; if ($Me->privChair) { show_pset_actions($pset); } if ($pset->disabled) { return; } $t0 = $Profile ? microtime(true) : 0; // load students if (@$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.seascode_username, c.anon_username, c.extension, c.disabled, c.dropped, c.roles, c.contactTags,\n\tpl.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"); $t1 = $Profile ? microtime(true) : 0; $students = array(); while ($result && ($s = $result->fetch_object("Contact"))) { $s->is_anonymous = $pset->anonymous; Contact::set_sorter($s, @$_REQUEST["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(); foreach ($students as $s) { if (!isset($s->printed)) { $row = (object) array("student" => $s); $row->text = render_pset_row($pset, $students, $s, $row, $pcmembers); if ($s->pcid && isset($students[$s->pcid])) { $row->ptext = render_pset_row($pset, $students, $students[$s->pcid], $row, $pcmembers); } $rows[$row->sortprefix . $s->sorter] = $row; $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" => @$_REQUEST["sort"])) . '">' . htmlspecialchars($u) . '</a>'; } } } ksort($rows, SORT_NATURAL | SORT_FLAG_CASE); 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))); } echo '<table class="s61"><tbody>'; $trn = 0; $sprefix = ""; foreach ($rows as $row) { ++$trn; if ($row->sortprefix !== $sprefix && $row->sortprefix[0] == "~") { echo "\n", '<tr><td colspan="' . ($max_ncol + ($checkbox ? 2 : 1)) . '"><hr></td></tr>', "\n"; } $sprefix = $row->sortprefix; echo '<tr class="k', $trn % 2, '">'; if ($checkbox) { echo '<td class="s61rownumber">', Ht::checkbox("s61_" . $Me->user_idpart($row->student), 1, array("class" => "s61check")), '</td>'; } echo '<td class="s61rownumber">', $trn, '.</td>', $row->text, "</tr>\n"; if (@$row->ptext) { echo '<tr class="k', $trn % 2, ' s61partner">'; if ($checkbox) { echo '<td></td>'; } echo '<td></td>', $row->ptext, "</tr>\n"; } } echo "</tbody></table>\n"; 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="nowrap" 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="nowrap" 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 _rows($field_list) { global $Conf; if (!$field_list) { return null; } // prepare query text $this->qopts["scores"] = array_keys($this->qopts["scores"]); if (empty($this->qopts["scores"])) { unset($this->qopts["scores"]); } $pq = $Conf->paperQuery($this->contact, $this->qopts); // make query $result = Dbl::qe_raw($pq); if (!$result) { return null; } // fetch rows $rows = array(); while ($row = PaperInfo::fetch($result, $this->contact)) { $rows[$row->paperId] = $row; } // prepare review query (see also search > getfn == "reviewers") $this->review_list = array(); if (isset($this->qopts["reviewList"]) && !empty($rows)) { $result = Dbl::qe("select Paper.paperId, reviewId, reviewType,\n reviewSubmitted, reviewModified, reviewNeedsSubmit, reviewRound,\n reviewOrdinal,\n PaperReview.contactId, lastName, firstName, email\n from Paper\n join PaperReview using (paperId)\n join ContactInfo on (PaperReview.contactId=ContactInfo.contactId)\n where paperId?a", array_keys($rows)); while ($row = edb_orow($result)) { Contact::set_sorter($row); $this->review_list[$row->paperId][] = $row; } foreach ($this->review_list as &$revlist) { usort($revlist, "PaperList::review_list_compar"); } unset($revlist); } // prepare PC topic interests if (isset($this->qopts["allReviewerPreference"])) { $ord = 0; $pcm = pcMembers(); foreach ($pcm as $pc) { $pc->prefOrdinal = sprintf("-0.%04d", $ord++); $pc->topicInterest = array(); } $result = Dbl::qe("select contactId, topicId, " . $Conf->query_topic_interest() . " from TopicInterest"); while ($row = edb_row($result)) { $pcm[$row[0]]->topicInterest[$row[1]] = $row[2]; } } // analyze rows (usually noop) foreach ($field_list as $fdef) { $fdef->analyze($this, $rows); } // sort rows if (!empty($this->sorters)) { $rows = $this->_sort($rows); if (isset($this->qopts["allReviewScores"])) { $this->_sortReviewOrdinal($rows); } } // set `any->optID` if ($nopts = PaperOption::count_option_list()) { foreach ($rows as $prow) { foreach ($prow->options() as $o) { if (!$this->any["opt{$o->id}"] && $this->contact->can_view_paper_option($prow, $o->option)) { $this->any["opt{$o->id}"] = true; --$nopts; } } if (!$nopts) { break; } } } Dbl::free($result); return $rows; }
function expandvar_recipient($what, $isbool) { global $Conf; if ($what == "%NEWASSIGNMENTS%") { return $this->get_new_assignments($this->recipient); } // rest is only there if we have a real paper if (!$this->row || get($this->row, "paperId") <= 0) { return self::EXPANDVAR_CONTINUE; } if ($this->preparation) { ++$this->preparation->paper_expansions; } if ($what == "%TITLE%") { return $this->row->title; } if ($what == "%TITLEHINT%") { if ($tw = UnicodeHelper::utf8_abbreviate($this->row->title, 40)) { return "\"{$tw}\""; } else { return ""; } } if ($what == "%NUMBER%" || $what == "%PAPER%") { return $this->row->paperId; } if ($what == "%REVIEWNUMBER%") { return $this->reviewNumber; } if ($what == "%AUTHOR%" || $what == "%AUTHORS%") { if (!$this->permissionContact->is_site_contact && !$this->row->has_author($this->permissionContact) && !$this->permissionContact->can_view_authors($this->row, false)) { return $isbool ? false : "Hidden for blind review"; } return rtrim($this->row->pretty_text_author_list()); } if ($what == "%AUTHORVIEWCAPABILITY%" && isset($this->row->capVersion) && $this->permissionContact->act_author_view($this->row)) { return "cap=" . $Conf->capability_text($this->row, "a"); } if ($what == "%SHEPHERD%" || $what == "%SHEPHERDNAME%" || $what == "%SHEPHERDEMAIL%") { $pc = pcMembers(); if (defval($this->row, "shepherdContactId") <= 0 || !defval($pc, $this->row->shepherdContactId, null)) { if ($isbool) { return false; } else { if ($this->expansionType == self::EXPAND_EMAIL) { return "<none>"; } else { return "(no shepherd assigned)"; } } } $shep = $pc[$this->row->shepherdContactId]; if ($what == "%SHEPHERD%") { return $this->expand_user($shep, "CONTACT"); } else { if ($what == "%SHEPHERDNAME%") { return $this->expand_user($shep, "NAME"); } else { return $this->expand_user($shep, "EMAIL"); } } } if ($what == "%REVIEWAUTHOR%" && $this->contacts["reviewer"]) { return $this->_expand_reviewer("CONTACT", $isbool); } if ($what == "%REVIEWS%") { return $this->get_reviews(); } if ($what == "%COMMENTS%") { return $this->get_comments(null); } $len = strlen($what); if ($len > 12 && substr($what, 0, 10) == "%COMMENTS(" && substr($what, $len - 2) == ")%") { if ($t = $this->tagger()->check(substr($what, 10, $len - 12), Tagger::NOVALUE)) { return $this->get_comments($t); } } if ($len > 12 && substr($what, 0, 10) == "%TAGVALUE(" && substr($what, $len - 2) == ")%") { if ($t = $this->tagger()->check(substr($what, 10, $len - 12), Tagger::NOVALUE | Tagger::NOPRIVATE)) { if (!isset($this->_tags[$t])) { $this->_tags[$t] = array(); $result = Dbl::qe("select paperId, tagIndex from PaperTag where tag=?", $t); while ($row = edb_row($result)) { $this->_tags[$t][$row[0]] = $row[1]; } } $tv = defval($this->_tags[$t], $this->row->paperId); if ($isbool) { return $tv !== null; } else { if ($tv !== null) { return $tv; } else { $this->_tagless[$this->row->paperId] = true; return "(none)"; } } } } if ($this->preparation) { --$this->preparation->paper_expansions; } return self::EXPANDVAR_CONTINUE; }