#!/usr/bin/env perl
#
# medalleroMoscu2013.pl
#
# Autor:
# Joaquín Ferrero
#
# Descripción:
# Actualización automática de medalleros olímpicos en Wikipedia.
#
# Entrada: ninguna
# Salida: ninguna
#
# Historial:
# 2013.08.13 : Versión Moscú Atletismo 2013
# 2013.06.26 : Versión Mersin Mediterráneo 2013
# 2012.08.31 : Versión Londres Paralímpicos 2012
# 2012.07.31 : Versión Londres Verano 2012
# 2010.03.20 : Versión Medellin Sudamericanos 2010
# 2010.03.13 : Versión Vancouver Paralimpicos 2010
# 2010.02.16 : Versión Vancouver Invierno 2010
# 2008.09.07 : Versión Pekín Verano 2008
#
### Bibliotecas -------------------------------------------------------------
use Modern::Perl 2013; # Programamos en Perl moderno
use utf8::all; # Activar todo el soporte para UTF-8. Realmente todo
use Mojo::UserAgent; # Un poco de mojo...
use MediaWiki::API; # Y mucha Wikipedia
#use Data::Dumper;
### Configuración -----------------------------------------------------------
my $PAÍS_ANFITRIÓN = 'RUS';
my $URL_MEDALLERO = 'http://www.iaaf.org/competitions/iaaf-world-championships/14th-iaaf-world-championships-4873/medaltable';
my $WIKIPEDIA_PÁGINA_MEDALLERO = 'Campeonato Mundial de Atletismo de 2013';
my $WIKIPEDIA_PÁGINA_TEST = 'Wikipedia:Zona de pruebas/5';
my $WIKIPEDIA_USUARIO_LOGIN = 'user';
my $WIKIPEDIA_USUARIO_PASSW = 'password';
my $WIKIPEDIA_API_URL = 'http://es.wikipedia.org/w/api.php';
my $DEBUG = 1; # 0 o 1
my $título_página_wiki = $WIKIPEDIA_PÁGINA_MEDALLERO; # $WIKIPEDIA_PÁGINA_TEST
my $medallero_wiki_cabeza = <<"EOF";
== Medallero ==
<!--
ATENCIÓN
Esta tabla se actualiza de forma automática cada 15 min. durante el periodo de los juegos.
CUALQUIER cambio realizado de forma manual se perderá.
AVISAR de incidencias al usuario JoaquinFerrero.
-->
EOF
### Fin de configuración ----------------------------------------------------
## Obtención de los resultados ----------------------------------------------
my $medallero_html;
my $ua = Mojo::UserAgent->new(
name => 'Mozilla/5.0 (X11; Ubuntu; Linux i686; rv:14.0) Mojolicious/2012 Wikipedia/es',
request_timeout => 5,
);
for my $retry (1 .. 3) { # Tres intentos
$medallero_html = $ua->get(
$URL_MEDALLERO,
{
}
)->res->dom->find("table.records-table")->[0]; # CSS Selector
last if defined $medallero_html;
say "Intento fallido $retry..." if $DEBUG;
sleep 30;
}
die "ERROR: No he podido leer la página del medallero oficial\n"
if not defined $medallero_html;
## Extracción de resultados -------------------------------------------------
my @tabla_medallero_oficial; # aquí guardamos el resultado de la extracción
my @filas = $medallero_html->find("tr")->each;
shift @filas; # la primera línea de la tabla no es interesante
my $posición = 1; # Renumeración de las posiciones
my $posición_absoluta = 1; # Posición real dentro del global de posiciones
for my $fila (@filas) {
my $resultados; # resultados para un participante
my @celdas = $fila->find("td")->each;
next if @celdas != 6;
$celdas[1]->children->first->attrs('src')
=~ /(\w+)[.](?:gif|png)$/; # extraemos el código COI de la bandera
$resultados->{'COI'} = uc $1;
my @medallas;
for my $celda (@celdas[2 .. 5]) { # resto de celdas de la fila: número de medallas
push @medallas, 0+ $celda->text;
}
$resultados->{'medallas'} = \@medallas;
# ajustar posición según logros alcanzados
if ( @tabla_medallero_oficial > 0 # solo a partir de la segunda fila
and (
$tabla_medallero_oficial[-1]{'medallas'}[0] > $medallas[0] # Oro
or $tabla_medallero_oficial[-1]{'medallas'}[1] > $medallas[1] # Plata
or $tabla_medallero_oficial[-1]{'medallas'}[2] > $medallas[2] # Bronce
)
) {
$posición = $posición_absoluta; # sí: su posición es una más que el anterior
}
$resultados->{'posición'} = $posición; # guardamos nueva posición
push @tabla_medallero_oficial, $resultados; # nueva fila en el medallero
$posición_absoluta++;
}
die "ERROR: No he leído la tabla del medallero oficial"
if ! @tabla_medallero_oficial;
## Confección del Medallero en formato wiki ---------------------------------
my $medallero_wiki; # Medallero en formato Wiki
my @totales_medallero; # Almacena la suma de las medallas
# Cabecera de la tabla
$medallero_wiki = $medallero_wiki_cabeza;
$medallero_wiki .= "{{Leyenda|#CCCCFF|País organizador|border=solid 1px #AAA}}\n";
$medallero_wiki .= "{| {{Medallero|tipo=1|ancho=60%}}\n";
# Filas de la tabla
my $DCOL = ' || ';
for my $fila (@tabla_medallero_oficial) {
my @medallas = @{$fila->{'medallas'}}; # Número de medallas
map { $totales_medallero[$_] += $medallas[$_] } 0 .. 3; # Cálculo de los totales
$medallero_wiki .= '|-'; # Nueva fila
$medallero_wiki .= '-bgcolor=ccccff' if $fila->{'COI'} eq $PAÍS_ANFITRIÓN; # destaque
$medallero_wiki .= "\n";
$medallero_wiki .= '| '
. join $DCOL =>
"'''$fila->{'posición'}'''", # posición
"{{$fila->{'COI'}}}", # país
@medallas # medallas
;
$medallero_wiki .= "\n";
}
# Totales y fin de la tabla
$medallero_wiki .= "|-\n" . join($DCOL, '! colspan="2" | Total', @totales_medallero) . "\n|}";
$medallero_wiki .= "\n\n";
## Conexión con Wikipedia ---------------------------------------------------
my $Wikipedia = MediaWiki::API->new({
api_url => $WIKIPEDIA_API_URL,
retries => 3,
retry_delay => 30,
});
$Wikipedia->login({
lgname => $WIKIPEDIA_USUARIO_LOGIN,
lgpassword => $WIKIPEDIA_USUARIO_PASSW,
})
or die $Wikipedia->{error}->{code} . ': ' . $Wikipedia->{error}->{details};
## Actualización de la página del medallero ---------------------------------
my $página_wiki; # Contenido de la página wiki actual
my $página_antes_wiki; # Contenido de la página wiki anterior
my $página_wiki_ref = $Wikipedia->get_page({
title => $título_página_wiki,
});
die "ERROR: No conseguí la página del medallero\n"
if $página_wiki_ref->{missing};
$página_wiki = $página_antes_wiki = $página_wiki_ref->{'*'}; # Cómo es la página en este momento
# Editamos la página
if ($página_wiki =~ s/^=+ Medallero =+.+?(?=^=)/$medallero_wiki/sm) {
if ($página_wiki ne $página_antes_wiki) { # Si hay realmente un cambio, la editamos
$Wikipedia->edit({
action => 'edit',
text => $página_wiki,
title => $título_página_wiki,
basetimestamp => $página_wiki_ref->{timestamp},
summary => 'Actualización automática del medallero',
})
or die $Wikipedia->{error}->{code} . ': ' . $Wikipedia->{error}->{details}
;
say 'Medallero actualizado' if $DEBUG;
}
else {
# say 'No hay cambios' if $DEBUG;
}
}
else {
die 'ERROR: no encuentro la sección del medallero en la página';
}
__END__