add wiki compare
This commit is contained in:
parent
692e609a46
commit
38fbc451f5
9 changed files with 81151 additions and 126 deletions
|
|
@ -5,6 +5,7 @@ namespace App\Controller;
|
|||
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
|
||||
use Symfony\Component\HttpFoundation\Response;
|
||||
use Symfony\Component\Routing\Annotation\Route;
|
||||
use Symfony\Component\HttpFoundation\Request;
|
||||
|
||||
class WikiController extends AbstractController
|
||||
{
|
||||
|
|
@ -23,13 +24,294 @@ class WikiController extends AbstractController
|
|||
$headers = array_shift($csvData);
|
||||
|
||||
$wikiPages = [];
|
||||
$missingTranslations = [];
|
||||
|
||||
// First pass: collect all staleness scores to find min and max
|
||||
$stalenessScores = [];
|
||||
foreach ($csvData as $row) {
|
||||
$page = array_combine($headers, $row);
|
||||
if (isset($page['staleness_score']) && is_numeric($page['staleness_score'])) {
|
||||
$stalenessScores[] = (float)$page['staleness_score'];
|
||||
}
|
||||
}
|
||||
|
||||
// Find min and max scores for normalization
|
||||
$minScore = !empty($stalenessScores) ? min($stalenessScores) : 0;
|
||||
$maxScore = !empty($stalenessScores) ? max($stalenessScores) : 100;
|
||||
|
||||
// Second pass: process pages and normalize scores
|
||||
foreach ($csvData as $row) {
|
||||
$page = array_combine($headers, $row);
|
||||
|
||||
// Normalize staleness score to 0-100 range (0 = best, 100 = worst)
|
||||
if (isset($page['staleness_score']) && is_numeric($page['staleness_score'])) {
|
||||
$originalScore = (float)$page['staleness_score'];
|
||||
|
||||
// Avoid division by zero
|
||||
if ($maxScore > $minScore) {
|
||||
$normalizedScore = ($originalScore - $minScore) / ($maxScore - $minScore) * 100;
|
||||
} else {
|
||||
$normalizedScore = 50; // Default to middle value if all scores are the same
|
||||
}
|
||||
|
||||
// Round to 2 decimal places
|
||||
$page['staleness_score'] = round($normalizedScore, 2);
|
||||
}
|
||||
|
||||
$wikiPages[$page['key']][$page['language']] = $page;
|
||||
}
|
||||
|
||||
// Identify pages missing French translations
|
||||
foreach ($wikiPages as $key => $languages) {
|
||||
if (isset($languages['en']) && !isset($languages['fr'])) {
|
||||
$missingTranslations[$key] = $languages['en'];
|
||||
}
|
||||
}
|
||||
|
||||
// Sort wiki pages by staleness score (descending)
|
||||
uasort($wikiPages, function($a, $b) {
|
||||
$scoreA = isset($a['en']) && isset($a['fr']) && isset($a['en']['staleness_score']) ? (float)$a['en']['staleness_score'] : 0;
|
||||
$scoreB = isset($b['en']) && isset($b['fr']) && isset($b['en']['staleness_score']) ? (float)$b['en']['staleness_score'] : 0;
|
||||
return $scoreB <=> $scoreA;
|
||||
});
|
||||
|
||||
return $this->render('admin/wiki.html.twig', [
|
||||
'wiki_pages' => $wikiPages,
|
||||
'missing_translations' => $missingTranslations,
|
||||
]);
|
||||
}
|
||||
|
||||
#[Route('/admin/wiki/compare/{key}', name: 'app_admin_wiki_compare')]
|
||||
public function compare(string $key): Response
|
||||
{
|
||||
$csvFile = $this->getParameter('kernel.project_dir') . '/wiki_compare/wiki_pages.csv';
|
||||
$jsonFile = $this->getParameter('kernel.project_dir') . '/wiki_compare/outdated_pages.json';
|
||||
|
||||
if (!file_exists($csvFile)) {
|
||||
$this->addFlash('error', 'Le fichier wiki_pages.csv n\'existe pas.');
|
||||
return $this->redirectToRoute('app_admin_index');
|
||||
}
|
||||
|
||||
$csvData = array_map('str_getcsv', file($csvFile));
|
||||
$headers = array_shift($csvData);
|
||||
|
||||
// Process CSV data to find the requested key
|
||||
$enPage = null;
|
||||
$frPage = null;
|
||||
|
||||
foreach ($csvData as $row) {
|
||||
$page = array_combine($headers, $row);
|
||||
if ($page['key'] === $key) {
|
||||
if ($page['language'] === 'en') {
|
||||
$enPage = $page;
|
||||
} elseif ($page['language'] === 'fr') {
|
||||
$frPage = $page;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// If English page doesn't exist, redirect back with error
|
||||
if (!$enPage) {
|
||||
$this->addFlash('error', 'La page wiki pour la clé "' . $key . '" n\'existe pas.');
|
||||
return $this->redirectToRoute('app_admin_wiki');
|
||||
}
|
||||
|
||||
// Get detailed content comparison from JSON file
|
||||
$detailedComparison = null;
|
||||
$mediaDiff = 0;
|
||||
|
||||
if (file_exists($jsonFile)) {
|
||||
$jsonData = json_decode(file_get_contents($jsonFile), true);
|
||||
|
||||
foreach ($jsonData as $page) {
|
||||
if ($page['key'] === $key) {
|
||||
$detailedComparison = [
|
||||
'section_comparison' => $page['section_comparison'] ?? null,
|
||||
'link_comparison' => $page['link_comparison'] ?? null,
|
||||
'media_comparison' => $page['media_comparison'] ?? null
|
||||
];
|
||||
|
||||
$mediaDiff = $page['media_diff'] ?? 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Calculate staleness score components
|
||||
$scoreComponents = [];
|
||||
|
||||
if ($frPage) {
|
||||
// Calculate date difference in days
|
||||
$dateDiff = 0;
|
||||
if ($enPage['last_modified'] && $frPage['last_modified']) {
|
||||
$enDate = \DateTime::createFromFormat('Y-m-d', $enPage['last_modified']);
|
||||
$frDate = \DateTime::createFromFormat('Y-m-d', $frPage['last_modified']);
|
||||
if ($enDate && $frDate) {
|
||||
$dateDiff = ($enDate->getTimestamp() - $frDate->getTimestamp()) / (60 * 60 * 24);
|
||||
}
|
||||
}
|
||||
|
||||
// Calculate content differences
|
||||
$wordDiff = $enPage['word_count'] - $frPage['word_count'];
|
||||
$sectionDiff = $enPage['sections'] - $frPage['sections'];
|
||||
$linkDiff = $enPage['link_count'] - $frPage['link_count'];
|
||||
|
||||
// Calculate score components
|
||||
$dateComponent = abs($dateDiff) * 0.2;
|
||||
$wordComponent = abs($wordDiff) / 100 * 0.5;
|
||||
$sectionComponent = abs($sectionDiff) * 0.15;
|
||||
$linkComponent = abs($linkDiff) / 10 * 0.15;
|
||||
|
||||
$scoreComponents = [
|
||||
'date' => [
|
||||
'value' => $dateDiff,
|
||||
'weight' => 0.2,
|
||||
'component' => $dateComponent,
|
||||
'description' => 'Différence de date (en jours)'
|
||||
],
|
||||
'word' => [
|
||||
'value' => $wordDiff,
|
||||
'weight' => 0.5,
|
||||
'component' => $wordComponent,
|
||||
'description' => 'Différence de nombre de mots'
|
||||
],
|
||||
'section' => [
|
||||
'value' => $sectionDiff,
|
||||
'weight' => 0.15,
|
||||
'component' => $sectionComponent,
|
||||
'description' => 'Différence de nombre de sections'
|
||||
],
|
||||
'link' => [
|
||||
'value' => $linkDiff,
|
||||
'weight' => 0.15,
|
||||
'component' => $linkComponent,
|
||||
'description' => 'Différence de nombre de liens'
|
||||
]
|
||||
];
|
||||
|
||||
// Add media component if available
|
||||
if (isset($enPage['media_count']) && isset($frPage['media_count'])) {
|
||||
$mediaComponent = abs($mediaDiff) / 5 * 0.1;
|
||||
$scoreComponents['media'] = [
|
||||
'value' => $mediaDiff,
|
||||
'weight' => 0.1,
|
||||
'component' => $mediaComponent,
|
||||
'description' => 'Différence de nombre d\'images'
|
||||
];
|
||||
|
||||
// Adjust other weights to maintain total of 1.0
|
||||
$scoreComponents['date']['weight'] = 0.2;
|
||||
$scoreComponents['word']['weight'] = 0.45;
|
||||
$scoreComponents['section']['weight'] = 0.15;
|
||||
$scoreComponents['link']['weight'] = 0.1;
|
||||
}
|
||||
}
|
||||
|
||||
// Create URL for new French page if it doesn't exist
|
||||
$createFrUrl = null;
|
||||
if (!$frPage) {
|
||||
$createFrUrl = 'https://wiki.openstreetmap.org/wiki/FR:Key:' . $key;
|
||||
}
|
||||
|
||||
// Format section titles for copy functionality
|
||||
$enSections = '';
|
||||
$frSections = '';
|
||||
|
||||
if ($detailedComparison && $detailedComparison['section_comparison']) {
|
||||
// English sections
|
||||
if ($enPage) {
|
||||
$enSectionsList = [];
|
||||
|
||||
// Add common sections
|
||||
foreach ($detailedComparison['section_comparison']['common'] as $section) {
|
||||
$enSectionsList[] = str_repeat('=', $section['en']['level']) . ' ' .
|
||||
$section['en']['title'] . ' ' .
|
||||
str_repeat('=', $section['en']['level']);
|
||||
}
|
||||
|
||||
// Add English-only sections
|
||||
foreach ($detailedComparison['section_comparison']['en_only'] as $section) {
|
||||
$enSectionsList[] = str_repeat('=', $section['level']) . ' ' .
|
||||
$section['title'] . ' ' .
|
||||
str_repeat('=', $section['level']) . ' (EN only)';
|
||||
}
|
||||
|
||||
$enSections = implode("\n", $enSectionsList);
|
||||
}
|
||||
|
||||
// French sections
|
||||
if ($frPage) {
|
||||
$frSectionsList = [];
|
||||
|
||||
// Add common sections
|
||||
foreach ($detailedComparison['section_comparison']['common'] as $section) {
|
||||
$frSectionsList[] = str_repeat('=', $section['fr']['level']) . ' ' .
|
||||
$section['fr']['title'] . ' ' .
|
||||
str_repeat('=', $section['fr']['level']);
|
||||
}
|
||||
|
||||
// Add French-only sections
|
||||
foreach ($detailedComparison['section_comparison']['fr_only'] as $section) {
|
||||
$frSectionsList[] = str_repeat('=', $section['level']) . ' ' .
|
||||
$section['title'] . ' ' .
|
||||
str_repeat('=', $section['level']) . ' (FR only)';
|
||||
}
|
||||
|
||||
$frSections = implode("\n", $frSectionsList);
|
||||
}
|
||||
}
|
||||
|
||||
// Format links for copy functionality
|
||||
$enLinks = '';
|
||||
$frLinks = '';
|
||||
|
||||
if ($detailedComparison && $detailedComparison['link_comparison']) {
|
||||
// English links
|
||||
if ($enPage) {
|
||||
$enLinksList = [];
|
||||
|
||||
// Add common links
|
||||
foreach ($detailedComparison['link_comparison']['common'] as $link) {
|
||||
$enLinksList[] = $link['en']['text'] . ' - ' . $link['en']['href'];
|
||||
}
|
||||
|
||||
// Add English-only links
|
||||
foreach ($detailedComparison['link_comparison']['en_only'] as $link) {
|
||||
$enLinksList[] = $link['text'] . ' - ' . $link['href'] . ' (EN only)';
|
||||
}
|
||||
|
||||
$enLinks = implode("\n", $enLinksList);
|
||||
}
|
||||
|
||||
// French links
|
||||
if ($frPage) {
|
||||
$frLinksList = [];
|
||||
|
||||
// Add common links
|
||||
foreach ($detailedComparison['link_comparison']['common'] as $link) {
|
||||
$frLinksList[] = $link['fr']['text'] . ' - ' . $link['fr']['href'];
|
||||
}
|
||||
|
||||
// Add French-only links
|
||||
foreach ($detailedComparison['link_comparison']['fr_only'] as $link) {
|
||||
$frLinksList[] = $link['text'] . ' - ' . $link['href'] . ' (FR only)';
|
||||
}
|
||||
|
||||
$frLinks = implode("\n", $frLinksList);
|
||||
}
|
||||
}
|
||||
|
||||
return $this->render('admin/wiki_compare.html.twig', [
|
||||
'key' => $key,
|
||||
'en_page' => $enPage,
|
||||
'fr_page' => $frPage,
|
||||
'score_components' => $scoreComponents,
|
||||
'create_fr_url' => $createFrUrl,
|
||||
'detailed_comparison' => $detailedComparison,
|
||||
'en_sections' => $enSections,
|
||||
'fr_sections' => $frSections,
|
||||
'en_links' => $enLinks,
|
||||
'fr_links' => $frLinks
|
||||
]);
|
||||
}
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue