function __construct($contact, $type, $papersel, $newrev_since)
 {
     global $Conf, $Now;
     $this->contact = $contact;
     assert(!!$contact->isPC);
     $any_newpcrev = $any_lead = $any_shepherd = 0;
     if ($contact->is_manager()) {
         $this->defsel("s", "Contact authors of submitted papers");
         $this->defsel("unsub", "Contact authors of unsubmitted papers");
         $this->defsel("au", "All contact authors");
         // map "somedec:no"/"somedec:yes" to real decisions
         $result = Dbl::qe("select outcome, count(*) from Paper where timeSubmitted>0 group by outcome");
         $dec_pcount = edb_map($result);
         $dec_tcount = array(0 => 0, 1 => 0, -1 => 0);
         foreach ($dec_pcount as $dnum => $dcount) {
             $dec_tcount[$dnum > 0 ? 1 : ($dnum < 0 ? -1 : 0)] += $dcount;
         }
         if ($type == "somedec:no" || $type == "somedec:yes") {
             $dmaxcount = -1;
             foreach ($dec_pcount as $dnum => $dcount) {
                 if (($type[8] == "n" ? $dnum < 0 : $dnum > 0) && $dcount > $dmaxcount && ($dname = $Conf->decision_name($dnum))) {
                     $type = "dec:{$dname}";
                     $dmaxcount = $dcount;
                 }
             }
         }
         $by_dec = array();
         foreach ($Conf->decision_map() as $dnum => $dname) {
             $k = "dec:{$dname}";
             if ($dnum && (@$dec_pcount[$dnum] > 0 || $type == $k)) {
                 $by_dec[$k] = "Contact authors of " . htmlspecialchars($dname) . " papers";
             }
         }
         if ($dec_tcount[1] > 0 || $type == "dec:yes") {
             $by_dec["dec:yes"] = "Contact authors of accept-class papers";
         }
         if ($dec_tcount[-1] > 0 || $type == "dec:no") {
             $by_dec["dec:no"] = "Contact authors of reject-class papers";
         }
         if ($dec_tcount[0] > 0 || $type == "dec:none") {
             $by_dec["dec:none"] = "Contact authors of undecided papers";
         }
         if ($type == "dec:any") {
             $by_dec["dec:any"] = "Contact authors of decided papers";
         }
         if (count($by_dec)) {
             $this->sel["bydec_group"] = array("optgroup", "Contact authors by decision");
             foreach ($by_dec as $k => $v) {
                 $this->defsel($k, $v);
             }
             $this->sel["bydec_group_end"] = array("optgroup");
         }
         $this->sel["rev_group"] = array("optgroup", "Reviewers");
         $this->defsel("rev", "Reviewers");
         $this->defsel("crev", "Reviewers with complete reviews");
         $this->defsel("uncrev", "Reviewers with incomplete reviews");
         $this->defsel("allcrev", "Reviewers with no incomplete reviews");
         $this->defsel("pcrev", "PC reviewers");
         $this->defsel("uncpcrev", "PC reviewers with incomplete reviews");
         // new assignments query
         // XXX this exposes information about PC review assignments
         // for conflicted papers to the chair; not worth worrying about
         $aq = "select PaperReview.paperId any_newpcrev from PaperReview";
         if (!$contact->privChair) {
             $aq .= " join Paper on (Paper.paperId=PaperReview.paperId and Paper.managerContactId=" . $contact->contactId . ")";
         }
         $aq .= "\n\twhere reviewType>=" . REVIEW_PC . " and reviewSubmitted is null and reviewNeedsSubmit!=0 and timeRequested>timeRequestNotified limit 1";
         $bcq_manager = "";
         if (!$contact->privChair) {
             $bcq_manager = " and managerContactId=" . $contact->contactId;
         }
         $q = "select any_newpcrev, any_lead, any_shepherd\n\tfrom ({$aq}) a\n\tleft join (select paperId any_lead from Paper where timeSubmitted>0 and leadContactId!=0{$bcq_manager} limit 1) b on (true)\n\tleft join (select paperId any_shepherd from Paper where timeSubmitted>0 and shepherdContactId!=0{$bcq_manager} limit 1) c on (true)";
         if ($row = Dbl::fetch_first_row($q)) {
             list($any_newpcrev, $any_lead, $any_shepherd) = $row;
         }
         $this->defsel("newpcrev", "PC reviewers with new review assignments");
         $this->defsel("extrev", "External reviewers");
         $this->defsel("uncextrev", "External reviewers with incomplete reviews");
         $this->sel["rev_group_end"] = array("optgroup");
     }
     $this->defsel_nm("myextrev", "Your requested reviewers");
     $this->defsel_nm("uncmyextrev", "Your requested reviewers with incomplete reviews");
     $this->sel["pc_group"] = array("optgroup", "Program committee");
     if ($contact->is_manager()) {
         if ($any_lead || $type == "lead") {
             $this->defsel("lead", "Discussion leads");
         }
         if ($any_shepherd || $type == "shepherd") {
             $this->defsel("shepherd", "Shepherds");
         }
     }
     $this->defsel_nm("pc", "Program committee");
     foreach (pcTags() as $t) {
         if ($t != "pc") {
             $this->defsel_nm("pc:{$t}", "PC members tagged “{$t}”");
         }
     }
     $this->sel["pc_group_end"] = array("optgroup");
     if ($contact->privChair) {
         $this->defsel("all", "All users");
     }
     if (isset($this->sel[$type])) {
         $this->type = $type;
     } else {
         if ($type == "myuncextrev" && isset($this->sel["uncmyextrev"])) {
             $this->type = "uncmyextrev";
         } else {
             $this->type = key($this->sel);
         }
     }
     $this->papersel = $papersel;
     if ($this->type == "newpcrev") {
         $t = @trim($newrev_since);
         if (preg_match(',\\A(?:|n/a|[(]?all[)]?|0)\\z,i', $t)) {
             $this->newrev_since = 0;
         } else {
             if (($this->newrev_since = $Conf->parse_time($t)) !== false) {
                 if ($this->newrev_since > $Now) {
                     $Conf->warnMsg("That time is in the future.");
                 }
             } else {
                 Conf::msg_error("Invalid date.");
                 $this->error = true;
             }
         }
     }
 }
 function render($sv)
 {
     global $Conf;
     $sv->echo_checkbox("rev_open", "<b>Open site for reviewing</b>");
     $sv->echo_checkbox("cmt_always", "Allow comments even if reviewing is closed");
     echo "<div class='g'></div>\n";
     $sv->echo_checkbox('pcrev_any', "PC members can review <strong>any</strong> submitted paper");
     echo "<div class='g'></div>\n";
     echo "<strong>Review anonymity:</strong> Are reviewer names hidden from authors?<br />\n";
     $sv->echo_radio_table("rev_blind", array(Conf::BLIND_ALWAYS => "Yes—reviews are anonymous", Conf::BLIND_NEVER => "No—reviewer names are visible to authors", Conf::BLIND_OPTIONAL => "Depends—reviewers decide whether to expose their names"));
     echo "<div class='g'></div>\n";
     $sv->echo_checkbox('rev_notifychair', 'Notify PC chairs of newly submitted reviews by email');
     // Deadlines
     echo "<h3 id=\"rounds\" class=\"settings g\">Deadlines &amp; rounds</h3>\n";
     echo '<p class="hint">Reviews are due by the deadline, but <em>cannot be modified</em> after the hard deadline. Most conferences don’t use hard deadlines for reviews.<br />', $sv->type_hint("date") ?: "", '</p>';
     $rounds = $Conf->round_list();
     if ($sv->use_req()) {
         for ($i = 1; isset($sv->req["roundname_{$i}"]); ++$i) {
             $rounds[$i] = get($sv->req, "deleteround_{$i}") ? ";" : trim(get_s($sv->req, "roundname_{$i}"));
         }
     }
     // prepare round selector
     $round_value = trim($sv->curv("rev_roundtag"));
     $current_round_value = $Conf->setting_data("rev_roundtag", "");
     if (preg_match('/\\A(?:|\\(none\\)|\\(no name\\)|default|unnamed|#0)\\z/i', $round_value)) {
         $round_value = "#0";
     } else {
         if (($round_number = $Conf->round_number($round_value, false)) || ($round_number = $Conf->round_number($current_round_value, false))) {
             $round_value = "#" . $round_number;
         } else {
             $round_value = $selector[$current_round_value] = $current_round_value;
         }
     }
     $round_map = edb_map(Dbl::ql("select reviewRound, count(*) from PaperReview group by reviewRound"));
     $print_round0 = true;
     if ($round_value !== "#0" && $round_value !== "" && $current_round_value !== "" && (!$sv->use_req() || isset($sv->req["roundname_0"])) && !$Conf->round0_defined()) {
         $print_round0 = false;
     }
     $selector = array();
     if ($print_round0) {
         $selector["#0"] = "unnamed";
     }
     for ($i = 1; $i < count($rounds); ++$i) {
         if ($rounds[$i] !== ";") {
             $selector["#{$i}"] = (object) array("label" => $rounds[$i], "id" => "rev_roundtag_{$i}");
         }
     }
     echo '<div id="round_container"', count($selector) == 1 ? ' style="display:none"' : '', '>', '<table id="rev_roundtag_table"><tr><td class="lxcaption">', $sv->label("rev_roundtag", "Current round"), '</td><td>', Ht::select("rev_roundtag", $selector, $round_value, $sv->sjs("rev_roundtag")), '</td></tr></table>', '<div class="hint">This round is used for new assignments.</div><div class="g"></div></div>';
     echo '<div id="roundtable">';
     $num_printed = 0;
     for ($i = 0; $i < count($rounds); ++$i) {
         if ($i ? $rounds[$i] !== ";" : $print_round0) {
             $this->echo_round($sv, $i, $i ? $rounds[$i] : "", +get($round_map, $i), count($selector) !== 1);
             ++$num_printed;
         }
     }
     echo '</div><div id="newround" style="display:none">';
     $this->echo_round($sv, '$', "", "", true);
     echo '</div><div class="g"></div>';
     echo Ht::js_button("Add round", "review_round_settings.add();hiliter(this)"), ' &nbsp; <span class="hint"><a href="', hoturl("help", "t=revround"), '">What is this?</a></span>', Ht::hidden("oldroundcount", count($Conf->round_list())), Ht::hidden("has_rev_roundtag", 1);
     for ($i = 1; $i < count($rounds); ++$i) {
         if ($rounds[$i] === ";") {
             echo Ht::hidden("roundname_{$i}", "", array("id" => "roundname_{$i}")), Ht::hidden("deleteround_{$i}", 1);
         }
     }
     Ht::stash_script("review_round_settings.init()");
     // External reviews
     echo "<h3 class=\"settings g\">External reviews</h3>\n";
     echo "<div class='g'></div>";
     $sv->echo_checkbox("extrev_chairreq", "PC chair must approve proposed external reviewers");
     $sv->echo_checkbox("pcrev_editdelegate", "PC members can edit external reviews they requested");
     echo "<div class='g'></div>\n";
     $t = expandMailTemplate("requestreview", false);
     echo "<table id='foldmailbody_requestreview' class='", $t == expandMailTemplate("requestreview", true) ? "foldc" : "foldo", "'><tr><td>", foldbutton("mailbody_requestreview"), "</td>", "<td><a href='#' onclick='return fold(\"mailbody_requestreview\")' class='q'><strong>Mail template for external review requests</strong></a>", " <span class='fx'>(<a href='", hoturl("mail"), "'>keywords</a> allowed; set to empty for default)<br /></span>\n<textarea class='tt fx' name='mailbody_requestreview' cols='80' rows='20'>", htmlspecialchars($t["body"]), "</textarea>", "</td></tr></table>\n";
     // Review visibility
     echo "<h3 class=\"settings g\">Visibility</h3>\n";
     echo "Can PC members <strong>see all reviews</strong> except for conflicts?<br />\n";
     $sv->echo_radio_table("pc_seeallrev", array(Conf::PCSEEREV_YES => "Yes", Conf::PCSEEREV_UNLESSINCOMPLETE => "Yes, unless they haven’t completed an assigned review for the same paper", Conf::PCSEEREV_UNLESSANYINCOMPLETE => "Yes, after completing all their assigned reviews", Conf::PCSEEREV_IFCOMPLETE => "Only after completing a review for the same paper"));
     echo "<div class='g'></div>\n";
     echo "Can PC members see <strong>reviewer names</strong> except for conflicts?<br />\n";
     $sv->echo_radio_table("pc_seeblindrev", array(0 => "Yes", 1 => "Only after completing a review for the same paper<br /><span class='hint'>This setting also hides reviewer-only comments from PC members who have not completed a review for the same paper.</span>"));
     echo "<div class='g'></div>";
     echo "Can external reviewers see the other reviews for their assigned papers, once they’ve submitted their own?<br />\n";
     $sv->echo_radio_table("extrev_view", array(2 => "Yes", 1 => "Yes, but they can’t see who wrote blind reviews", 0 => "No"));
     // Review ratings
     echo "<h3 class=\"settings g\">Review ratings</h3>\n";
     echo "Should HotCRP collect ratings of reviews? &nbsp; <a class='hint' href='", hoturl("help", "t=revrate"), "'>(Learn more)</a><br />\n";
     $sv->echo_radio_table("rev_ratings", array(REV_RATINGS_PC => "Yes, PC members can rate reviews", REV_RATINGS_PC_EXTERNAL => "Yes, PC members and external reviewers can rate reviews", REV_RATINGS_NONE => "No"));
 }