Usuario:JoaquinFerrero/Medallero2010

Programa para la actualización automática del Medallero de los Juegos Olímpicos Vancouver 2010

editar
#!/usr/bin/perl
# *- encode: utf8. tabs: 4 spaces. -*
#
# medalleroVancouver2010.pl
#
# Autor:
#       Joaquín Ferrero
#
# Descripción:
#       Actualización automática del medallero olímpico en Wikipedia para los Juegos Olímpicos de Vancouver 2010.
#
#       La conexión entre la página oficial y la información de Wikipedia se realiza con los códigos de país que
#       el COI asigna a cada uno: http://es.wikipedia.org/wiki/C%C3%B3digos_nacionales_del_COI
#
# Entrada: ninguna
# Salida:  ninguna
#
# Historial:
#   2010.02.16 : Versión para Vancouver 2010
#   2008.09.07 : Versión inicial para Pekín 2008
#

## Bibliotecas
use common::sense;                                              # Siempre hay que tener sentido común
use LWP::Simple;
use MediaWiki::API;

## Constantes
my $MEDALLERO_OFICIAL                 = 'http://www.vancouver2010.com/olympic-medals/';
my $WIKIPEDIA_VANCOUVER2010           = 'Juegos Olímpicos de Vancouver 2010';
my $WIKIPEDIA_MEDALLERO_VANCOUVER2010 = 'Anexo:Medallero de los Juegos Olímpicos de Vancouver 2010';
my $WIKIPEDIA_TEST_PAGE               = 'Wikipedia:Zona de pruebas';
my $AVISO = qq(<includeonly><!-- Para cerrar la tabla en el artículo principal -->|}</includeonly><noinclude><!--
Para que automáticamente se genere una lista de sólo 10 países en el artículo principal, mover el tag "noinclude"
tras los 10 mejores países clasificados -->\n);

## Variables
my %paises;                     # $paises{SVK} = "{{BanderaOL|Eslovaquia|SVK|ed=Vancouver 2010}}"
my $medallero_oficial;          # Resultados del medallero desde el sitio oficial
my @tabla_medallero_oficial;    # $tabla_medallero_oficial[$i] = [$posicion,$pais,@medallas,$total]
my $wiki_medallero;             # Tabla del medallero en formato wiki
my @totales_medallero;          # Almacena la suma de las medallas
my $wiki_pagina;                # Contenido de la página en formato wiki

## Configuración
my $DEBUG = 1;                                                  # 1: Dar información extra en la salida estándar. 0: No
my $wikipedia_resultado = $WIKIPEDIA_MEDALLERO_VANCOUVER2010;   # Para hacer pruebas, cambiar esta variable a $WIKIPEDIA_TEST_PAGE
                                                                # En producción, cambiarla por $WIKIPEDIA_MEDALLERO_VANCOUVER2010

## Conexión con Wikipedia
my $mw = MediaWiki::API->new({
    api_url     => 'http://es.wikipedia.org/w/api.php',
    retries     => 3,
    retry_delay => 30,
});

$mw->login({
    lgname      => 'JoaquinFerrero',
    lgpassword  => 'contraseña',
})
    or die $mw->{error}->{code} . ': ' . $mw->{error}->{details};

## Obtención de la lista de los países participantes
while (my $l = <DATA>) {                                        # Primero, desde la sección DATA
    chomp $l;
    my ($id, $valor) = split " ", $l, 2;
    $paises{$id} = $valor;
}
    
if (!%paises) {                                                 # Si no hay DATA, entonces desde la propia página web de Wikipedia
    $wiki_pagina = $mw->get_page({ title => $WIKIPEDIA_VANCOUVER2010 })->{'*'};

                                                                # Buscamos las banderas de los participantes
    while ($wiki_pagina =~ /BanderaOL\|(.+?)\|(...)\|(ed=.*?)\}/simog) {
        $paises{$2} = "{{BanderaOL|$1|$2|$3}}";
    }

    die "ERROR: la página de los Juegos no es correcta\n"  if ! %paises;

                                                                # Modificación del programa, en la sección DATA
    open my $yo_mismo, q[>>], $0  or  die "ERROR: No puede añadir a $0\n";
    binmode $yo_mismo, ':utf8';
    while(my($p,$v) = each %paises) {
        say $yo_mismo "$p $v";
    }
    close $yo_mismo;

    say 'Actualizado el programa medallero.pl'  if $DEBUG;
}

die "ERROR: no tengo una lista correcta de países\n"  if ! %paises;

## Página con los resultados oficiales
$medallero_oficial = get($MEDALLERO_OFICIAL);
die "ERROR: No conseguí los resultados de medallas\n"  if not $medallero_oficial;

my ($seccion_medallas) = $medallero_oficial =~ m{<div class="dataTable medalDataTable medalCount">(.*?)</div>}smio;

while($seccion_medallas =~ m{<tr .*? > (.*?) </tr>}smigox) {
    my $datos = $1;

    my($pais)   = $datos =~ /<td class="c2".*? flag(...)"/io;
    my($oro)    = $datos =~ /<td class="c3">(\d+)/io;
    my($plata)  = $datos =~ /<td class="c4">(\d+)/io;
    my($bronze) = $datos =~ /<td class="c5">(\d+)/io;

    if ($paises{$pais}) {
        $pais = $paises{$pais};
        push @tabla_medallero_oficial, [ $pais, $oro, $plata, $bronze, $oro+$plata+$bronze ];
    }
    elsif ($pais) {
        say "ERROR: No tengo código para el país [$pais]:\n$datos";
    }
}

die "ERROR: No he leído medallero oficial"  if ! @tabla_medallero_oficial;

# Ordenación según el número de medallas oro, plata y bronce
@tabla_medallero_oficial
    = sort {
          $b->[1] <=> $a->[1]                                   # Oro
                  ||
          $b->[2] <=> $a->[2]                                   # Plata
                  ||
          $b->[3] <=> $a->[3]                                   # Bronze
                  ||
          $a->[0] cmp $b->[0]                                   # Nombre del país
      }
      @tabla_medallero_oficial
      ;

# Inserción del número de posición
my $cuenta_filas;
my $cuenta_posicion;
my $anterior_pais_medallero = '';

for my $pais_ref (@tabla_medallero_oficial) {

    $cuenta_filas++;

    my $pais_medallero = join ',', @{ $pais_ref }[1..4];        # Vemos el aspecto de las medallas

    if ($pais_medallero ne $anterior_pais_medallero) {          # Si el medallero del país es distinto del anterior país
        $cuenta_posicion = $cuenta_filas;                       # actualizamos el contador de posición al de las filas
    }

    unshift @{$pais_ref}, $cuenta_posicion;                     # agregamos la posición en
                                                                # la primera posición de la información de cada país
    $anterior_pais_medallero = $pais_medallero;
}

## Medallero en formato wiki
$wiki_medallero  = <<"EOF";
== Medallero ==
</noinclude><!--

        ATENCIÓN: La tabla se actualiza de forma automática cada 5 min. durante el periodo de los juegos.

                         CUALQUIER cambio realizado de forma manual se perderá.

-->{| {{Medallero|style=text-align:right;}}
EOF

my $se_ha_puesto_el_aviso = 0;

foreach my $fila (@tabla_medallero_oficial) {

    if ($fila->[0] > 10  and  ! $se_ha_puesto_el_aviso++) {     # Poner nota de corte a los diez primeros clasificados
        $wiki_medallero .= $AVISO;
    }

    $wiki_medallero                                             # Cada $fila del medallero
        .= "|-\n"
        .  "|'''$fila->[0]'''\n"
        .  join( q{||align=center|}, "|align=left|$fila->[1]", @{$fila}[2 .. 5] )
        .  "\n"
        ;

    map { $totales_medallero[$_-2] += $fila->[$_] } 2 .. 5;     # Cálculo de los totales
}

# Totales y fin de la tabla
$wiki_medallero
    .= qq(|-class="sortbottom"\n)
    .  join('||align=center|', "!colspan=2| '''Total'''", @totales_medallero) . "\n|}"
    ;

if (not $se_ha_puesto_el_aviso) {
    $wiki_medallero .= '<noinclude>';
}

$wiki_medallero .= "\n\n";

## Actualización de la página del medallero
my $wiki_pagina_ref = $mw->get_page({ title => $wikipedia_resultado });
die "ERROR: No conseguí la página del medallero\n"  if $wiki_pagina_ref->{missing};

my $wiki_pagina_antes = $wiki_pagina = $wiki_pagina_ref->{'*'}; # Cómo es la página ahora

# Hacemos la actualización
if ($wiki_pagina =~ s/^== Medallero ==.+?(?=^==)/$wiki_medallero/sm) {

    if ($wiki_pagina ne $wiki_pagina_antes) {                   # Si hay realmente un cambio la editamos
         $mw->edit({
             action        => 'edit',
             title         => $wikipedia_resultado,
             basetimestamp => $wiki_pagina_ref->{timestamp},
             text          => $wiki_pagina,
             summary       => 'Actualización automática del medallero',
         })
             or die $mw->{error}->{code} . ': ' . $mw->{error}->{details}
         ;

         say 'Actualizado medallero'  if $DEBUG;
    }
}

## Datos fijos
# Si se limpia esta sección, la próxima ejecución del programa lo rellenará con la lista de los países participantes,
# extraída de la página de los Juegos en Wikipedia.
__DATA__
IRI {{BanderaOL|Irán|IRI|ed=Vancouver 2010}}
BUL {{BanderaOL|Bulgaria|BUL|ed=Vancouver 2010}}
ISR {{BanderaOL|Israel|ISR|ed=Vancouver 2010}}
NZL {{BanderaOL|Nueva Zelanda|NZL|ed=Vancouver 2010}}
BIH {{BanderaOL|Bosnia y Herzegovina|BIH|ed=Vancouver 2010}}
SUI {{BanderaOL|Suiza|SUI|ed=Vancouver 2010}}
NEP {{BanderaOL|Nepal|NEP|ed=Vancouver 2010}}
ROU {{BanderaOL|Rumania|ROU|ed=Vancouver 2010}}
MGL {{BanderaOL|Mongolia|MGL|ed=Vancouver 2010}}
RUS {{BanderaOL|Rusia|RUS|ed=Vancouver 2010}}
UZB {{BanderaOL|Uzbekistán|UZB|ed=Vancouver 2010}}
LAT {{BanderaOL|Letonia|LAT|ed=Vancouver 2010}}
ALB {{BanderaOL|Albania|ALB|ed=Vancouver 2010}}
DEN {{BanderaOL|Dinamarca|DEN|ed=Vancouver 2010}}
BEL {{BanderaOL|Bélgica|BEL|ed=Vancouver 2010}}
TPE {{BanderaOL|China Taipei|TPE|ed=Vancouver 2010}}
ARM {{BanderaOL|Armenia|ARM|ed=Vancouver 2010}}
AUT {{BanderaOL|Austria|AUT|ed=Vancouver 2010}}
PRK {{BanderaOL|Corea del Norte|PRK|ed=Vancouver 2010}}
MKD {{BanderaOL|Macedonia|MKD|ed=Vancouver 2010}}
CAN {{BanderaOL|Canadá|CAN|ed=Vancouver 2010}}
POL {{BanderaOL|Polonia|POL|ed=Vancouver 2010}}
LIE {{BanderaOL|Liechtenstein|LIE|ed=Vancouver 2010}}
COL {{BanderaOL|Colombia|COL|ed=Vancouver 2010}}
SVK {{BanderaOL|Eslovaquia|SVK|ed=Vancouver 2010}}
GRE {{BanderaOL|Grecia|GRE|ed=Vancouver 2010}}
ETH {{BanderaOL|Etiopía|ETH|ed=Vancouver 2010}}
SMR {{BanderaOL|San Marino|SMR|ed=Vancouver 2010}}
BLR {{BanderaOL|Bielorrusia|BLR|ed=Vancouver 2010}}
ITA {{BanderaOL|Italia|ITA|ed=Vancouver 2010}}
LTU {{BanderaOL|Lituania|LTU|ed=Vancouver 2010}}
CHI {{BanderaOL|Chile|CHI|ed=Vancouver 2010}}
FIN {{BanderaOL|Finlandia|FIN|ed=Vancouver 2010}}
TUR {{BanderaOL|Turquía|TUR|ed=Vancouver 2010}}
FRA {{BanderaOL|Francia|FRA|ed=Vancouver 2010}}
BRA {{BanderaOL|Brasil|BRA|ed=Vancouver 2010}}
ISL {{BanderaOL|Islandia|ISL|ed=Vancouver 2010}}
SWE {{BanderaOL|Suecia|SWE|ed=Vancouver 2010}}
HUN {{BanderaOL|Hungría|HUN|ed=Vancouver 2010}}
EST {{BanderaOL|Estonia|EST|ed=Vancouver 2010}}
MEX {{BanderaOL|México|MEX|ed=Vancouver 2010}}
LIB {{BanderaOL|Líbano|LIB|ed=Vancouver 2010}}
IND {{BanderaOL|India|IND|ed=Vancouver 2010}}
CRO {{BanderaOL|Croacia|CRO|ed=Vancouver 2010}}
JPN {{BanderaOL|Japón|JPN|ed=Vancouver 2010}}
POR {{BanderaOL|Portugal|POR|ed=Vancouver 2010}}
TJK {{BanderaOL|Tayikistán|TJK|ed=Vancouver 2010}}
GEO {{BanderaOL|Georgia|GEO|ed=Vancouver 2010}}
CHN {{BanderaOL|China|CHN|ed=Vancouver 2010}}
CYP {{BanderaOL|Chipre|CYP|ed=Vancouver 2010}}
PAK {{BanderaOL|Pakistán|PAK|ed=Vancouver 2010}}
MNE {{BanderaOL|Montenegro|MNE|ed=Vancouver 2010}}
SRB {{BanderaOL|Serbia|SRB|ed=Vancouver 2010}}
NOR {{BanderaOL|Noruega|NOR|ed=Vancouver 2010}}
MAR {{BanderaOL|Marruecos|MAR|ed=Vancouver 2010}}
ESP {{BanderaOL|España|ESP|ed=Vancouver 2010}}
CAY {{BanderaOL|Islas Caimán|CAY|ed=Vancouver 2010}}
BER {{BanderaOL|Bermudas|BER|ed=Vancouver 2010}}
KOR {{BanderaOL|Corea del Sur|KOR|ed=Vancouver 2010}}
AND {{BanderaOL|Andorra|AND|ed=Vancouver 2010}}
MDA {{BanderaOL|Moldavia|MDA|ed=Vancouver 2010}}
SLO {{BanderaOL|Eslovenia|SLO|ed=Vancouver 2010}}
KAZ {{BanderaOL|Kazajistán|KAZ|ed=Vancouver 2010}}
GER {{BanderaOL|Alemania|GER|ed=Vancouver 2010}}
RSA {{BanderaOL|Sudáfrica|RSA|ed=Vancouver 2010}}
MON {{BanderaOL|Mónaco|MON|ed=Vancouver 2010}}
GBR {{BanderaOL|Reino Unido|GBR|ed=Vancouver 2010}}
JAM {{BanderaOL|Jamaica|JAM|ed=Vancouver 2010}}
UKR {{BanderaOL|Ucrania|UKR|ed=Vancouver 2010}}
AUS {{BanderaOL|Australia|AUS|ed=Vancouver 2010}}
PER {{BanderaOL|Perú|PER|ed=Vancouver 2010}}
USA {{BanderaOL|Estados Unidos|USA|ed=Vancouver 2010}}
SEN {{BanderaOL|Senegal|SEN|ed=Vancouver 2010}}
AZE {{BanderaOL|Azerbaiyán|AZE|ed=Vancouver 2010}}
GHA {{BanderaOL|Ghana|GHA|ed=Vancouver 2010}}
ARG {{BanderaOL|Argentina|ARG|ed=Vancouver 2010}}
CZE {{BanderaOL|República Checa|CZE|ed=Vancouver 2010}}
IRL {{BanderaOL|Irlanda|IRL|ed=Vancouver 2010}}
NED {{BanderaOL|Países Bajos|NED|ed=Vancouver 2010}}
ALG {{BanderaOL|Argelia|ALG|ed=Vancouver 2010}}
KGZ {{BanderaOL|Kirguistán|KGZ|ed=Vancouver 2010}}
HKG {{BanderaOL|Hong Kong|HKG|ed=Vancouver 2010}}