예제 #1
0
function showMedia()
{
    #----------------------------------------------------------------------
    global $chosenYears, $chosenRegionId, $chosenOrder;
    #--- Prepare conditions.
    $yearCondition = yearCondition();
    $regionCondition = regionCondition('competition');
    $orderCondition = $chosenOrder == 'date' ? "ORDER BY competition.year DESC,\n                                                         competition.month DESC,\n                                                         competition.day DESC" : "ORDER BY timestampDecided DESC";
    #--- Get data of the (matching) media items.
    $media = dbQuery("\n    SELECT media.*, competition.*, cellName, country.name AS countryName\n\n    FROM CompetitionsMedia media, Competitions competition, Countries country\n    WHERE 1\n      AND competition.id = competitionId\n      AND country.id = countryId\n      {$yearCondition}\n      {$regionCondition}\n      AND status = 'accepted'\n    {$orderCondition}, cellName\n  ");
    #--- Print the data.
    tableBegin('results', 6);
    #  tableCaption( false, spaced(array( eventName($chosenEventId), chosenRegionName(), $chosenYears )));
    tableHeader(explode('|', 'Insertion Date|Competition Date|Competition|Country, City|Type|Link'), array(5 => 'class="f"'));
    foreach ($media as $data) {
        extract($data);
        #--- Print the empty row.
        if ($chosenOrder == 'submission') {
            $year = preg_replace('/-.*/', '', $timestampDecided);
        }
        if (isset($previousYear) && $year != $previousYear) {
            tableRowEmpty();
        }
        $previousYear = $year;
        tableRow(array(preg_replace('/ .*/', '', $timestampDecided), competitionDate($data), competitionLink($competitionId, $cellName), "<b>{$countryName}</b>, {$cityName}", $type, externalLink($uri, $text)));
    }
    tableEnd();
}
function listCompetitions()
{
    #----------------------------------------------------------------------
    global $chosenEventId, $chosenYears, $chosenRegionId, $chosenPatternHtml;
    global $chosenList, $chosenMap;
    global $chosenCompetitions;
    $chosenCompetitions = getCompetitions($chosenList);
    tableBegin('results', 5);
    tableCaption(false, spaced(array(eventName($chosenEventId), chosenRegionName(), $chosenYears, $chosenPatternHtml ? "\"{$chosenPatternHtml}\"" : '')));
    if ($chosenList) {
        tableHeader(explode('|', 'Year|Date|Name|Country, City|Venue'), array(4 => 'class="f"'));
        foreach ($chosenCompetitions as $competition) {
            extract($competition);
            if (isset($previousYear) && $year != $previousYear) {
                tableRowEmpty();
            }
            $previousYear = $year;
            $isPast = wcaDate('Ymd') > 10000 * $year + 100 * $month + $day;
            tableRow(array($year, competitionDate($competition), $isPast ? competitionLink($id, $cellName) : ($showPreregForm || $showPreregList ? competitionLinkClassed('rg', $id, $cellName) : competitionLinkClassed('fc', $id, $cellName)), "<b>{$countryName}</b>, {$cityName}", processLinks($venue)));
        }
    }
    tableEnd();
    if ($chosenMap) {
        // create map markers
        $markers = array();
        foreach ($chosenCompetitions as $comp) {
            $markers[$comp['id']] = array();
            $markers[$comp['id']]['latitude'] = $comp['latitude'];
            $markers[$comp['id']]['longitude'] = $comp['longitude'];
            $markers[$comp['id']]['info'] = "<a href='c.php?i=" . $comp['id'] . "'>" . o($comp['cellName']) . "</a><br />" . date("M j, Y", mktime(0, 0, 0, $comp['month'], $comp['day'], $comp['year'])) . " - " . o($comp['cityName']);
        }
        displayMap($markers);
    }
}
function showHistoryOfContinentalRecords()
{
    #----------------------------------------------------------------------
    global $chosenPersonId;
    $results = dbQuery("\n    SELECT\n      result.*,\n      event.format         valueFormat,\n      event.cellName       eventCellName,\n      competition.cellName competitionCellName,\n      round.cellName       roundCellName\n    FROM\n      Results      result,\n      Competitions competition,\n      Events       event,\n      Rounds       round\n    WHERE " . randomDebug() . "\n      AND result.personId = '{$chosenPersonId}'\n      AND ((result.regionalSingleRecord != '' AND result.regionalSingleRecord != 'NR' AND result.regionalSingleRecord != 'WR') OR (result.regionalAverageRecord != '' AND result.regionalAverageRecord != 'NR' AND result.regionalAverageRecord != 'WR'))\n      AND event.id = result.eventId\n      AND event.rank < 1000\n      AND competition.id = result.competitionId\n      AND round.id = result.roundId\n    ORDER BY\n      event.rank, year DESC, month DESC, day DESC, roundId DESC\n  ");
    if (!count($results)) {
        return;
    }
    tableBegin('results', 6);
    tableCaption(false, 'History of Continental Records');
    tableHeader(explode('|', 'Event|Single|Average|Competition|Round|Result Details'), array(1 => "class='R2'", 2 => "class='R2'", 5 => "class='f'"));
    foreach ($results as $result) {
        extract($result);
        if (isset($currentEventId) && $eventId != $currentEventId) {
            tableRowEmpty();
        }
        tableRow(array(isset($currentEventId) && $eventId == $currentEventId ? '' : eventLink($eventId, $eventCellName), ($regionalSingleRecord == '' or $regionalSingleRecord == 'NR' or $regionalSingleRecord == 'WR') ? '' : formatValue($best, $valueFormat), ($regionalAverageRecord == '' or $regionalAverageRecord == 'NR' or $regionalAverageRecord == 'WR') ? '' : formatValue($average, $valueFormat), competitionLink($competitionId, $competitionCellName), $roundCellName, formatAverageSources($regionalAverageRecord != '' and $regionalAverageRecord != 'NR' and $regionalAverageRecord != 'WR', $result, $valueFormat)));
        $currentEventId = $eventId;
    }
    tableEnd();
}
function showWorldChampionshipPodiums()
{
    #----------------------------------------------------------------------
    global $chosenPersonId;
    $results = dbQuery("\n    SELECT\n      result.*,\n      event.format         valueFormat,\n      event.cellName       eventCellName,\n      competition.cellName competitionCellName,\n      year\n    FROM\n      Results      result,\n      Competitions competition,\n      Events       event\n    WHERE " . randomDebug() . "\n      AND best > 0\n      AND pos <= 3\n      AND roundId in ('f', 'c')\n      AND competition.cellName like 'World Championship %'\n      AND result.personId = '{$chosenPersonId}'\n      AND event.id = result.eventId\n      AND competition.id = result.competitionId\n      AND event.rank < 1000\n    ORDER BY\n      year DESC, event.rank\n  ");
    if (!count($results)) {
        return;
    }
    tableBegin('results', 6);
    tableCaption(false, 'World Championship Podiums');
    tableHeader(explode('|', 'Year|Event|Place|Single|Average|Result Details'), array(0 => "class='R2'", 2 => "class='R2'", 3 => "class='r'", 4 => "class='r'", 5 => "class='f'"));
    $lastYear = 0;
    foreach ($results as $result) {
        extract($result);
        if ($year < $lastYear) {
            tableRowEmpty();
        }
        tableRow(array($year != $lastYear ? $year : '', eventLink($eventId, $eventCellName), competitionLink($competitionId, $pos, $eventId, $roundId), formatValue($best, $valueFormat), formatValue($average, $valueFormat), formatAverageSources(true, $result, $valueFormat)));
        $lastYear = $year;
    }
    tableEnd();
}
function showMedia()
{
    #----------------------------------------------------------------------
    global $chosenType, $chosenStatus, $chosenRegionId, $chosenOrder;
    #--- Prepare conditions.
    $typeCondition = $chosenType ? "AND type='{$chosenType}'" : '';
    $accepted = $chosenStatus == 'accepted';
    $order = $accepted ? "ORDER BY timestampDecided    DESC" : "ORDER BY timestampSubmitted  DESC";
    $orderCondition = $chosenOrder == 'date' ? "ORDER BY competition.year DESC,\n                                                         competition.month DESC,\n                                                         competition.day DESC" : $order;
    $headerDate = $accepted ? "Insertion" : "Submission";
    #--- Get data of the (matching) media items.
    $media = dbQuery("\n    SELECT media.*,\n           competition.year, competition.month, competition.day,\n           competition.endMonth, competition.endDay,\n           competition.countryId, competition.cityName,\n           cellName,\n           country.name AS countryName\n    FROM CompetitionsMedia media, Competitions competition, Countries country\n    WHERE 1\n      AND competition.id = competitionId\n      AND country.id = countryId\n      {$typeCondition}\n      " . regionCondition('competition') . "\n      AND status='{$chosenStatus}'\n    {$orderCondition}, cellName\n  ");
    #--- Begin form and table.
    echo "<form action='validate_media_ACTION.php' method='POST'>\n";
    tableBegin('results', 7);
    tableHeader(explode('|', $headerDate . ' Date|Competition Date|Competition|Country, City|Type|Link|'), array(5 => 'class="f"'));
    #--- Print results.
    foreach ($media as $data) {
        extract($data);
        $timestamp = $accepted ? $timestampDecided : $timestampSubmitted;
        if ($chosenOrder == 'submission') {
            $year = preg_replace('/-.*/', '', $timestamp);
        }
        if (isset($previousYear) && $year != $previousYear) {
            tableRowEmpty();
        }
        $previousYear = $year;
        $button = "<input type='submit' class='butt' value='Info' name='info{$id}' /> ";
        $button .= "<input type='submit' class='butt' value='Edit' name='edit{$id}' /> ";
        $button .= $accepted ? "<input type='submit' class='butt' value='Erase' name='refuse{$id}' />" : "<input type='submit' class='butt' value='Accept' name='accept{$id}' />\n                            <input type='submit' class='butt' value='Refuse' name='refuse{$id}' />";
        tableRow(array(preg_replace('/ .*/', '', $timestamp), competitionDate($data), competitionLink($competitionId, $cellName), "<b>{$countryName}</b>, {$cityName}", $type, externalLink(htmlEscape($uri), htmlEscape($text)), $button));
    }
    #--- End form and table.
    tableEnd();
    echo "</form>";
}
function computeRegionalRecordMarkers($valueId, $valueName)
{
    #----------------------------------------------------------------------
    global $chosenAnything, $chosenCompetitionId, $differencesWereFound, $previousRecord, $pendingCompetitions, $startDate;
    # -----------------------------
    # Description of the main idea:
    # -----------------------------
    # Get all results that are potential regional records. Process them one
    # event at a time. Inside, process them one competition at a time, in
    # chronological order of start date. Each competition's results are only
    # compared against records of strictly previous competitions, not against
    # parallel competitions. For this, there are these main arrays:
    #
    # - $previousRecord[regionId] is a running collection of each region's record,
    #   covering all competitions *before* the current one.
    #
    # - $record[regionId] is based on $previousRecord and is used and updated
    #   inside the current competition.
    #
    # - $pendingCompetitions[regionId] holds $record of competitions already
    #   processed but not merged into $previousRecord. When a new competition is
    #   encountered, we merge those that ended before the new one into $previousRecord.
    #
    # - $baseRecord[eventId][regionId] is for when a user chose a specific
    #   competition to check. Then we quickly ask the database for the current
    #   region records from before that competition. This could be used for
    #   giving the user a year-option as well, but we don't have that (yet?).
    # -----------------------------
    #--- If a competition was chosen, we need all records from before it
    if ($chosenCompetitionId) {
        $startDate = getCompetitionValue($chosenCompetitionId, "year*10000 + month*100 + day");
        $results = dbQueryHandle("\n      SELECT eventId, result.countryId, continentId, min({$valueId}) value, event.format valueFormat\n      FROM Results result, Competitions competition, Countries country, Events event\n      WHERE {$valueId} > 0\n        AND competition.id = result.competitionId\n        AND country.id     = result.countryId\n        AND event.id       = result.eventId\n        AND year*10000 + if(endMonth,endMonth,month)*100 + if(endDay,endDay,day) < {$startDate}\n      GROUP BY eventId, countryId");
        while ($row = mysql_fetch_row($results)) {
            list($eventId, $countryId, $continentId, $value, $valueFormat) = $row;
            if (isSuccessValue($value, $valueFormat)) {
                foreach (array($countryId, $continentId, 'World') as $regionId) {
                    if (!isset($baseRecord[$eventId][$regionId]) || $value < $baseRecord[$eventId][$regionId]) {
                        $baseRecord[$eventId][$regionId] = $value;
                    }
                }
            }
        }
        mysql_free_result($results);
    } else {
        $competitions = dbQuery("\n      SELECT id, year*10000 + if(endMonth,endMonth,month)*100 + if(endDay,endDay,day) endDate\n      FROM   Competitions competition");
        foreach ($competitions as $competition) {
            $endDate[$competition['id']] = $competition['endDate'];
        }
    }
    #--- The IDs of relevant results (those already marked as region record and those that could be)
    $queryRelevantIds = "\n   (SELECT id FROM Results WHERE regional{$valueName}Record<>'' " . eventCondition() . competitionCondition() . ")\n   UNION\n   (SELECT id\n    FROM\n      Results result,\n      (SELECT eventId, competitionId, roundId, countryId, min({$valueId}) value\n       FROM Results\n       WHERE {$valueId} > 0\n       " . eventCondition() . competitionCondition() . "\n       GROUP BY eventId, competitionId, roundId, countryId) helper\n    WHERE result.eventId       = helper.eventId\n      AND result.competitionId = helper.competitionId\n      AND result.roundId       = helper.roundId\n      AND result.countryId     = helper.countryId\n      AND result.{$valueId}      = helper.value)";
    #--- Get the results, ordered appropriately
    $results = dbQueryHandle("\n    SELECT\n      year*10000 + month*100 + day startDate,\n      result.id resultId,\n      result.eventId,\n      result.competitionId,\n      result.roundId,\n      result.personId,\n      result.personName,\n      result.countryId,\n      result.regional{$valueName}Record storedMarker,\n      {$valueId} value,\n      continentId,\n      continent.recordName continentalRecordName,\n      event.format valueFormat\n    FROM\n      ({$queryRelevantIds}) relevantIds,\n      Results      result,\n      Competitions competition,\n      Countries    country,\n      Continents   continent,\n      Events       event,\n      Rounds       round\n    WHERE 1\n      AND result.id      = relevantIds.id\n      AND competition.id = result.competitionId\n      AND round.id       = result.roundId\n      AND country.id     = result.countryId\n      AND continent.id   = country.continentId\n      AND event.id       = result.eventId\n    ORDER BY event.rank, startDate, competitionId, round.rank, {$valueId}\n  ");
    #--- For displaying the dates, fetch all competitions
    $allCompetitions = array();
    foreach (dbQuery("SELECT * FROM Competitions") as $row) {
        $allCompetitions[$row['id']] = $row;
    }
    #--- Process each result.
    $currentEventId = $announcedEventId = $announcedRoundId = $announcedCompoId = NULL;
    while ($row = mysql_fetch_row($results)) {
        list($startDate, $resultId, $eventId, $competitionId, $roundId, $personId, $personName, $countryId, $storedMarker, $value, $continentId, $continentalRecordName, $valueFormat) = $row;
        #--- Handle failures of multi-attempts.
        if (!isSuccessValue($value, $valueFormat)) {
            continue;
        }
        #--- At new events, reset everything
        if ($eventId != $currentEventId) {
            $currentEventId = $eventId;
            $currentCompetitionId = false;
            $record = $previousRecord = isset($baseRecord[$eventId]) ? $baseRecord[$eventId] : array();
            $pendingCompetitions = array();
        }
        #--- Handle new competitions.
        if ($competitionId != $currentCompetitionId) {
            #--- Add the records of the previously current competition to the set of pending competition records
            if ($currentCompetitionId) {
                $pendingCompetitions[] = array($endDate[$currentCompetitionId], $record);
            }
            #--- Note the current competition
            $currentCompetitionId = $competitionId;
            #--- Prepare the records this competition will be based on
            $pendingCompetitions = array_filter($pendingCompetitions, "handlePendingCompetition");
            $record = $previousRecord;
        }
        #--- Calculate whether it's a new region record and update the records.
        $calcedMarker = '';
        if (!isset($record[$countryId]) || $value <= $record[$countryId]) {
            $calcedMarker = 'NR';
            $record[$countryId] = $value;
            if (!isset($record[$continentId]) || $value <= $record[$continentId]) {
                $calcedMarker = $continentalRecordName;
                $record[$continentId] = $value;
                if (!isset($record['World']) || $value <= $record['World']) {
                    $calcedMarker = 'WR';
                    $record['World'] = $value;
                }
            }
        }
        #--- If stored or calculated marker say it's some regional record at all...
        if ($storedMarker || $calcedMarker) {
            #--- Do stored and calculated agree? Choose colors and update list of differences.
            $same = $storedMarker == $calcedMarker;
            $storedColor = $same ? '999' : 'F00';
            $calcedColor = $same ? '999' : '0E0';
            if (!$same) {
                $selectedIds[] = $resultId;
                $differencesWereFound = true;
            }
            #--- If no filter was chosen, only show differences.
            if (!$chosenAnything && $same) {
                continue;
            }
            #--- Highlight regions if the calculated marker thinks it's a record for them.
            $countryName = $countryId;
            $continentName = substr($continentId, 1);
            $worldName = 'World';
            if ($calcedMarker) {
                $countryName = "<b>{$countryName}</b>";
            }
            if ($calcedMarker && $calcedMarker != 'NR') {
                $continentName = "<b>{$continentName}</b>";
            }
            if ($calcedMarker == 'WR') {
                $worldName = "<b>{$worldName}</b>";
            }
            #--- Recognize new events/rounds/competitions.
            $announceEvent = $eventId != $announcedEventId;
            $announcedEventId = $eventId;
            $announceRound = $roundId != $announcedRoundId;
            $announcedRoundId = $roundId;
            $announceCompo = $competitionId != $announcedCompoId;
            $announcedCompoId = $competitionId;
            #--- If new event, announce it.
            if ($announceEvent) {
                tableCaption(false, "{$eventId} {$valueName}");
                tableHeader(explode('|', 'Date|Competition|Round|Person|Event|Country|Continent|World|Value|Stored|Computed|Agree'), array(7 => "class='R2'"));
            }
            #--- If new round/competition inside an event, add a separator row.
            if (($announceRound || $announceCompo) && !$announceEvent) {
                tableRowEmpty();
            }
            #--- Prepare the checkbox.
            $checkbox = "<input type='checkbox' name='update{$valueName}{$resultId}' value='{$calcedMarker}' />";
            #--- Show the result.
            tableRow(array(competitionDate($allCompetitions[$competitionId]), competitionLink($competitionId, $competitionId), $roundId, personLink($personId, $personName), $eventId, $countryName, $continentName, $worldName, formatValue($value, $valueFormat), "<span style='font-weight:bold;color:#{$storedColor}'>{$storedMarker}</span>", "<span style='font-weight:bold;color:#{$calcedColor}'>{$calcedMarker}</span>", $same ? '' : $checkbox));
        }
    }
    mysql_free_result($results);
}
function showUnfinishedPersons () {
#----------------------------------------------------------------------
  global $personsFromPersons, $personsFromResultsWithoutId, $birthdates;

  #--- Pre-compute the candidate tuples: (id, name, countryId, romanName, romanNameSimilarityPlaceHolder, countryIdSimilarityPlaceHolder)
  $candidates = array();
  foreach( $personsFromPersons as $person ){
    list( $id, $name, $countryId ) = $person;
    $candidates[] = array( $id, $name, $countryId, extractRomanName($name), 0, 0 );
  }

  #--- Begin the form and table.
  echo "<form action='persons_finish_unfinished_ACTION.php' method='post'>";
  tableBegin( 'results', 8 );
  tableHeader( explode( '|', '|personName|countryId|personId|birthdate|personName|countryId|personSemiId' ),
               array( 6=>'class="6"' ) );

  #--- Walk over all persons from the Results table.
  $caseNr = 0;
  foreach( $personsFromResultsWithoutId as $person ){
    list( $name, $countryId, $firstYear ) = $person;
    
    #--- Try to compute the semi-id.
    $quarterId = removeUglyAccentsAndStuff( extractRomanName( $name ));
    $quarterId = preg_replace( '/[^a-zA-Z ]/', '', $quarterId );
    $quarterId = strtoupper( substr( preg_replace( '/(.*)\s(.*)/', '$2$1', $quarterId ), 0, 4 ));
    if ( strlen ( $quarterId ) == 0 ) {
      // if the name comes empty, invent a quarterId
      $quarterId = 'XXXX';
    } else if ( strlen( $quarterId ) < 4 ) {
      // make sure the quarterId is 4-letter long
      while ( strlen( $quarterId ) < 4 ) {
        $quarterId .= $quarterId;
      }
      $quarterId = substr( $quarterId, 0, 4 );
    }
    $semiId = $firstYear . $quarterId;

    #--- Html-ify name and country.
    $nameHtml = htmlEscape( $name );
    $countryIdHtml = htmlEscape( $countryId );

    #--- Hidden field describing the case.
    $caseNr++;
    tableRowFull( "&nbsp;<input type='hidden' name='oldNameAndCountry$caseNr' value='$nameHtml|$countryIdHtml' />" );
    
    #--- Show the person.
    # Note that we set this input to checked, but if there's a better match
    # lower on, then it will take precendence.
    tableRowStyled( 'font-weight:bold', array(
      "<input type='radio' name='action$caseNr' value='new' checked='checked' />",
      visualize( $name ),
      visualize( $countryId ),
      peekLink( $name, $countryId ),
      'mm/dd/yyyy',
      "<input type='text' name='name$caseNr' value='$nameHtml' size='20' />",
      "<input type='text' name='country$caseNr' value='$countryIdHtml' size='20' />",
      "<input type='text' name='semiId$caseNr' value='$semiId' size='10' maxlength='8' />",
    ));

    #--- Show most similar persons.
    $similarsCtr = 0;
    foreach( getMostSimilarPersonsMax( extractRomanName($name), $countryId, $candidates, 10 ) as $similarPerson ){
      list( $other_id, $other_name, $other_countryId ) = $similarPerson;
      
      #--- If name and country match the unfinished persons, pre-select it.
      $checked = ($other_name==$name && $other_countryId==$countryId)
        ? "checked='checked'" : '';
        
      #--- Skip the unfinished person itself. 
      if( $checked && !$other_id )
        continue;

      #--- Html-ify.
      $nameHtml = htmlEscape( $other_name );
      $countryHtml = htmlEscape( $other_countryId );
      $idHtml = htmlEscape( $other_id );
      
      #--- Use "name|country|id" as action.
      $action = "$nameHtml|$countryHtml|$idHtml";
      
      #--- Show the other person.
      tableRow( array(
        "<input type='radio' name='action$caseNr' value='$action' $checked />",
#        ($other_id ? personLink( $other_id, $other_name ) : $other_name),
        visualize( $other_name ),
        visualize( $other_countryId ),
        ($other_id ? "<a class='p' href='../p.php?i=$other_id' target='_blank'>$other_id</a>" : peekLink( $other_name, $other_countryId )),
        $birthdates[ $other_id ],
        '', #sprintf( "%.2f", $similarity ),
        '',
        '',
      ));
      
      #--- Stop after five similar persons.
      if( ++$similarsCtr == 5 )
        break;
    }

    #--- Offer an explicit skip.
    tableRow( array(
      "<input type='radio' name='action$caseNr' value='skip' />",
      'I\'m not sure yet', '', '', '', '', '', ''
    ));
    
    #--- Don't show more than 20 unfinished persons.
    if( $caseNr == 20 )
      break;
  }

  #--- Show 'Update' button, finish table and form.
  tableRowEmpty();
  tableRowFull( "<input type='submit' value='Update' />" );
  tableEnd();
  echo "</form>";
}
    }
    $result['regionName'] = 'World';
    if ($value == $bestValueOfWorld) {
        $bestOfWorld[] = $result;
    }
}
#----------------------------------------------------------------------
#   Print the table.
#----------------------------------------------------------------------
startTimer();
$regionName = preg_replace('/^_/', '', $chosenRegionId);
$eventName = eventName($chosenEventId);
$headerSources = $chosenAverage ? 'Result Details' : '';
tableBegin('results', 5);
tableCaption(true, spaced(array($eventName, $chosenShow, $regionName, $chosenYears)));
tableHeader(explode('|', "Region|Result|Person|Competition|{$headerSources}"), array(0 => 'class="L"', 1 => "class='R2'", 4 => 'class="f"'));
if (isset($bestOfCountry)) {
    $all = array_merge($bestOfWorld, array(0), $bestOfContinent, array(0), $bestOfCountry);
    foreach ($all as $row) {
        if (!$row) {
            tableRowEmpty();
            continue;
        }
        extract($row);
        $isNewRegion = !isset($previousRegionName) || $regionName != $previousRegionName;
        $previousRegionName = $regionName;
        tableRow(array($isNewRegion ? $regionName : '', $isNewRegion ? formatValue($value, $valueFormat) : '', personLink($personId, $personName), competitionLink($competitionId, $competitionName), formatAverageSources($chosenAverage, $row, $valueFormat)));
    }
}
tableEnd();
stopTimer("printing the table");
function showUnfinishedPersons()
{
    #----------------------------------------------------------------------
    global $personsFromPersons, $personsFromResultsWithoutId, $birthdates;
    #--- Pre-compute the candidate tuples: (id, name, countryId, romanName, romanNameSimilarityPlaceHolder, countryIdSimilarityPlaceHolder)
    $candidates = array();
    foreach ($personsFromPersons as $person) {
        list($id, $name, $countryId) = $person;
        $candidates[] = array($id, $name, $countryId, extractRomanName($name), 0, 0);
    }
    #--- Begin the form and table.
    echo "<form action='persons_finish_unfinished_ACTION.php' method='post'>";
    tableBegin('results', 8);
    tableHeader(explode('|', '|personName|countryId|personId|birthdate|personName|countryId|personSemiId'), array(6 => 'class="6"'));
    #--- Walk over all persons from the Results table.
    $caseNr = 0;
    $availableSpots = array();
    // array of semiIds in progress
    foreach ($personsFromResultsWithoutId as $person) {
        list($name, $countryId, $firstYear) = $person;
        #--- Try to compute the semi-id.
        $paddingLetter = 'U';
        $neatName = strtoupper(preg_replace('/[^a-zA-Z ]/', '', removeUglyAccentsAndStuff(extractRomanName($name))));
        $nameParts = explode(' ', $neatName);
        $lastName = $nameParts[count($nameParts) - 1];
        $restOfName = implode(array_slice($nameParts, 0, count($nameParts) - 1));
        // follows a simple trick that prevents us from empty or too short restOfNames and provides the appropriate padding
        $restOfName = str_pad($restOfName, 4, $paddingLetter);
        $lettersToShift = max(0, 4 - strlen($lastName));
        $cleared = false;
        while (!$cleared && $lettersToShift <= 4) {
            $quarterId = substr($lastName, 0, 4 - $lettersToShift) . substr($restOfName, 0, $lettersToShift);
            $semiId = $firstYear . $quarterId;
            // update array of persons in progress
            if (!array_key_exists($semiId, $availableSpots)) {
                $lastIdTaken = dbQuery("SELECT id FROM Persons WHERE id LIKE '{$semiId}__' ORDER BY id DESC LIMIT 1");
                if (!count($lastIdTaken)) {
                    $counter = 0;
                } else {
                    $counter = intval(substr($lastIdTaken[0]['id'], 8, 2), 10);
                }
                $availableSpots[$semiId] = 99 - $counter;
            }
            // is there a spot available?
            if ($availableSpots[$semiId]) {
                $availableSpots[$semiId]--;
                $cleared = true;
            } else {
                $lettersToShift++;
            }
        }
        /* The script has tried all the possibilities and none of them was valid.
         * If we reach here with $cleared set to false (something that is not going to happen in centuries) then
         * the person posting will receive an error in persons_finish_unfinished_ACTION.php and the software team
         * of the future will have work to do.
         */
        if (!$cleared) {
            // if we didn't clear a spot we stick with the first combination
            $lettersToShift = max(0, 4 - strlen($lastName));
            $semiId = $firstYear . substr($lastName, 0, 4 - $lettersToShift) . substr($restOfName, 0, $lettersToShift);
            $availableSpots[$semiId] = 0;
        }
        #--- Html-ify name and country.
        $nameHtml = htmlEscape($name);
        $countryIdHtml = htmlEscape($countryId);
        #--- Hidden field describing the case.
        $caseNr++;
        tableRowFull("&nbsp;<input type='hidden' name='oldNameAndCountry{$caseNr}' value='{$nameHtml}|{$countryIdHtml}' />");
        #--- Show the person.
        # Note that we set this input to checked, but if there's a better match
        # lower on, then it will take precendence.
        tableRowStyled('font-weight:bold', array("<input type='radio' name='action{$caseNr}' value='new' checked='checked' />", visualize($name), visualize($countryId), peekLink($name, $countryId), 'mm/dd/yyyy', "<input type='text' name='name{$caseNr}' value='{$nameHtml}' size='20' />", "<input type='text' name='country{$caseNr}' value='{$countryIdHtml}' size='20' />", "<input type='text' name='semiId{$caseNr}' value='{$semiId}' size='10' maxlength='8' />"));
        #--- Show most similar persons.
        $similarsCtr = 0;
        foreach (getMostSimilarPersonsMax(extractRomanName($name), $countryId, $candidates, 10) as $similarPerson) {
            list($other_id, $other_name, $other_countryId) = $similarPerson;
            #--- If name and country match the unfinished persons, pre-select it.
            $checked = $other_name == $name && $other_countryId == $countryId ? "checked='checked'" : '';
            #--- Skip the unfinished person itself.
            if ($checked && !$other_id) {
                continue;
            }
            #--- Html-ify.
            $nameHtml = htmlEscape($other_name);
            $countryHtml = htmlEscape($other_countryId);
            $idHtml = htmlEscape($other_id);
            #--- Use "name|country|id" as action.
            $action = "{$nameHtml}|{$countryHtml}|{$idHtml}";
            #--- Show the other person.
            tableRow(array("<input type='radio' name='action{$caseNr}' value='{$action}' {$checked} />", visualize($other_name), visualize($other_countryId), $other_id ? "<a class='p' href='../p.php?i={$other_id}' target='_blank'>{$other_id}</a>" : peekLink($other_name, $other_countryId), $birthdates[$other_id], '', '', ''));
            #--- Stop after five similar persons.
            if (++$similarsCtr == 5) {
                break;
            }
        }
        #--- Offer an explicit skip.
        tableRow(array("<input type='radio' name='action{$caseNr}' value='skip' />", 'I\'m not sure yet', '', '', '', '', '', ''));
        #--- Don't show more than 20 unfinished persons.
        if ($caseNr == 20) {
            break;
        }
    }
    #--- Show 'Update' button, finish table and form.
    tableRowEmpty();
    tableRowFull("<input type='submit' value='Update' />");
    tableEnd();
    echo "</form>";
}
function checkTooMuchInResults()
{
    #----------------------------------------------------------------------
    global $personsFromPersons, $personsFromResults;
    echo "<hr />";
    $tooMuchInResults = array();
    #--- Find all ('finished') entries in Results that don't have a match in Persons.
    foreach (array_keys($personsFromResults) as $personKey) {
        if ($personsFromResults[$personKey]['id'] && !isset($personsFromPersons[$personKey])) {
            $tooMuchInResults[] = $personKey;
        }
    }
    #--- If all OK, say so and return.
    if (empty($tooMuchInResults)) {
        echo "<p style='color:#6C6'><strong>OK!</strong> All persons in <strong>Results</strong> who have an id also appear in <strong>Persons</strong>.</p>";
        return;
    }
    #--- Otherwise, show the Results troublemakers and possible matches in Persons.
    echo "<p style='color:#F00'><strong>BAD!</strong> Not all persons in <strong>Results</strong> who have an id also appear in <strong>Persons</strong>:</p>";
    tableBegin('results', 4);
    tableHeader(explode('|', '|Name|countryId|id'), array(3 => 'class="f"'));
    foreach ($tooMuchInResults as $personKey) {
        extract($personsFromResults[$personKey]);
        tableRowStyled('font-weight:bold', array('', visualize($name), visualize($countryId), visualize($id)));
        $currId = $id;
        $currName = $name;
        $currCountryId = $countryId;
        foreach (getMostSimilarPersons($id, $name, $countryId, $personsFromPersons) as $similarPerson) {
            extract($similarPerson);
            tableRow(array('<a href="persons_check_finished_ACTION.php?action=fix_results_data' . '&old_name=' . urlEncode($currName) . '&new_name=' . urlEncode($name) . '&old_id=' . urlEncode($currId) . '&new_id=' . urlEncode($id) . '&old_country=' . urlEncode($currCountryId) . '&new_country=' . urlEncode($countryId) . '">Change to:</a>', visualize($name), visualize($countryId), visualize($id)));
        }
        tableRowEmpty();
    }
    tableEnd();
    $GLOBALS["success"] = false;
}