Git Repositories

Deux plugins, l'un est très lent mais complet, l'autre rapide mais sans la date de... master
authorCyrille Pontvieux <cyrille.pontvieux@april-waf.com>
Tue, 7 Jan 2014 16:11:50 +0000 (17:11 +0100)
committerCyrille Pontvieux <cyrille.pontvieux@april-waf.com>
Tue, 7 Jan 2014 16:11:50 +0000 (17:11 +0100)
GCtrictrac2013.pm [new file with mode: 0644]
GCtrictrac2013withrelease.pm [new file with mode: 0644]

diff --git a/GCtrictrac2013.pm b/GCtrictrac2013.pm
new file mode 100644 (file)
index 0000000..76ef33f
--- /dev/null
@@ -0,0 +1,305 @@
+package GCPlugins::GCboardgames::GCtrictrac2013;
+
+###################################################
+#
+#  Copyright 2013 Cyrille Pontvieux
+#
+#  This file is part of GCstar.
+#
+#  GCstar is free software; you can redistribute it and/or modify
+#  it under the terms of the GNU General Public License as published by
+#  the Free Software Foundation; either version 2 of the License, or
+#  (at your option) any later version.
+#
+#  GCstar is distributed in the hope that it will be useful,
+#  but WITHOUT ANY WARRANTY; without even the implied warranty of
+#  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+#  GNU General Public License for more details.
+#
+#  You should have received a copy of the GNU General Public License
+#  along with GCstar; if not, write to the Free Software
+#  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
+#
+###################################################
+
+use strict;
+use Encode;
+use LWP::Simple;
+
+use GCPlugins::GCboardgames::GCboardgamesCommon;
+
+{
+  package GCPlugins::GCboardgames::GCPlugintrictrac2013;
+  use base qw(GCPlugins::GCboardgames::GCboardgamesPluginsBase);
+
+  # start of a html tag
+  sub start {
+    my ($self, $tagname, $attr, $attrseq, $origtext) = @_;
+    $self->{inside}->{$tagname}++;
+    if ($self->{parsingEnded}) {
+      return;
+    }
+    if ($self->{parsingList}) {
+      if (($tagname eq "div") && ($attr->{class} eq "boardgame")) {
+        $self->{inBoardgameItem} = 1
+      } elsif (($self->{inBoardgameItem} == 1) && ($tagname eq "a")) {
+        $self->{itemIdx}++;
+        $self->{itemsList}[$self->{itemIdx}]->{url} = $attr->{href};
+        $self->{itemsList}[$self->{itemIdx}]->{name} = $attr->{title};
+      }
+    } else {
+      if (($tagname eq "img") && ($attr->{class} =~ /img-boardgame-250-/)) {
+        $self->{curInfo}->{boxpic} = $attr->{src};
+      } elsif (($tagname eq "span") && ($attr->{class} eq "fn")) {
+        $self->{inName} = 1;
+      } elsif (($self->{inExts} == 0) && ($tagname eq "span") && ($attr->{class} eq "row-header-title label-row-title")) {
+        $self->{inExts} = 1;
+      } elsif (($self->{inExts} == 2) && ($tagname eq "div") && ($attr->{class} eq "boardgame_box infos")) {
+        $self->{inExts} = 3;
+      } elsif (($self->{inExts} == 3) && ($tagname eq "a")) {
+        $self->{curInfo}->{expandedby} .= $attr->{title} . ',';
+        $self->{inExts} = 2;
+      } elsif (($tagname eq "div") && ($attr->{class} eq "core")) {
+        $self->{inExts} = -1;
+      } elsif ($self->{inExtOf} && ($tagname eq "a")) {
+        $self->{curInfo}->{expansionfor} = $attr->{title};
+        $self->{inExtOf} = 0;
+      } elsif (($self->{inMecha} == 1) && ($tagname eq "th")) {
+        $self->{inMecha} = 2;
+      } elsif (($self->{inThemes} == 1) && ($tagname eq "th")) {
+        $self->{inThemes} = 2;
+      } elsif ((not $self->{inTH}) && ($tagname eq "th")) {
+        $self->{inTH} = 1;
+      } elsif (($self->{inAuteur} || $self->{inAnnee} || $self->{inIllu} || $self->{inEditeur}) && (not $self->{inA}) && ($tagname eq "a")) {
+        $self->{inA} = 1;
+      } elsif (($self->{inNbJoueurs} || $self->{inAge}) && (not $self->{inSpan}) && ($tagname eq "span")) {
+        $self->{inSpan} = 1;
+      } elsif (($tagname eq "div") && ($attr->{class} =~ /cke-content/)) {
+        $self->{inDesc} = 1;
+      } elsif (($tagname eq "p") && ($self->{inDesc} == 1)) {
+        $self->{inDesc} = 2;
+      } elsif (($tagname eq "br") && ($self->{inDesc} == 2)) {
+        $self->{curInfo}->{description} .= "\n";
+      } elsif (($tagname eq "div") and ($attr->{id} eq "repertory_row_boxes_table_1")) {
+        $self->{inMecha} = 1;
+      } elsif (($tagname eq "div") and ($attr->{id} eq "repertory_row_boxes_table_2")) {
+        $self->{inMecha} = 0;
+        $self->{inThemes} = 1;
+      } elsif (($tagname eq "div") and ($attr->{id} =~ /opinion_row_boxes_list/)) {
+        $self->{inThemes} = 0;
+      }
+    }
+  }
+
+  # end of a html tag
+  sub end {
+    my ($self, $tagname) = @_;    
+    $self->{inside}->{$tagname}--;
+    if (($self->{inBoardgameItem} == 1) && ($tagname eq "a")) {
+      $self->{inBoardgameItem} = 0
+    }
+    if ($self->{inName}) {
+      $self->{inName} = 0;
+    }
+    if ($self->{inTH} && ($tagname eq "th")) {
+      $self->{inTH} = 0;
+      if ($self->{inMecha} == 2) {
+        $self->{inMecha} = 1;
+      } elsif ($self->{inThemes} == 2) {
+        $self->{inThemes} = 1;
+      }
+    }
+    if ($self->{inA} && ($tagname eq "a")) {
+      $self->{inA} = 0;
+    }
+    if ($self->{inSpan} && ($tagname eq "span")) {
+      $self->{inSpan} = 0;
+    }
+    if (($self->{inDesc} == 2) && ($tagname eq "p")) {
+      $self->{curInfo}->{description} .= "\n\n";
+    }
+    if (($self->{inDesc} == 2) && ($tagname eq "div")) {
+      $self->{inDesc} = 0;
+    }
+    if ($tagname eq "html") {
+      $self->{curInfo}->{designedby} =~ s/, $//;
+      $self->{curInfo}->{illustratedby} =~ s/, $//;
+      $self->{curInfo}->{mechanics} =~ s/, $//;
+      $self->{curInfo}->{category} =~ s/, $//;
+      $self->{curInfo}->{name} =~ s/^[ \t\r\n]+//m;
+      $self->{curInfo}->{name} =~ s/[ \t\r\n]+$//m;
+      $self->{curInfo}->{designedby} =~ s/^[ \t\r\n]+//m;
+      $self->{curInfo}->{designedby} =~ s/[ \t\r\n]+$//m;
+      $self->{curInfo}->{released} =~ s/^[ \t\r\n]+//m;
+      $self->{curInfo}->{released} =~ s/[ \t\r\n]+$//m;
+      $self->{curInfo}->{illustratedby} =~ s/^[ \t\r\n]+//m;
+      $self->{curInfo}->{illustratedby} =~ s/[ \t\r\n]+$//m;
+      $self->{curInfo}->{publishedby} =~ s/^[ \t\r\n]+//m;
+      $self->{curInfo}->{publishedby} =~ s/[ \t\r\n]+$//m;
+      $self->{curInfo}->{players} =~ s/^[ \t\r\n]+//m;
+      $self->{curInfo}->{players} =~ s/[ \t\r\n]+$//m;
+      $self->{curInfo}->{suggestedage} =~ s/^[ \t\r\n]+//m;
+      $self->{curInfo}->{suggestedage} =~ s/[ \t\r\n]+$//m;
+      $self->{curInfo}->{playingtime} =~ s/^[ \t\r\n]+//m;
+      $self->{curInfo}->{playingtime} =~ s/[ \t\r\n]+$//m;
+      $self->{curInfo}->{description} =~ s/^[ \t\r\n]+//m;
+      $self->{curInfo}->{description} =~ s/[ \t\r\n]+$//m;
+      $self->{curInfo}->{mechanics} =~ s/^[ \t\r\n]+//m;
+      $self->{curInfo}->{mechanics} =~ s/[ \t\r\n]+$//m;
+      $self->{curInfo}->{category} =~ s/^[ \t\r\n]+//m;
+      $self->{curInfo}->{category} =~ s/[ \t\r\n]+$//m;
+    }
+  }
+
+  # html text node
+  sub text {
+    my ($self, $origtext) = @_;
+    return if (length($origtext) < 2);
+    $origtext =~ s/&#34;/"/g;
+    $origtext =~ s/&#179;/3/g;
+    $origtext =~ s/\n//g;
+    $origtext =~ s/^[ \t\n]+//;
+    $origtext =~ s/[ \t\n]+$//;
+    my $textutf8 = Encode::encode("UTF-8", $origtext);
+    return if ($self->{parsingEnded});
+    if ($self->{parsingList}) {
+    } else {
+      if ($self->{inName}) {
+        $self->{curInfo}->{name} = $origtext;
+      }
+      if (($self->{inExts} == 1) && ($textutf8 eq "Extensions")) {
+        $self->{inExts} = 2;
+      }
+      if ($textutf8 eq "Ce jeu est une extension de") {
+        $self->{inExtOf} = 1;
+      }
+      if ($self->{inTH} && not ($self->{inA} || $self->{inSpan})) {
+        if ($textutf8 eq "Auteur") {
+          $self->{inAuteur} = 1;
+        } elsif ($textutf8 eq "Année de publication") {
+          $self->{inAnnee} = 1;
+        } elsif ($textutf8 eq "Illustrateur") {
+          $self->{inIllu} = 1;
+        } elsif ($textutf8 eq "Editeur") {
+          $self->{inEditeur} = 1;
+        } elsif ($textutf8 eq "Nombre de joueurs") {
+          $self->{inNbJoueurs} = 1;
+        } elsif ($textutf8 eq "Age") {
+          $self->{inAge} = 1;
+        } elsif ($textutf8 eq "Durée") {
+          $self->{inDuree} = 1;
+        }
+      } elsif ($self->{inA} or $self->{inSpan}) {
+        if ($self->{inAuteur}) {
+          $self->{curInfo}->{designedby} .= $origtext . ", ";
+          $self->{inAuteur} = 0;
+        }
+        if ($self->{inAnnee}) {
+          $self->{curInfo}->{released} = $origtext;
+          $self->{inAnnee} = 0;
+        }
+        if ($self->{inIllu}) {
+          $self->{curInfo}->{illustratedby} .= $origtext . ", ";
+          $self->{inIllu} = 0;
+        }
+        if ($self->{inEditeur}) {
+          $self->{curInfo}->{publishedby} = $origtext;
+          $self->{inEditeur} = 0;
+        }
+        if ($self->{inNbJoueurs}) {
+          $self->{curInfo}->{players} = $origtext;
+          $self->{inNbJoueurs} = 0;
+        }
+        if ($self->{inAge}) {
+          $self->{curInfo}->{suggestedage} = $origtext;
+          $self->{inAge} = 0;
+        }
+      } elsif ($self->{inDuree} and length($origtext) > 1) { # This one is different because TricTrac did not put the length in a span tag -_-
+        $self->{curInfo}->{playingtime} = $origtext;
+        $self->{inDuree} = 0;
+      }
+      if ($self->{inDesc} == 2) {
+        $self->{curInfo}->{description} .= $origtext;
+      }
+      if ($self->{inMecha} == 2) {
+        $self->{curInfo}->{mechanics} .= $origtext . ", ";
+        $self->{inMecha} = 1;
+      }
+      if ($self->{inThemes} == 2) {
+        $self->{curInfo}->{category} .= $origtext . ", ";
+        $self->{inThemes} = 1;
+      }
+    }
+  }
+
+  sub new {
+    my $proto = shift;
+    my $class = ref($proto) || $proto;
+    my $self  = $class->SUPER::new();
+    bless ($self, $class);
+    $self->{hasField} = {
+      name => 1,
+      released => 1,
+    };
+    $self->{isBoardgame} = 0;
+    $self->{curName} = undef;
+    $self->{curUrl} = undef;
+    $self->{inBoardgameItem} = 0;
+    $self->{inName} = 0;
+    $self->{inExts} = 0;
+    $self->{inExtOf} = 0;
+    $self->{inTH} = 0;
+    $self->{inA} = 0;
+    $self->{inSpan} = 0;
+    $self->{inAnnee} = 0;
+    $self->{inIllu} = 0;
+    $self->{inEditeur} = 0;
+    $self->{inNbJoueurs} = 0;
+    $self->{inAge} = 0;
+    $self->{inDuree} = 0;
+    $self->{inDesc} = 0;
+    $self->{inMecha} = 0;
+    $self->{inThemes} = 0;
+    return $self;
+  }
+
+  sub preProcess {
+    my ($self, $html) = @_;
+    $self->{parsingEnded} = 0;
+    $html =~ s/"&#34;/'"/g;
+    $html =~ s/&#34;"/"'/g;
+    $html =~ s|\x{92}|'|gi;
+    $html =~ s|&#146;|'|gi;
+    $html =~ s|&#149;|*|gi;
+    return $html;
+  }
+
+  sub getSearchUrl {
+    my ($self, $word) = @_;
+    return "http://trictrac.net/recherche?entities=boardgame&query=$word";
+  }
+  
+  sub getItemUrl {
+    my ($self, $url) = @_;
+    return $url if $url =~ /^http:/;
+    if ($url =~ /^\//) {
+      return "http://trictrac.net".$url;
+    } else {
+      return "http://trictrac.net/".$url;
+    }
+  }
+
+  sub getName {
+    return "Tric Trac 2013";
+  }
+  
+  sub getAuthor {
+    return 'Cyrille Pontvieux';
+  }
+  
+  sub getLang {
+    return 'FR';
+  }
+}
+
+1;
diff --git a/GCtrictrac2013withrelease.pm b/GCtrictrac2013withrelease.pm
new file mode 100644 (file)
index 0000000..aa9d26b
--- /dev/null
@@ -0,0 +1,313 @@
+package GCPlugins::GCboardgames::GCtrictrac2013withrelease;
+
+###################################################
+#
+#  Copyright 2013 Cyrille Pontvieux
+#
+#  This file is part of GCstar.
+#
+#  GCstar is free software; you can redistribute it and/or modify
+#  it under the terms of the GNU General Public License as published by
+#  the Free Software Foundation; either version 2 of the License, or
+#  (at your option) any later version.
+#
+#  GCstar is distributed in the hope that it will be useful,
+#  but WITHOUT ANY WARRANTY; without even the implied warranty of
+#  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+#  GNU General Public License for more details.
+#
+#  You should have received a copy of the GNU General Public License
+#  along with GCstar; if not, write to the Free Software
+#  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
+#
+###################################################
+
+use strict;
+use Encode;
+use LWP::Simple;
+
+use GCPlugins::GCboardgames::GCboardgamesCommon;
+
+{
+  package GCPlugins::GCboardgames::GCPlugintrictrac2013withrelease;
+  use base qw(GCPlugins::GCboardgames::GCboardgamesPluginsBase);
+
+  # start of a html tag
+  sub start {
+    my ($self, $tagname, $attr, $attrseq, $origtext) = @_;
+    $self->{inside}->{$tagname}++;
+    if ($self->{parsingEnded}) {
+      return;
+    }
+    if ($self->{parsingList}) {
+      if (($tagname eq "div") && ($attr->{class} eq "boardgame")) {
+        $self->{inBoardgameItem} = 1
+      } elsif (($self->{inBoardgameItem} == 1) && ($tagname eq "a")) {
+        $self->{itemIdx}++;
+        $self->{itemsList}[$self->{itemIdx}]->{url} = $attr->{href};
+        $self->{itemsList}[$self->{itemIdx}]->{name} = $attr->{title};
+        # This is super slow, but Tric-Trac does not show anymore the release year on the result page.
+        my $url = "http://trictrac.net" . $attr->{href};
+        my $content = $self->loadPage($url);
+        my $year = "";
+        if ($content =~ m,.*/jeu-de-societe/les-jeux-de-l-annee/([0-9]+)/.*,) {
+          $year = $1;
+        }
+        $self->{itemsList}[$self->{itemIdx}]->{released} = $year;
+      }
+    } else {
+      if (($tagname eq "img") && ($attr->{class} =~ /img-boardgame-250-/)) {
+        $self->{curInfo}->{boxpic} = $attr->{src};
+      } elsif (($tagname eq "span") && ($attr->{class} eq "fn")) {
+        $self->{inName} = 1;
+      } elsif (($self->{inExts} == 0) && ($tagname eq "span") && ($attr->{class} eq "row-header-title label-row-title")) {
+        $self->{inExts} = 1;
+      } elsif (($self->{inExts} == 2) && ($tagname eq "div") && ($attr->{class} eq "boardgame_box infos")) {
+        $self->{inExts} = 3;
+      } elsif (($self->{inExts} == 3) && ($tagname eq "a")) {
+        $self->{curInfo}->{expandedby} .= $attr->{title} . ',';
+        $self->{inExts} = 2;
+      } elsif (($tagname eq "div") && ($attr->{class} eq "core")) {
+        $self->{inExts} = -1;
+      } elsif ($self->{inExtOf} && ($tagname eq "a")) {
+        $self->{curInfo}->{expansionfor} = $attr->{title};
+        $self->{inExtOf} = 0;
+      } elsif (($self->{inMecha} == 1) && ($tagname eq "th")) {
+        $self->{inMecha} = 2;
+      } elsif (($self->{inThemes} == 1) && ($tagname eq "th")) {
+        $self->{inThemes} = 2;
+      } elsif ((not $self->{inTH}) && ($tagname eq "th")) {
+        $self->{inTH} = 1;
+      } elsif (($self->{inAuteur} || $self->{inAnnee} || $self->{inIllu} || $self->{inEditeur}) && (not $self->{inA}) && ($tagname eq "a")) {
+        $self->{inA} = 1;
+      } elsif (($self->{inNbJoueurs} || $self->{inAge}) && (not $self->{inSpan}) && ($tagname eq "span")) {
+        $self->{inSpan} = 1;
+      } elsif (($tagname eq "div") && ($attr->{class} =~ /cke-content/)) {
+        $self->{inDesc} = 1;
+      } elsif (($tagname eq "p") && ($self->{inDesc} == 1)) {
+        $self->{inDesc} = 2;
+      } elsif (($tagname eq "br") && ($self->{inDesc} == 2)) {
+        $self->{curInfo}->{description} .= "\n";
+      } elsif (($tagname eq "div") and ($attr->{id} eq "repertory_row_boxes_table_1")) {
+        $self->{inMecha} = 1;
+      } elsif (($tagname eq "div") and ($attr->{id} eq "repertory_row_boxes_table_2")) {
+        $self->{inMecha} = 0;
+        $self->{inThemes} = 1;
+      } elsif (($tagname eq "div") and ($attr->{id} =~ /opinion_row_boxes_list/)) {
+        $self->{inThemes} = 0;
+      }
+    }
+  }
+
+  # end of a html tag
+  sub end {
+    my ($self, $tagname) = @_;    
+    $self->{inside}->{$tagname}--;
+    if (($self->{inBoardgameItem} == 1) && ($tagname eq "a")) {
+      $self->{inBoardgameItem} = 0
+    }
+    if ($self->{inName}) {
+      $self->{inName} = 0;
+    }
+    if ($self->{inTH} && ($tagname eq "th")) {
+      $self->{inTH} = 0;
+      if ($self->{inMecha} == 2) {
+        $self->{inMecha} = 1;
+      } elsif ($self->{inThemes} == 2) {
+        $self->{inThemes} = 1;
+      }
+    }
+    if ($self->{inA} && ($tagname eq "a")) {
+      $self->{inA} = 0;
+    }
+    if ($self->{inSpan} && ($tagname eq "span")) {
+      $self->{inSpan} = 0;
+    }
+    if (($self->{inDesc} == 2) && ($tagname eq "p")) {
+      $self->{curInfo}->{description} .= "\n\n";
+    }
+    if (($self->{inDesc} == 2) && ($tagname eq "div")) {
+      $self->{inDesc} = 0;
+    }
+    if ($tagname eq "html") {
+      $self->{curInfo}->{designedby} =~ s/, $//;
+      $self->{curInfo}->{illustratedby} =~ s/, $//;
+      $self->{curInfo}->{mechanics} =~ s/, $//;
+      $self->{curInfo}->{category} =~ s/, $//;
+      $self->{curInfo}->{name} =~ s/^[ \t\r\n]+//m;
+      $self->{curInfo}->{name} =~ s/[ \t\r\n]+$//m;
+      $self->{curInfo}->{designedby} =~ s/^[ \t\r\n]+//m;
+      $self->{curInfo}->{designedby} =~ s/[ \t\r\n]+$//m;
+      $self->{curInfo}->{released} =~ s/^[ \t\r\n]+//m;
+      $self->{curInfo}->{released} =~ s/[ \t\r\n]+$//m;
+      $self->{curInfo}->{illustratedby} =~ s/^[ \t\r\n]+//m;
+      $self->{curInfo}->{illustratedby} =~ s/[ \t\r\n]+$//m;
+      $self->{curInfo}->{publishedby} =~ s/^[ \t\r\n]+//m;
+      $self->{curInfo}->{publishedby} =~ s/[ \t\r\n]+$//m;
+      $self->{curInfo}->{players} =~ s/^[ \t\r\n]+//m;
+      $self->{curInfo}->{players} =~ s/[ \t\r\n]+$//m;
+      $self->{curInfo}->{suggestedage} =~ s/^[ \t\r\n]+//m;
+      $self->{curInfo}->{suggestedage} =~ s/[ \t\r\n]+$//m;
+      $self->{curInfo}->{playingtime} =~ s/^[ \t\r\n]+//m;
+      $self->{curInfo}->{playingtime} =~ s/[ \t\r\n]+$//m;
+      $self->{curInfo}->{description} =~ s/^[ \t\r\n]+//m;
+      $self->{curInfo}->{description} =~ s/[ \t\r\n]+$//m;
+      $self->{curInfo}->{mechanics} =~ s/^[ \t\r\n]+//m;
+      $self->{curInfo}->{mechanics} =~ s/[ \t\r\n]+$//m;
+      $self->{curInfo}->{category} =~ s/^[ \t\r\n]+//m;
+      $self->{curInfo}->{category} =~ s/[ \t\r\n]+$//m;
+    }
+  }
+
+  # html text node
+  sub text {
+    my ($self, $origtext) = @_;
+    return if (length($origtext) < 2);
+    $origtext =~ s/&#34;/"/g;
+    $origtext =~ s/&#179;/3/g;
+    $origtext =~ s/\n//g;
+    $origtext =~ s/^[ \t\n]+//;
+    $origtext =~ s/[ \t\n]+$//;
+    my $textutf8 = Encode::encode("UTF-8", $origtext);
+    return if ($self->{parsingEnded});
+    if ($self->{parsingList}) {
+    } else {
+      if ($self->{inName}) {
+        $self->{curInfo}->{name} = $origtext;
+      }
+      if (($self->{inExts} == 1) && ($textutf8 eq "Extensions")) {
+        $self->{inExts} = 2;
+      }
+      if ($textutf8 eq "Ce jeu est une extension de") {
+        $self->{inExtOf} = 1;
+      }
+      if ($self->{inTH} && not ($self->{inA} || $self->{inSpan})) {
+        if ($textutf8 eq "Auteur") {
+          $self->{inAuteur} = 1;
+        } elsif ($textutf8 eq "Année de publication") {
+          $self->{inAnnee} = 1;
+        } elsif ($textutf8 eq "Illustrateur") {
+          $self->{inIllu} = 1;
+        } elsif ($textutf8 eq "Editeur") {
+          $self->{inEditeur} = 1;
+        } elsif ($textutf8 eq "Nombre de joueurs") {
+          $self->{inNbJoueurs} = 1;
+        } elsif ($textutf8 eq "Age") {
+          $self->{inAge} = 1;
+        } elsif ($textutf8 eq "Durée") {
+          $self->{inDuree} = 1;
+        }
+      } elsif ($self->{inA} or $self->{inSpan}) {
+        if ($self->{inAuteur}) {
+          $self->{curInfo}->{designedby} .= $origtext . ", ";
+          $self->{inAuteur} = 0;
+        }
+        if ($self->{inAnnee}) {
+          $self->{curInfo}->{released} = $origtext;
+          $self->{inAnnee} = 0;
+        }
+        if ($self->{inIllu}) {
+          $self->{curInfo}->{illustratedby} .= $origtext . ", ";
+          $self->{inIllu} = 0;
+        }
+        if ($self->{inEditeur}) {
+          $self->{curInfo}->{publishedby} = $origtext;
+          $self->{inEditeur} = 0;
+        }
+        if ($self->{inNbJoueurs}) {
+          $self->{curInfo}->{players} = $origtext;
+          $self->{inNbJoueurs} = 0;
+        }
+        if ($self->{inAge}) {
+          $self->{curInfo}->{suggestedage} = $origtext;
+          $self->{inAge} = 0;
+        }
+      } elsif ($self->{inDuree} and length($origtext) > 1) { # This one is different because TricTrac did not put the length in a span tag -_-
+        $self->{curInfo}->{playingtime} = $origtext;
+        $self->{inDuree} = 0;
+      }
+      if ($self->{inDesc} == 2) {
+        $self->{curInfo}->{description} .= $origtext;
+      }
+      if ($self->{inMecha} == 2) {
+        $self->{curInfo}->{mechanics} .= $origtext . ", ";
+        $self->{inMecha} = 1;
+      }
+      if ($self->{inThemes} == 2) {
+        $self->{curInfo}->{category} .= $origtext . ", ";
+        $self->{inThemes} = 1;
+      }
+    }
+  }
+
+  sub new {
+    my $proto = shift;
+    my $class = ref($proto) || $proto;
+    my $self  = $class->SUPER::new();
+    bless ($self, $class);
+    $self->{hasField} = {
+      name => 1,
+      released => 1,
+    };
+    $self->{isBoardgame} = 0;
+    $self->{curName} = undef;
+    $self->{curUrl} = undef;
+    $self->{inBoardgameItem} = 0;
+    $self->{inName} = 0;
+    $self->{inExts} = 0;
+    $self->{inExtOf} = 0;
+    $self->{inTH} = 0;
+    $self->{inA} = 0;
+    $self->{inSpan} = 0;
+    $self->{inAnnee} = 0;
+    $self->{inIllu} = 0;
+    $self->{inEditeur} = 0;
+    $self->{inNbJoueurs} = 0;
+    $self->{inAge} = 0;
+    $self->{inDuree} = 0;
+    $self->{inDesc} = 0;
+    $self->{inMecha} = 0;
+    $self->{inThemes} = 0;
+    return $self;
+  }
+
+  sub preProcess {
+    my ($self, $html) = @_;
+    $self->{parsingEnded} = 0;
+    $html =~ s/"&#34;/'"/g;
+    $html =~ s/&#34;"/"'/g;
+    $html =~ s|\x{92}|'|gi;
+    $html =~ s|&#146;|'|gi;
+    $html =~ s|&#149;|*|gi;
+    return $html;
+  }
+
+  sub getSearchUrl {
+    my ($self, $word) = @_;
+    return "http://trictrac.net/recherche?entities=boardgame&query=$word";
+  }
+  
+  sub getItemUrl {
+    my ($self, $url) = @_;
+    return $url if $url =~ /^http:/;
+    if ($url =~ /^\//) {
+      return "http://trictrac.net".$url;
+    } else {
+      return "http://trictrac.net/".$url;
+    }
+  }
+
+  sub getName {
+    return "Tric Trac 2013 avec sortie (lent)";
+  }
+  
+  sub getAuthor {
+    return 'Cyrille Pontvieux';
+  }
+  
+  sub getLang {
+    return 'FR';
+  }
+}
+
+1;