function showCurrentPersonalRecords()
{
    #----------------------------------------------------------------------
    global $chosenPersonId;
    $bests = dbQuery("\n\n  SELECT * FROM\n\n   (SELECT \n      eventId,\n      best single,\n      worldRank singleRank,\n      continentRank singleRankContinent,\n      countryRank singleRankCountry\n    FROM RanksSingle\n    WHERE personId='{$chosenPersonId}') singles\n    \n    LEFT JOIN\n   \n   (SELECT \n      eventId eC,\n      best average,\n      worldRank averageRank,\n      continentRank averageRankContinent,\n      countryRank averageRankCountry\n    FROM RanksAverage\n    WHERE personId='{$chosenPersonId}') average\n    \n    ON eventId = eC,\n    Events event\n    WHERE\n      eventId = event.id\n    ORDER BY\n      event.rank\n\n\n  ");
    tableBegin('results', 10);
    tableCaption(false, "Current Personal Records");
    tableHeader(explode(" ", "Event NR CR WR Single Average WR CR NR "), array("", "class='r'", "class='r'", "class='R'", "class='R2'", "class='R2'", "class='R'", "class='r'", "class='r'", "class='f'"));
    $oddMessage = "A missing or worse country/continent rank compared to a larger region rank is due to the change of country because results from previous regions don't count for differing current regions.";
    foreach ($bests as $best) {
        extract($best);
        $odd = $singleRankCountry > $singleRankContinent || $singleRankContinent > $singleRank || $averageRankCountry > $averageRankContinent || $averageRankContinent > $averageRank || !$singleRankCountry && $singleRankContinent || !$singleRankContinent && $singleRank || !$averageRankCountry && $averageRankContinent || !$averageRankContinent && $averageRank;
        tableRow(array(internalEventLink("#{$eventId}", eventCellName($eventId)), "<span style='color:#999'>" . colorMe($singleRankCountry) . "</span>", colorMe($singleRankContinent), colorMe($singleRank), eventLink($eventId, formatValue($single, valueFormat($eventId))), eventAverageLink($eventId, formatValue($average, valueFormat($eventId))), colorMe($averageRank), colorMe($averageRankContinent), "<span style='color:#999'>" . colorMe($averageRankCountry) . "</span>", $odd ? "<a title='{$oddMessage}' style='color:#66F' onclick='alert(\"{$oddMessage}\")'>(*)</a>" : ''));
    }
    tableEnd();
}
function checkSimilarResults()
{
    #----------------------------------------------------------------------
    global $competitionCondition, $chosenWhich;
    echo "<hr /><p>Checking <b>" . $chosenWhich . " similar results</b>... (wait for the result message box at the end)</p>\n";
    #--- Get all similar results (except old-new multiblind)
    $rows = pdo_query("\n      SELECT\n          Results.competitionId AS competitionId,\n          Results.personId AS personIdA, Results.personName AS personNameA, Results.eventId AS eventIdA, Results.roundId AS roundIdA,\n          h.personId AS personIdB, h.personName AS personNameB, h.eventId AS eventIdB, h.roundId AS roundIdB,\n          Results.value1 AS value1A, Results.value2 AS value2A, Results.value3 AS value3A, Results.value4 AS value4A, Results.value5 AS value5A,\n          h.value1 AS value1B, h.value2 AS value2B, h.value3 AS value3B, h.value4 AS value4B, h.value5 AS value5B\n      FROM Results\n      JOIN (\n          SELECT competitionId, eventId, roundId, personId, personName, value1, value2, value3, value4, value5\n          FROM Results " . ($competitionCondition ? "JOIN Competitions ON Competitions.id = competitionId " : "") . "WHERE best > 0 " . ($competitionCondition ? $competitionCondition : "") . " AND value3 <> 0\n              AND eventId <> '333mbo'\n      ) h ON Results.competitionId = h.competitionId\n          AND Results.eventId <> '333mbo'\n          AND Results.personId < h.personId\n          AND (\n              (Results.value1 = h.value1 AND h.value1 > 0) +\n              (Results.value2 = h.value2 AND h.value2 > 0) +\n              (Results.value3 = h.value3 AND h.value3 > 0) +\n              (Results.value4 = h.value4 AND h.value4 > 0) +\n              (Results.value5 = h.value5 AND h.value5 > 0) > 2\n              )\n  ");
    tableBegin('results', 4);
    foreach ($rows as $row) {
        $competition = getCompetition($row['competitionId']);
        $competitionName = $competition['cellName'];
        tableCaption(false, competitionLink($row['competitionId'], $competitionName));
        tableHeader(explode('|', "Person|Event|Round|Result Details"), array(3 => 'class="f"'));
        foreach (array('A', 'B') as $letter) {
            $otherLetter = chr(65 + 66 - ord($letter));
            $resultStr = '';
            for ($i = 1; $i <= 5; $i++) {
                $value = $row['value' . $i . $letter];
                if (!$value) {
                    break;
                }
                $resultStr .= "<span class='label label-" . ($value == $row['value' . $i . $otherLetter] ? "danger" : "success") . "'>" . formatValue($value, valueFormat($row['eventId' . $letter])) . "</span> ";
            }
            tableRow(array(personLink($row['personId' . $letter], $row['personName' . $letter]), eventCellName($row['eventId' . $letter]), roundCellName($row['roundId' . $letter]), $resultStr));
        }
    }
    tableEnd();
    #--- Tell the result.
    $date = wcaDate();
    noticeBox2(count($rows) == 0, "No similar results were found.<br />{$date}", "Similar results were found.<br />{$date}");
}
        case 18:
            echo 'RET ';
            break;
        case 19:
            echo "OUT ";
            $ord = $memory[$i++];
            if ($ord >= 32 && $ord <= 126) {
                $chr = true;
                echo "'" . chr($ord) . "'";
            } else {
                $chr = false;
                echo sprintf('0x%04x', $ord);
            }
            break;
        case 20:
            echo 'IN ' . valueFormat($memory[$i++]);
            break;
        case 21:
            echo 'NOOP ';
            break;
        default:
            $bin = sprintf('%016b', $cmd);
            echo sprintf('0x%04x', $cmd) . ' (' . $cmd . ', ' . implode(' ', str_split($bin, 4)) . ')';
    }
    echo "\t; " . sprintf('0x%06x', $address) . "\n";
}
function valueFormat($value, $base = 'h')
{
    if ($value <= 32767) {
        if ($base == 'h') {
            return sprintf('0x%04x', $value);
function checkResult($result, &$countryIdSet, &$competitionIdSet, &$eventIdSet, &$formatIdSet, &$roundIdSet)
{
    # pass-by-reference just for speed
    #----------------------------------------------------------------------
    #--- 1) Check the ids (except persons cause they're a bigger beast checked elsewhere)
    if (!isset($countryIdSet[$result['countryId']])) {
        return "bad countryId " . $result['countryId'];
    }
    if (!isset($competitionIdSet[$result['competitionId']])) {
        return "bad competitionId " . $result['competitionId'];
    }
    if (!isset($eventIdSet[$result['eventId']])) {
        return "bad eventId " . $result['eventId'];
    }
    if (!isset($formatIdSet[$result['formatId']])) {
        return "bad formatId " . $result['formatId'];
    }
    if (!isset($roundIdSet[$result['roundId']])) {
        return "bad roundId " . $result['roundId'];
    }
    #--- 2) Let dns, dnf, zer, suc be the number of values of each kind.
    $dns = $dnf = $zer = $suc = 0;
    foreach (range(1, 5) as $i) {
        $value = $result["value{$i}"];
        $dns += $value == -2;
        $dnf += $value == -1;
        $zer += $value == 0;
        $suc += $value > 0;
    }
    #--- 3) Check that no zero-value is followed by a non-zero value.
    foreach (range(1, 4) as $i) {
        if ($result["value{$i}"] == 0 && $result["value" . ($i + 1)] != 0) {
            return "Zero must not be followed by non-zero.";
        }
    }
    #--- 4) Check zer<5 (there must be at least one non-zero value)
    if ($zer == 5) {
        return "There must be at least one non-zero value";
    }
    #--- 5) Check dns+dnf+zer+suc=5 (nothing besides these is allowed)
    if ($dns + $dnf + $zer + $suc != 5) {
        return "Invalid value";
    }
    #--- 6) Sort the successful values into v_1 .. v_suc
    $v = array();
    foreach (range(1, 5) as $i) {
        $value = $result["value{$i}"];
        if ($value > 0) {
            $v[] = $value;
        }
    }
    sort($v);
    array_unshift($v, 0);
    #--- 7) compute best
    $best = $suc > 0 ? $v[1] : ($dnf > 0 ? -1 : -2);
    #--- 8) compute average
    $average = 0;
    $format = $result['formatId'];
    $event = $result['eventId'];
    $bo3_as_mo3 = $format == '3' && ($event == '333bf' || $event == '333fm' || $event == '333ft');
    $scaler = $event == '333fm' ? 100 : 1;
    if ($format == 'm' || $bo3_as_mo3) {
        $average = $zer > 2 ? 0 : ($suc < 3 ? -1 : round(($v[1] + $v[2] + $v[3]) * $scaler / 3));
    }
    if ($format == 'a') {
        $average = $zer > 0 ? 0 : ($suc < 4 ? -1 : round(($v[2] + $v[3] + $v[4]) / 3));
    }
    if ($average > 60000) {
        $average = $average + 50 - ($average + 50) % 100;
    }
    #--- 9) compare the computed best and average with the stored ones
    if ($result['best'] != $best) {
        return "'best' should be {$best}";
    }
    if ($result['average'] != $average) {
        return "'average' should be {$average}";
    }
    #--- 10) check number of zero-values for non-combined rounds
    $round = $result['roundId'];
    if ($round != 'c' && $round != 'd' && $round != 'e' && $round != 'g' && $round != 'h') {
        if ($format == '1' && $zer != 4) {
            return "should have one non-zero value";
        }
        if ($format == '2' && $zer != 3) {
            return "should have two non-zero values";
        }
        if ($format == '3' && $zer != 2) {
            return "should have three non-zero values";
        }
        if ($format == 'm' && $zer != 2) {
            return "should have three non-zero values";
        }
        if ($format == 'a' && $zer != 0) {
            return "shouldn't have zero-values";
        }
    } else {
        if ($format == '2' && $zer < 3) {
            return "should have at most two non-zero values";
        }
        if ($format == '3' && $zer < 2) {
            return "should have at most three non-zero values";
        }
        if ($format == 'm' && $zer < 2) {
            return "should have at most three non-zero values";
        }
    }
    #--- 12) check times over 10 minutes
    if (valueFormat($result['eventId']) == 'time') {
        foreach (range(1, 5) as $i) {
            $value = $result["value{$i}"];
            if ($value > 60000 && $value % 100) {
                return "{$value} should be rounded";
            }
        }
    }
    #--- 13) check correctness of multi results according to H1b and H1c
    if ($result['eventId'] == '333mbf') {
        foreach (range(1, 5) as $i) {
            $value = $result["value{$i}"];
            if ($value < 1) {
                continue;
            }
            $missed = $value % 100;
            $value = intval($value / 100);
            $time = $value % 100000;
            $value = intval($value / 100000);
            $difference = 99 - $value % 100;
            $solved = $difference + $missed;
            $attempted = $solved + $missed;
            if ($time > 3600) {
                return formatValue($result["value{$i}"], 'multi') . " should be below one hour";
            }
            if ($time > 600 * $attempted) {
                return formatValue($result["value{$i}"], 'multi') . " should be below 10 minutes times the number of cubes";
            }
        }
    }
    #--- No error
    return false;
}
function showPsychSheet($eventId)
{
    #----------------------------------------------------------------------
    global $chosenCompetitionId;
    echo "<h1>Psych Sheet</h1><br />";
    #--- What's first, single or average?
    $order = count(dbQuery("SELECT * FROM Results WHERE eventId='{$eventId}' AND formatId in ('a','m') LIMIT 1")) ? array('Average', 'Single') : array('Single', 'Average');
    #--- Get singles, averages and preregs.
    $score1 = array();
    foreach (dbQuery("SELECT personId, best, worldRank FROM Ranks{$order[0]} WHERE eventId='{$eventId}'") as $row) {
        $score1[$row['personId']] = array($row['best'], $row['worldRank']);
    }
    $score2 = array();
    foreach (dbQuery("SELECT personId, best, worldRank FROM Ranks{$order[1]} WHERE eventId='{$eventId}'") as $row) {
        $score2[$row['personId']] = array($row['best'], $row['worldRank']);
    }
    $preregs = dbQuery("\n    SELECT personId, name, countryId\n    FROM   Preregs\n    WHERE  competitionId = '{$chosenCompetitionId}'\n      AND  status = 'a'\n      AND  eventIds rlike '[[:<:]]{$eventId}[[:>:]]'\n  ");
    #--- Add singles, averages and a comparison key to the preregs.
    foreach ($preregs as &$prereg) {
        extract($prereg);
        $prereg['score1'] = isset($score1[$personId]) ? $score1[$personId] : array(0, 0);
        # PHP suuuucks
        $prereg['score2'] = isset($score2[$personId]) ? $score2[$personId] : array(0, 0);
        $s1 = isset($score1[$personId]) ? $score1[$personId][1] : 999999999;
        $s2 = isset($score2[$personId]) ? $score2[$personId][1] : 999999999;
        $prereg['cmpKey'] = sprintf('%09d%09d', $s1, $s2);
    }
    unset($prereg);
    # Because otherwise PHP is a weirdo and messes up the table-foreach below.
    #--- Sort the preregs.
    usort($preregs, function ($a, $b) {
        return strcmp($a['cmpKey'], $b['cmpKey']);
    });
    #--- Show the preregs table.
    tableBegin('results', 8);
    tableCaption(false, eventName($eventId));
    tableHeader(explode('|', "Rank|Person|Citizen of|Best {$order[0]}|WR|Best {$order[1]}|WR|"), array(0 => 'class="r"', 3 => 'class="R"', 4 => 'class="R"', 5 => 'class="r"', 6 => 'class="r"', 7 => 'class="f"'));
    $ctr = 0;
    $lastCmpKey = '';
    foreach ($preregs as $prereg) {
        extract($prereg);
        $ctr++;
        $rank = $cmpKey > $lastCmpKey ? $ctr : '';
        $lastCmpKey = $cmpKey;
        tableRow(array($rank, $personId ? personLink($personId, $name) : $name, $countryId, formatValue($score1[0], valueFormat($eventId)), $score1[1], formatValue($score2[0], valueFormat($eventId)), $score2[1], ''));
    }
    tableEnd();
}
function addList($list, $legacyId)
{
    #----------------------------------------------------------------------
    $competitions = readDatabaseTableWithId('Competitions');
    list($id, $title, $subtitle, $columnDefs, $rows) = $list;
    $info = isset($list[5]) ? $list[5] : '';
    #--- From column definitions like "[P] Person [N] Appearances [T] | [P] Person [N] Appearances"
    #--- extract classes and names like:
    #--- ('P', 'N', 'T', 'P', 'N', 'f')
    #--- ('Person', 'Appearances, '&nbsp; &nbsp; | &nbsp; &nbsp;', 'Person', 'Appearances', '&nbsp;')
    $columnDefs = "{$columnDefs} [f] &nbsp;";
    $columnDefs = preg_replace('/\\|/', ' &nbsp; &nbsp; | &nbsp; &nbsp; ', $columnDefs);
    preg_match_all('/\\[(\\w+)\\]\\s*([^[]*[^[ ])/', $columnDefs, $matches);
    $columnClasses = $matches[1];
    $columnNames = $matches[2];
    $ctr = 0;
    foreach ($columnClasses as $class) {
        if ($class == 'P') {
        } elseif ($class == 'E') {
        } elseif ($class == 'C') {
        } elseif ($class == 't') {
        } elseif ($class == 'T') {
            $attributes[$ctr] = 'class="L"';
        } elseif ($class == 'N') {
            $attributes[$ctr] = 'class="R2"';
        } elseif ($class == 'n') {
            $attributes[$ctr] = 'class="r"';
        } elseif ($class == 'R') {
            $attributes[$ctr] = 'class="R2"';
        } elseif ($class == 'r') {
            $attributes[$ctr] = 'class="r"';
        } elseif ($class == 'f') {
            $attributes[$ctr] = 'class="f"';
        } else {
            showErrorMessage("Unknown column type <b>'</b>{$class}<b>'</b>");
        }
        $ctr++;
    }
    if ($subtitle) {
        $subtitle = "<span style='color:#999'>({$subtitle})</span>";
    }
    if ($info) {
        $info = htmlEntities($info, ENT_QUOTES);
        $info = "(<a title='{$info}' style='color:#FC0' onclick='alert(\"{$info}\")'>info</a>)";
    }
    $columnCount = count($columnNames);
    echo "<div id='{$id}'>\n";
    TableBegin('results', $columnCount);
    TableCaptionNew(false, $legacyId, "{$title} {$subtitle} {$info}");
    TableHeader($columnNames, $attributes);
    #--- Display the table.
    $rowCtr = 0;
    foreach ($rows as $row) {
        $values = array();
        $numbers = '';
        #    array_unshift( $row, 0 );
        #    foreach( $row as $key => $value ){
        foreach (range(0, $columnCount - 2) as $i) {
            $value = $row[$i];
            $Class = ucfirst($columnClasses[$i]);
            if ($Class == 'P' && $value) {
                $value = personLink($value, extractRomanName(currentPersonName($value)));
            }
            if ($Class == 'E') {
                $value = eventLink($value, eventCellName($value));
            }
            if ($Class == 'C') {
                $value = competitionLink($value, $competitions[$value]['cellName']);
            }
            if ($Class == 'R') {
                $value = formatValue($value, isset($row['eventId']) ? valueFormat($row['eventId']) : 'time');
            }
            $values[] = $value;
            if ($Class == 'N') {
                $numbers .= "{$value}|";
            }
        }
        #--- Add the rank.
        $rowCtr++;
        $rank = isset($prevNumbers) && $numbers == $prevNumbers ? '' : $rowCtr;
        ###  $rank = $rowCtr;
        $prevNumbers = $numbers;
        #    $values[0] = $rank;
        #--- Add the filler column cell.
        $values[] = '';
        #--- Show the row.
        TableRow($values);
    }
    TableEnd();
    echo "</div>\n";
}