echo "<table><tr>\n";
     foreach ($col as $thecol) {
         if (count($thecol)) {
             echo "<td class='top'><table>";
             foreach ($thecol as $td) {
                 echo "<tr><td style='padding:0 2em 1ex 0'>", $td, "</td></tr>";
             }
             echo "</table></td>\n";
         }
     }
     echo "</tr></table>\n";
 }
 // ajax assignment form
 echo Ht::form(hoturl_post("assign", "update=1"), array("id" => "assrevform")), "<div class='clear'>", Ht::hidden("kind", $qreq->kind), Ht::hidden("p", ""), Ht::hidden("pcs{$reviewer}", ""), Ht::hidden("reviewer", $reviewer), Ht::hidden("rev_roundtag", $qreq->rev_roundtag), "</div></form>\n\n";
 // main assignment form
 $search = new PaperSearch($Me, array("t" => $qreq->t, "q" => $qreq->q, "urlbase" => hoturl_site_relative_raw("manualassign", "reviewer={$reviewer}")));
 $paperList = new PaperList($search, ["sort" => true, "list" => true, "reviewer" => $pcm[$reviewer]], make_qreq());
 $paperList->display .= " topics ";
 if ($qreq->kind != "c") {
     $paperList->display .= "reviewers ";
 }
 if (isset($showau)) {
     $search->overrideMatchPreg = true;
     $search->matchPreg = array();
     if ($showau) {
         $search->matchPreg["authorInformation"] = make_match_preg($showau);
     }
     if ($showco) {
         $search->matchPreg["collaborators"] = make_match_preg($showco);
     }
 }
 private static function try_list($opt, $listtype, $sort = null)
 {
     global $Conf, $Me;
     if ($listtype == "u" && $Me->privChair) {
         $searchtype = defval($opt, "t") === "all" ? "all" : "pc";
         $q = "select contactId from ContactInfo";
         if ($searchtype == "pc") {
             $q .= " where (roles&" . Contact::ROLE_PC . ")!=0";
         }
         $result = Dbl::ql("{$q} order by lastName, firstName, email");
         $a = array();
         while ($row = edb_row($result)) {
             $a[] = (int) $row[0];
         }
         Dbl::free($result);
         return self::create("u/" . $searchtype, $a, $searchtype == "pc" ? "Program committee" : "Users", hoturl_site_relative_raw("users", "t={$searchtype}"));
     } else {
         $search = new PaperSearch($Me, $opt);
         $x = $search->session_list_object($sort);
         if ($sort || $search->has_sort()) {
             $pl = new PaperList($search, array("sort" => $sort));
             $x->ids = $pl->id_array();
         }
         return $x;
     }
 }
// paper selection
echo divClass("pap"), "<h3>Paper selection</h3>";
if (!isset($Qreq->q)) {
    // XXX redundant
    $Qreq->q = join(" ", $SSel->selection());
}
echo Ht::entry_h("q", $Qreq->q, array("id" => "autoassignq", "placeholder" => "(All)", "size" => 40, "title" => "Enter paper numbers or search terms", "class" => "hotcrp_searchbox", "onfocus" => 'autosub("requery",this)')), " &nbsp;in &nbsp;";
if (count($tOpt) > 1) {
    echo Ht::select("t", $tOpt, $Qreq->t, array("onchange" => "highlightUpdate(\"requery\")"));
} else {
    echo join("", $tOpt);
}
echo " &nbsp; ", Ht::submit("requery", "List", array("id" => "requery"));
if (isset($Qreq->requery) || isset($Qreq->haspap)) {
    echo "<br /><span class='hint'>Assignments will apply to the selected papers.</span>\n<div class='g'></div>";
    $search = new PaperSearch($Me, array("t" => $Qreq->t, "q" => $Qreq->q, "urlbase" => hoturl_site_relative_raw("autoassign")));
    $plist = new PaperList($search);
    $plist->display .= " reviewers ";
    $plist->papersel = $SSel->selection_map();
    echo $plist->table_html("reviewersSel", ["nofooter" => true]), Ht::hidden("prevt", $Qreq->t), Ht::hidden("prevq", $Qreq->q), Ht::hidden("haspap", 1);
}
echo "</div>\n";
// echo "<tr><td class='caption'></td><td class='entry'><div class='g'></div></td></tr>\n";
// action
echo divClass("ass"), "<h3>Action</h3>";
echo divClass("rev", "hotradiorelation");
doRadio("a", "rev", "Ensure each selected paper has <i>at least</i>");
echo "&nbsp; ", Ht::entry("revct", get($Qreq, "revct", 1), array("size" => 3, "onfocus" => 'autosub(false,this)')), "&nbsp; ";
doSelect("revtype", array(REVIEW_PRIMARY => "primary", REVIEW_SECONDARY => "secondary", REVIEW_PC => "optional"));
echo "&nbsp; review(s)</div>\n";
echo divClass("revadd", "hotradiorelation");
if (isset($_REQUEST["redisplay"])) {
    $pfd = " ";
    foreach ($_REQUEST as $k => $v) {
        if (substr($k, 0, 4) == "show" && $v) {
            $pfd .= substr($k, 4) . " ";
        }
    }
    $Conf->save_session("pfdisplay", $pfd);
    redirectSelf();
}
$pldisplay = displayOptionsSet("pfdisplay");
// Header and body
$Conf->header("Review preferences", "revpref", actionBar());
$Conf->infoMsg($Conf->message_html("revprefdescription"));
// search
$search = new PaperSearch($Me, array("t" => "rable", "urlbase" => hoturl_site_relative_raw("reviewprefs", "reviewer={$reviewer}"), "q" => defval($_REQUEST, "q", "")), $reviewer);
$pl = new PaperList($search, ["sort" => true, "list" => true, "row_id_pattern" => "p#", "foldtype" => "pf", "reviewer" => $reviewer_contact], make_qreq());
$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> &nbsp;</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];
    }
 function __construct($me, $options, $reviewer = false)
 {
     global $Conf;
     if (is_string($options)) {
         $options = array("q" => $options);
     }
     // contact facts
     $this->contact = $me;
     $this->privChair = $me->privChair;
     $this->amPC = $me->isPC;
     $this->cid = $me->contactId;
     // paper selection
     $ptype = get_s($options, "t");
     if ($ptype === 0) {
         $ptype = "";
     }
     if ($this->privChair && !$ptype && $Conf->timeUpdatePaper()) {
         $this->limitName = "all";
     } else {
         if ($me->privChair && $ptype === "act" || $me->isPC && (!$ptype || $ptype === "act" || $ptype === "all") && $Conf->can_pc_see_all_submissions()) {
             $this->limitName = "act";
         } else {
             if ($me->privChair && $ptype === "unm") {
                 $this->limitName = "unm";
             } else {
                 if ($me->isPC && (!$ptype || $ptype === "s" || $ptype === "unm")) {
                     $this->limitName = "s";
                 } else {
                     if ($me->isPC && ($ptype === "und" || $ptype === "undec")) {
                         $this->limitName = "und";
                     } else {
                         if ($me->isPC && ($ptype === "acc" || $ptype === "revs" || $ptype === "reqrevs" || $ptype === "req" || $ptype === "lead" || $ptype === "rable" || $ptype === "manager")) {
                             $this->limitName = $ptype;
                         } else {
                             if ($this->privChair && ($ptype === "all" || $ptype === "unsub")) {
                                 $this->limitName = $ptype;
                             } else {
                                 if ($ptype === "r" || $ptype === "rout" || $ptype === "a") {
                                     $this->limitName = $ptype;
                                 } else {
                                     if ($ptype === "rable") {
                                         $this->limitName = "r";
                                     } else {
                                         if (!$me->is_reviewer()) {
                                             $this->limitName = "a";
                                         } else {
                                             if (!$me->is_author()) {
                                                 $this->limitName = "r";
                                             } else {
                                                 $this->limitName = "ar";
                                             }
                                         }
                                     }
                                 }
                             }
                         }
                     }
                 }
             }
         }
     }
     // track other information
     $this->allowAuthor = false;
     if ($me->privChair || $me->is_author() || $this->amPC && $Conf->submission_blindness() != Conf::BLIND_ALWAYS) {
         $this->allowAuthor = true;
     }
     // default query fields
     // NB: If a complex query field, e.g., "re", "tag", or "option", is
     // default, then it must be the only default or query construction
     // will break.
     $this->fields = array();
     $qtype = defval($options, "qt", "n");
     if ($qtype === "n" || $qtype === "ti") {
         $this->fields["ti"] = 1;
     }
     if ($qtype === "n" || $qtype === "ab") {
         $this->fields["ab"] = 1;
     }
     if ($this->allowAuthor && ($qtype === "n" || $qtype === "au" || $qtype === "ac")) {
         $this->fields["au"] = 1;
     }
     if ($this->privChair && $qtype === "ac") {
         $this->fields["co"] = 1;
     }
     if ($this->amPC && $qtype === "re") {
         $this->fields["re"] = 1;
     }
     if ($this->amPC && $qtype === "tag") {
         $this->fields["tag"] = 1;
     }
     $this->qt = $qtype === "n" ? "" : $qtype;
     // the query itself
     $this->q = trim(get_s($options, "q"));
     // URL base
     if (isset($options["urlbase"])) {
         $this->urlbase = $options["urlbase"];
     } else {
         $this->urlbase = hoturl_site_relative_raw("search", "t=" . urlencode($this->limitName));
         if ($qtype !== "n") {
             $this->urlbase .= "&qt=" . urlencode($qtype);
         }
     }
     if (strpos($this->urlbase, "&amp;") !== false) {
         trigger_error(caller_landmark() . " PaperSearch::urlbase should be a raw URL", E_USER_NOTICE);
     }
     $this->_reviewer = $reviewer;
     if ($this->_reviewer === false) {
         $this->_reviewer = get($options, "reviewer", false);
     }
     $this->_reviewer_fixed = !!$this->_reviewer;
     if ($this->_reviewer && $reviewer === false) {
         error_log("PaperSearch::\$reviewer set: " . json_encode(debug_backtrace(DEBUG_BACKTRACE_IGNORE_ARGS)));
     }
     $this->_allow_deleted = defval($options, "allow_deleted", false);
 }
// special case: if "accept" or "refuse" is set, and "email" and "password"
// are both set, vector through the signin page
if (isset($_REQUEST["email"]) && isset($_REQUEST["password"]) && (isset($_REQUEST["accept"]) || isset($_REQUEST["refuse"]) || isset($_REQUEST["decline"]))) {
    PaperTable::cleanRequest();
    $after = "";
    foreach (array("paperId" => "p", "pap" => "p", "reviewId" => "r", "commentId" => "c") as $k => $v) {
        if (isset($_REQUEST[$k]) && !isset($_REQUEST[$v])) {
            $_REQUEST[$v] = $_GET[$v] = $_POST[$v] = $_REQUEST[$k];
        }
    }
    foreach (array("p", "r", "c", "accept", "refuse", "decline") as $opt) {
        if (isset($_REQUEST[$opt])) {
            $after .= ($after === "" ? "" : "&") . $opt . "=" . urlencode($_REQUEST[$opt]);
        }
    }
    $url = hoturl_site_relative_raw("review", $after);
    go(hoturl("index", "email=" . urlencode($_REQUEST["email"]) . "&password="******"password"]) . "&go=" . urlencode($url)));
}
if ($Me->is_empty()) {
    $Me->escape();
}
$rf = ReviewForm::get();
// header
function confHeader()
{
    global $paperTable;
    PaperTable::do_header($paperTable, "review", @$_REQUEST["mode"]);
}
function errorMsgExit($msg)
{
    global $Conf;
 function table_html($listname, $url, $listtitle = "", $foldsession = null)
 {
     global $Conf, $contactListFields;
     // PC tags
     $listquery = $listname;
     $queryOptions = array();
     if (str_starts_with($listname, "#")) {
         $queryOptions["where"] = "(u.contactTags like " . Dbl::utf8ci("'% " . sqlq_for_like(substr($listname, 1)) . "#%'") . ")";
         $listquery = "pc";
     }
     // get paper list
     if (!($baseFieldId = $this->listFields($listquery))) {
         Conf::msg_error("There is no people list query named “" . htmlspecialchars($listquery) . "”.");
         return null;
     }
     $this->limit = array_shift($baseFieldId);
     // get field array
     $fieldDef = array();
     $acceptable_fields = array();
     $this->any = (object) array("sel" => false);
     $ncol = 0;
     foreach ($baseFieldId as $fid) {
         if ($this->selector($fid, $queryOptions) === false) {
             continue;
         }
         if (!($fieldDef[$fid] = @$contactListFields[$fid])) {
             $fieldDef[$fid] = $contactListFields[self::FIELD_SCORE];
         }
         $acceptable_fields[$fid] = true;
         if ($fieldDef[$fid][1] == 1) {
             $ncol++;
         }
     }
     // run query
     $rows = $this->_rows($queryOptions);
     if (!$rows || count($rows) == 0) {
         return "No matching people";
     }
     // list number
     if ($this->listNumber === true) {
         $this->listNumber = SessionList::allocate("u/" . $this->limit);
         $this->contactLinkArgs .= "&amp;ls=" . $this->listNumber;
     }
     // sort rows
     if (!@$acceptable_fields[$this->sortField]) {
         $this->sortField = null;
     }
     $srows = $this->_sort($rows);
     // count non-callout columns
     $firstcallout = $lastcallout = null;
     $n = 0;
     foreach ($fieldDef as $fieldId => $fdef) {
         if ($fdef[1] == 1) {
             if ($firstcallout === null && $fieldId < self::FIELD_SELECTOR) {
                 $firstcallout = $n;
             }
             if ($fieldId < self::FIELD_SCORE) {
                 $lastcallout = $n + 1;
             }
             ++$n;
         }
     }
     $firstcallout = $firstcallout ? $firstcallout : 0;
     $lastcallout = ($lastcallout ? $lastcallout : $ncol) - $firstcallout;
     // collect row data
     $this->count = 0;
     $show_colors = $this->contact->isPC;
     $anyData = array();
     $body = '';
     $extrainfo = $hascolors = false;
     $ids = array();
     foreach ($srows as $row) {
         if (($this->limit == "resub" || $this->limit == "extsub") && $row->numReviewsSubmitted == 0) {
             continue;
         }
         $trclass = "k" . $this->count % 2;
         if ($show_colors && ($m = $row->viewable_color_classes($this->contact))) {
             if (TagInfo::classes_have_colors($m)) {
                 $trclass = $m;
                 $hascolors = true;
             } else {
                 $trclass .= " {$m}";
             }
         }
         if ($row->disabled && $this->contact->isPC) {
             $trclass .= " graytext";
         }
         $this->count++;
         $ids[] = (int) $row->contactId;
         // First create the expanded callout row
         $tt = "";
         foreach ($fieldDef as $fieldId => $fdef) {
             if ($fdef[1] >= 2 && ($d = $this->content($fieldId, $row)) !== "") {
                 $tt .= "<div";
                 //$t .= "  <tr class=\"pl_$fdef[0] pl_callout $trclass";
                 if ($fdef[1] >= 3) {
                     $tt .= " class=\"fx" . ($fdef[1] - 2) . "\"";
                 }
                 $tt .= '><em class="plx">' . $this->header($fieldId, -1, $row) . ":</em> " . $d . "</div>";
             }
         }
         if ($tt !== "") {
             $x = "  <tr class=\"plx {$trclass}\">";
             if ($firstcallout > 0) {
                 $x .= "<td colspan=\"{$firstcallout}\"></td>";
             }
             $tt = $x . "<td class=\"plx\" colspan=\"" . ($lastcallout - $firstcallout) . "\">" . $tt . "</td></tr>\n";
         }
         // Now the normal row
         $t = "  <tr class=\"pl {$trclass}\">\n";
         $n = 0;
         foreach ($fieldDef as $fieldId => $fdef) {
             if ($fdef[1] == 1) {
                 $c = $this->content($fieldId, $row);
                 $t .= "    <td class=\"pl pl_{$fdef['0']}\"";
                 if ($n >= $lastcallout && $tt != "") {
                     $t .= " rowspan=\"2\"";
                 }
                 $t .= ">" . $c . "</td>\n";
                 if ($c != "") {
                     $anyData[$fieldId] = 1;
                 }
                 ++$n;
             }
         }
         $t .= "  </tr>\n";
         $body .= $t . $tt;
     }
     $foldclasses = array();
     foreach (self::$folds as $k => $fold) {
         if (@$this->have_folds[$fold] !== null) {
             $this->have_folds[$fold] = strpos(displayOptionsSet("uldisplay"), " {$fold} ") !== false;
             $foldclasses[] = "fold" . ($k + 1) . ($this->have_folds[$fold] ? "o" : "c");
         }
     }
     $x = "<table id=\"foldul\" class=\"pltable pltable_full plt_" . htmlspecialchars($listquery);
     if ($foldclasses) {
         $x .= " " . join(" ", $foldclasses);
     }
     if ($foldclasses && $foldsession) {
         $x .= "\" data-fold-session=\"{$foldsession}";
     }
     $x .= "\">\n";
     if ($this->showHeader) {
         $x .= "  <thead class=\"pltable\">\n  <tr class=\"pl_headrow\">\n";
         $ord = 0;
         if ($this->sortable && $url) {
             $sortUrl = htmlspecialchars($url) . (strpos($url, "?") ? "&amp;" : "?") . "sort=";
             $q = '<a class="pl_sort" rel="nofollow" href="' . $sortUrl;
             foreach ($fieldDef as $fieldId => $fdef) {
                 if ($fdef[1] != 1) {
                     continue;
                 } else {
                     if (!isset($anyData[$fieldId])) {
                         $x .= "    <th class=\"pl pl_{$fdef['0']}\"></th>\n";
                         continue;
                     }
                 }
                 $x .= "    <th class=\"pl pl_{$fdef['0']}\">";
                 $ftext = $this->header($fieldId, $ord++);
                 if ($this->sortField == null && $fieldId == 1) {
                     $this->sortField = $fieldId;
                 }
                 if ($fieldId == $this->sortField) {
                     $x .= '<a class="pl_sort_def' . ($this->reverseSort ? "_rev" : "") . '" rel="nofollow" href="' . $sortUrl . $fieldId . ($this->reverseSort ? "N" : "R") . '">' . $ftext . "</a>";
                 } else {
                     if ($fdef[2]) {
                         $x .= $q . $fieldId . "\">" . $ftext . "</a>";
                     } else {
                         $x .= $ftext;
                     }
                 }
                 $x .= "</th>\n";
             }
         } else {
             foreach ($fieldDef as $fieldId => $fdef) {
                 if ($fdef[1] == 1 && isset($anyData[$fieldId])) {
                     $x .= "    <th class=\"pl pl_{$fdef['0']}\">" . $this->header($fieldId, $ord++) . "</th>\n";
                 } else {
                     if ($fdef[1] == 1) {
                         $x .= "    <th class=\"pl pl_{$fdef['0']}\"></th>\n";
                     }
                 }
             }
         }
         $x .= "  </tr></thead>\n";
     }
     reset($fieldDef);
     if (key($fieldDef) == self::FIELD_SELECTOR) {
         $x .= $this->footer($ncol, $hascolors);
     }
     $x .= "<tbody class=\"pltable" . ($hascolors ? " pltable_colored" : "") . "\">" . $body . "</tbody></table>";
     if ($this->listNumber) {
         $l = SessionList::create("u/" . $listname, $ids, $listtitle ? $listtitle : "Users", hoturl_site_relative_raw("users", ["t" => $listname]));
         SessionList::change($this->listNumber, $l);
     }
     return $x;
 }