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( " <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>"; }
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(" <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 importLocalNames () { #---------------------------------------------------------------------- global $chosenUpload, $chosenConfirm, $chosenNamesFile, $chosenFilename; $oneBad = false; $oneGood = false; if( $chosenUpload ){ $upload_path = '../upload/'; if( $chosenFilename == '' ) $chosenFilename = 'tmp' . rand(); if( ! $chosenConfirm ) move_uploaded_file( $_FILES['namesFile']['tmp_name'], $upload_path . $chosenFilename . '.txt' ); $nameLines = file( $upload_path . $chosenFilename . '.txt', FILE_SKIP_EMPTY_LINES ); foreach( $nameLines as $nameLine ){ $nameLine = rtrim( $nameLine ); if( count( explode( ',', $nameLine )) != 2 ){ echo "<span style='color:#F00'>Wrong line syntax: <br /> " . htmlEscape( $nameLine ) . "</span><br />\n"; $oneBad = true; continue; } list( $wcaId, $localName ) = explode( ',', $nameLine ); $wcaId = utf8_decode( $wcaId ); $persons = dbQuery( "SELECT name personName FROM Persons WHERE id='$wcaId' AND subId=1" ); if( count( $persons ) == 0 ){ echo "<span style='color:#DB0'>Unknown WCA id " . htmlEscape( $wcaId ) . "</span><br />\n"; $oneBad = true; continue; } $person = array_shift( $persons ); extract( $person ); if( $chosenConfirm ){ $localName = mysql_real_escape_string( $localName ); $name = mysql_real_escape_string( extractRomanName( $personName )) . ' (' . $localName . ')'; $personName = mysql_real_escape_string( $personName ); dbCommand( "UPDATE Persons SET name='$name' WHERE id='$wcaId' AND subId=1" ); dbCommand( "UPDATE Results SET personName='$name' WHERE personId='$wcaId' AND personName='$personName'" ); $oneGood = true; } else{ $personLocalName = extractLocalName( $personName ); if( $localName == ''){ if( $personLocalName == '' ){} else{ echo "<span style='color:#3C3'>I will remove name ".htmlEscape( $personLocalName )." from ".htmlEscape( $personName )."($wcaId)</span><br />\n"; } } else{ if( $personLocalName == '' ){ echo "<span style='color:#3C3'>I will add name ".htmlEscape( $localName )." to ".htmlEscape( $personName )."($wcaId)</span><br />\n"; } else{ echo "<span style='color:#3C3'>I will change name ".htmlEscape( $personLocalName )." to ".htmlEscape( $localName )." for ".htmlEscape( $personName )."($wcaId)</span><br />\n"; } } } } if( $chosenConfirm ){ if(( $oneGood ) and ( ! $oneBad )) noticeBox3( 1, "Complete. All names were updated." ); if(( $oneGood ) and ( $oneBad )) noticeBox3( 0, "Complete. However, some lines were skipped." ); if(( ! $oneGood ) and ( $oneBad )) noticeBox3( -1, "Cound't update anything." ); if(( ! $oneGood ) and ( ! $oneBad )) noticeBox3( 0, "I found an empty text !?" ); $chosenUpload = false; unlink( $upload_path . $chosenFilename . '.txt' ); } else{ echo "<form method='POST'>\n"; echo "<input type='hidden' id='namesFile' name='namesFile' value='".htmlEscape($chosenNamesFile)."' />\n"; echo "<input type='hidden' id='upload' name='upload' value='$chosenUpload' />\n"; echo "<input type='hidden' id='filename' name='filename' value='".htmlEscape($chosenFilename)."' />\n"; echo "<input type='submit' id='confirm' name='confirm' value='Confirm' /></form>\n"; } } if( ! $chosenUpload ){ adminHeadline( 'Add local names' ); echo "<p>You can add or modify local names here, by upload a file containing the names. The file must be a plain text file encoded in UTF-8. Each line must contain: the WCA id, a comma (',') and the name you would like to add. If you want to remove a name from the database, just leave the name part blank.</p>\n"; echo "<p>Example: <br /><br />2009WANG20,王超<br />2009WANG62,王宇欣<br />2009WANG13,王宇轩<br />etc.</p>\n"; echo "<hr>\n"; echo "<table class='prereg'>\n"; echo " <form method='POST' enctype='multipart/form-data'>\n"; echo " <tr><td width='30%'><label for='namesFile'>Upload file: </label></td>\n"; echo " <td><input type='file' id='namesFile' name='namesFile' /></td>\n"; echo " <td><input type='submit' id='upload' name='upload' value='Upload' /></td></tr></form>\n"; echo "</table>\n"; } }
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, ' | ', 'Person', 'Appearances', ' ') $columnDefs = "{$columnDefs} [f] "; $columnDefs = preg_replace('/\\|/', ' | ', $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"; }