1 #include <QtNetwork/QNetworkAccessManager>
2 #include <QtNetwork/QNetworkRequest>
9 #include <QApplication>
11 #include <qjson/qobjecthelper.h>
12 #include <qjson/serializer.h>
14 #include "backendkicker.h"
16 const int BackendKicker::INTERVAL_FAST = 180;
18 BackendKicker::BackendKicker(QObject *parent) :
19 MatchDayBackend(parent),
21 m_netaccmgr(new QNetworkAccessManager(this)),
22 m_initialUpdateDone(false)
24 QSettings settings(qApp->organizationName(), qApp->applicationName());
26 connect(m_netaccmgr, SIGNAL(finished(QNetworkReply*)),
27 this, SLOT(dlndFinished(QNetworkReply*)));
29 connect(&m_updateTimer, SIGNAL(timeout()),
30 this, SLOT(update()));
32 m_updateTimer.setSingleShot(true);
34 this->selectLeague(settings.value("League", "1. Bundesliga").toString());
37 Match* BackendKicker::getOrAddMatch(QString hometeam, QString awayteam, QDateTime date)
39 QListIterator<Match*> iter(m_matchlist);
42 while (iter.hasNext()) {
44 if (match->awayTeam() == awayteam &&
45 match->homeTeam() == hometeam) {
50 match = new Match(hometeam, awayteam, date, this);
51 m_matchlist.append(match);
52 emit matchAdded(match);
57 int BackendKicker::matchCount()
59 return m_matchlist.count();
62 Match* BackendKicker::getMatch(int index)
66 match = m_matchlist.at(index);
68 qWarning() << "No match at index " << index;
74 QVariant BackendKicker::serializableData()
76 QVariantMap matchvariantmap;
78 QListIterator<Match*> iter(m_matchlist);
80 QJson::Serializer serializer;
83 while (iter.hasNext()) {
86 matchvariantmap = QJson::QObjectHelper::qobject2qvariant(match);
87 qDebug() << serializer.serialize(matchvariantmap);
88 list.append(QVariant(matchvariantmap));
91 return matchvariantmap;
94 static QDateTime parseDate(QString datehtml)
96 static QDateTime lastParsedDate;
100 int month, day, hour, minute;
102 //qDebug() << "parseDate in: " << datehtml;
104 tokens = datehtml.split(QRegExp("[>.&;:<\"]"), QString::SkipEmptyParts);
105 date = QDate::currentDate();
107 //qDebug() << tokens;
108 if (tokens.count() < 6) {
109 return lastParsedDate;
112 month = (tokens.at(2)).toInt();
113 day = (tokens.at(1)).toInt();
114 hour = (tokens.at(4)).toInt();
115 minute = (tokens.at(5)).toInt();
117 lastParsedDate = QDateTime(QDate(date.year(), month, day),
118 QTime(hour, minute));
120 return lastParsedDate;
123 static QString parseTeam(QString teamhtml)
127 //qDebug() << "parseTeam in: " << teamhtml;
129 teamhtml.truncate(teamhtml.indexOf("</a>"));
130 team = teamhtml.mid(teamhtml.lastIndexOf(">") + 1);
132 //qDebug() << "parseTeam out: " << team;
136 void BackendKicker::parseScore(Match* match, QString scorehtml)
140 //qDebug() << "parseScore in: " << scorehtml;
141 tokens = scorehtml.split(QRegExp("[>&();:<]"), QString::SkipEmptyParts);
142 //qDebug() << tokens;
144 if (tokens.count() == 7) {
145 // no extra color tag -> either not started, halftime or finished
146 if (tokens.at(4) == "-") {
147 // no first half results -> match not started yet
148 match->setState(Match::NotStarted, m_initialUpdateDone);
149 } else if (tokens.at(1) == "-") {
150 // second half has not been started but there are first
151 // half results -> currently half time
152 match->setScore(tokens.at(4).toInt(), tokens.at(5).toInt(),
153 m_initialUpdateDone);
154 match->setState(Match::HalfTime, m_initialUpdateDone);
156 // no color tag and no "-" -> game is finished
157 match->setScore(tokens.at(1).toInt(), tokens.at(2).toInt(),
158 m_initialUpdateDone);
159 match->setState(Match::Finished, m_initialUpdateDone);
162 // there is a color tag which means that either first
163 // half or second half are currently running
164 if (tokens.at(4).contains("color")) {
165 // first half score marked red -> first half running
166 match->setScore(tokens.at(5).toInt(), tokens.at(6).toInt(),
167 m_initialUpdateDone);
168 match->setState(Match::FirstHalf, m_initialUpdateDone);
169 } else if (tokens.at(1).contains("color")) {
170 // second half score marked res -> second half running
171 match->setState(Match::SecondHalf, m_initialUpdateDone);
172 match->setScore(tokens.at(2).toInt(), tokens.at(3).toInt(),
173 m_initialUpdateDone);
177 qDebug() << "match state: " << match->state();
178 qDebug() << "match home: " << match->homeScore();
179 qDebug() << "match away: " << match->awayScore();
180 qDebug() << "notify: " << m_initialUpdateDone;
183 void BackendKicker::parsePage (QString htmlstr)
185 QStringList rawmatches;
186 QString hometeam, awayteam, tmp;
194 //qDebug() << "parsePage in: " << htmlstr;
196 rx.setPattern("<td class=\"first\">(.*)<td class=\"aligncenter last\">");
198 while ((pos = rx.indexIn(htmlstr, pos)) != -1) {
200 rawmatches.append(htmlstr.mid(pos, rx.matchedLength()));
201 //qDebug() << "MATCH " << count << ":" << htmlstr.mid(pos, rx.matchedLength()) << "\n\n";
202 pos += rx.matchedLength();
205 rx.setPattern("<td.*>(.*)</td>");
207 QStringList::iterator i;
208 for (i = rawmatches.begin(); i != rawmatches.end(); ++i) {
211 while ((pos = rx.indexIn(*i, pos)) != -1) {
213 tmp = (*i).mid(pos, rx.matchedLength());
214 pos += rx.matchedLength();
217 date = parseDate(tmp);
220 hometeam = parseTeam(tmp);
223 awayteam = parseTeam(tmp);
224 match = getOrAddMatch(hometeam, awayteam, date);
227 parseScore(match, tmp);
236 bool BackendKicker::selectLeague(QString league)
238 bool leagueIsSupported = true;
240 if (league == "1. Bundesliga") {
241 m_URL = "http://www.kicker.de/news/fussball/bundesliga/spieltag/1-bundesliga/2010-11/spieltag.html";
242 } else if (league == "2. Bundesliga") {
243 m_URL = "http://www.kicker.de/news/fussball/bundesliga/spieltag/2-bundesliga/2010-11/spieltag.html";
244 } else if (league == "3. Liga") {
245 m_URL = "http://www.kicker.de/news/fussball/3liga/spieltag/3-liga/2010-11/spieltag.html";
246 } else if (league == "tipp3 Bundesliga") {
247 m_URL = "http://www.kicker.de/news/fussball/intligen/oesterreich/tipp3-bundesliga/2010-11/spieltag.html";
249 leagueIsSupported = false;
253 m_initialUpdateDone = false;
254 this->m_matchlist.clear();
257 return leagueIsSupported;
260 void BackendKicker::update()
262 emit updateStarted();
264 qDebug() << "Start Update with URL: " << m_URL;
265 m_netaccmgr->get(QNetworkRequest(QUrl(m_URL)));
268 void BackendKicker::dlndFinished(QNetworkReply *reply)
271 int secstonextupdate;
273 if (reply->error() != QNetworkReply::NoError) {
274 qWarning() << "Download failed with error: " << reply->error();
276 rawdata = reply->readAll();
280 secstonextupdate = secsToNextGame();
281 if ((secstonextupdate == -1) ||
282 (secstonextupdate > 8 * 3600)) {
283 // all games finished for this matchday
284 secstonextupdate = 8 * 3600;
285 } else if (secstonextupdate < INTERVAL_FAST) {
286 secstonextupdate = INTERVAL_FAST;
288 m_updateTimer.start(secstonextupdate * 1000);
290 emit updateFinished(reply->error());
291 m_initialUpdateDone = true;
292 qDebug() << "Update finished, next update in: " << secstonextupdate << "seconds.";
295 int BackendKicker::secsToNextGame()
297 QListIterator<Match*> iter(m_matchlist);
300 int secstonextgame = -1;
302 while (iter.hasNext()) {
304 if (match->state() == Match::FirstHalf ||
305 match->state() == Match::SecondHalf ||
306 match->state() == Match::HalfTime) {
309 return secstonextgame;
311 } else if (match->state() == Match::NotStarted) {
312 secstogame = QDateTime::currentDateTime().secsTo(match->date());
313 if (secstonextgame == -1) {
314 secstonextgame = secstogame;
315 } else if (secstogame < secstonextgame) {
316 secstonextgame = secstogame;
321 return secstonextgame;