d2914aa45575c8625a08508a9f9e7178d5e9bb7a
[buliscores] / src / backendkicker.cpp
1 #include <QtNetwork/QNetworkAccessManager>
2 #include <QtNetwork/QNetworkRequest>
3 #include <QUrl>
4 #include <QRegExp>
5 #include <QDebug>
6 #include <QStringList>
7 #include <QDateTime>
8 #include <QSettings>
9 #include <QApplication>
10
11 #include "backendkicker.h"
12
13 BackendKicker::BackendKicker(QObject *parent) :
14     MatchDayBackend(parent)
15 {
16     QSettings settings(qApp->organizationName(), qApp->applicationName());
17     this->selectLeague(settings.value("League", "1. Bundesliga").toString());
18
19     this->update();
20 }
21
22 Match* BackendKicker::getMatch(QString hometeam, QString awayteam, QDateTime date)
23 {
24     QListIterator<Match*> iter(m_matchlist);
25     Match*        match;
26
27     while (iter.hasNext()) {
28         match = iter.next();
29         if (match->awayTeam() == awayteam &&
30             match->homeTeam() == hometeam) {
31             return match;
32         }
33     }
34
35     match = new Match(hometeam, awayteam, date, this);
36     m_matchlist.append(match);
37
38     return match;
39 }
40
41 QList<Match*> BackendKicker::matchList()
42 {
43     return m_matchlist;
44 }
45
46 static QDateTime parseDate(QString datehtml)
47 {
48     static QDateTime    lastParsedDate;
49     QStringList         tokens;
50     QDate               date;
51
52     int month, day, hour, minute;
53
54     //qDebug() << "parseDate in: " << datehtml;
55
56     tokens = datehtml.split(QRegExp("[>.&;:<\"]"), QString::SkipEmptyParts);
57     date = QDate::currentDate();
58
59     qDebug() << tokens;
60     if (tokens.count() < 6) {
61         return lastParsedDate;
62     }
63
64     month  = (tokens.at(2)).toInt();
65     day    = (tokens.at(1)).toInt();
66     hour   = (tokens.at(4)).toInt();
67     minute = (tokens.at(5)).toInt();
68
69     lastParsedDate =  QDateTime(QDate(date.year(), month, day),
70                                 QTime(hour, minute));
71
72     return lastParsedDate;
73 }
74
75 static QString parseTeam(QString teamhtml)
76 {
77     QString team;
78
79     //qDebug() << "parseTeam in: " << teamhtml;
80
81     teamhtml.truncate(teamhtml.indexOf("</a>"));
82     team = teamhtml.mid(teamhtml.lastIndexOf(">") + 1);
83
84     qDebug() << "parseTeam out: " << team;
85     return team;
86 }
87
88 static void parseScore(Match* match, QString scorehtml)
89 {
90     QStringList tokens;
91
92     qDebug() << "parseScore in: " << scorehtml;
93     tokens = scorehtml.split(QRegExp("[>&();:<]"), QString::SkipEmptyParts);
94     qDebug() << tokens;
95
96     if (tokens.count() == 7) {
97         // no extra color tag -> either not started, halftime or finished
98         if (tokens.at(4) == "-") {
99             // no first half results -> match not started yet
100             match->setState(Match::NotStarted);
101         } else if (tokens.at(1) == "-") {
102             // second half has not been started but there are first
103             // half results -> currently half time
104             match->setScore(tokens.at(4).toInt(), tokens.at(5).toInt());
105             match->setState(Match::HalfTime);
106         } else {
107             // no color tag and no "-" -> game is finished
108             match->setScore(tokens.at(1).toInt(), tokens.at(2).toInt());
109             match->setState(Match::Finished);
110         }
111     } else {
112         // there is a color tag which means that either first
113         // half or second half are currently running
114         if (tokens.at(4).contains("color")) {
115             // first half score marked red -> first half running
116             match->setScore(tokens.at(5).toInt(), tokens.at(6).toInt());
117             match->setState(Match::FirstHalf);
118         } else if (tokens.at(1).contains("color")) {
119             // second half score marked res -> second half running
120             match->setState(Match::SecondHalf);
121             match->setScore(tokens.at(2).toInt(), tokens.at(3).toInt());
122         }
123
124     }
125     qDebug() << "match state: " << match->state();
126     qDebug() << "match home: " << match->homeScore();
127     qDebug() << "match away: " << match->awayScore();
128 }
129
130 void BackendKicker::parsePage (QString htmlstr)
131 {
132     QStringList     rawmatches;
133     QString         hometeam, awayteam, tmp;
134     QRegExp         rx;
135     QDateTime       date;
136     Match*          match;
137
138     int             pos     = 0;
139     int             count   = 0;
140
141     //qDebug() << "parsePage in: " << htmlstr;
142
143     rx.setPattern("<td class=\"first\">(.*)<td class=\"aligncenter last\">");
144     rx.setMinimal(true);
145     while ((pos = rx.indexIn(htmlstr, pos)) != -1) {
146          ++count;
147          rawmatches.append(htmlstr.mid(pos, rx.matchedLength()));
148          qDebug() << "MATCH " << count << ":" << htmlstr.mid(pos, rx.matchedLength()) << "\n\n";
149          pos += rx.matchedLength();
150      }
151
152     rx.setPattern("<td.*>(.*)</td>");
153
154     QStringList::iterator i;
155     for (i = rawmatches.begin(); i != rawmatches.end(); ++i) {
156         pos = 0;
157         count = 0;
158         while ((pos = rx.indexIn(*i, pos)) != -1) {
159              ++count;
160              tmp = (*i).mid(pos, rx.matchedLength());
161              pos += rx.matchedLength();
162              switch (count) {
163              case 2: // date
164                  date = parseDate(tmp);
165                  break;
166              case 3: // hometeam
167                  hometeam = parseTeam(tmp);
168                  break;
169              case 5: // awayteam
170                  awayteam = parseTeam(tmp);
171                  match = getMatch(hometeam, awayteam, date);
172                  break;
173              case 6: // scores
174                  parseScore(match, tmp);
175                  break;
176              default:
177                 ;;
178              }
179         }
180     }
181 }
182
183 bool BackendKicker::selectLeague(QString league)
184 {
185     bool leagueIsSupported = true;
186
187     if (league == "1. Bundesliga") {
188         m_URL = "http://www.kicker.de/news/fussball/bundesliga/spieltag/1-bundesliga/2010-11/spieltag.html";
189     } else if (league == "2. Bundesliga") {
190         m_URL = "http://www.kicker.de/news/fussball/bundesliga/spieltag/2-bundesliga/2010-11/spieltag.html";
191     } else if (league == "tipp3 Bundesliga") {
192         m_URL = "http://www.kicker.de/news/fussball/intligen/oesterreich/tipp3-bundesliga/2010-11/spieltag.html";
193     } else {
194         leagueIsSupported = false;
195     }
196
197     // delete last data
198     return leagueIsSupported;
199 }
200
201 void BackendKicker::update()
202 {
203     emit updateStarted();
204
205     //QString URL = "file:///home/david/Projects/git-buliscores/testdata/spieltag.html";
206     QNetworkAccessManager *manager = new QNetworkAccessManager(this);
207     connect(manager, SIGNAL(finished(QNetworkReply*)),
208             this, SLOT(dlndFinished(QNetworkReply*)));
209
210     qDebug() << "URL: " << m_URL;
211     manager->get(QNetworkRequest(QUrl(m_URL)));
212 }
213
214 void BackendKicker::dlndFinished(QNetworkReply *reply)
215 {
216     QString         rawdata;
217
218     if (reply->error() != QNetworkReply::NoError) {
219         // TODO proper user friendly error handling here!
220         qDebug() << "dlnd failed: error: " << reply->error();
221     }
222
223     this->m_matchlist.clear();
224
225     rawdata = reply->readAll();
226     parsePage(rawdata);
227
228     emit matchListChanged();
229 }