1 #include <QtNetwork/QNetworkAccessManager>
2 #include <QtNetwork/QNetworkRequest>
9 #include <QApplication>
11 #include <qjson/qobjecthelper.h>
13 #include "backendkicker.h"
15 const int BackendKicker::INTERVAL_FAST = 180;
17 BackendKicker::BackendKicker(QObject *parent) :
18 MatchDayBackend(parent),
20 m_netaccmgr(new QNetworkAccessManager(this)),
21 m_initialUpdateDone(false)
23 QSettings settings(qApp->organizationName(), qApp->applicationName());
25 connect(m_netaccmgr, SIGNAL(finished(QNetworkReply*)),
26 this, SLOT(dlndFinished(QNetworkReply*)));
28 connect(&m_updateTimer, SIGNAL(timeout()),
29 this, SLOT(update()));
31 m_updateTimer.setSingleShot(true);
33 this->selectLeague(settings.value("League", "1. Bundesliga").toString());
36 Match* BackendKicker::getOrAddMatch(QString hometeam, QString awayteam, QDateTime date)
38 QListIterator<Match*> iter(m_matchlist);
41 while (iter.hasNext()) {
43 if (match->awayTeam() == awayteam &&
44 match->homeTeam() == hometeam) {
49 match = new Match(hometeam, awayteam, date, this);
50 m_matchlist.append(match);
51 emit matchAdded(match);
56 int BackendKicker::matchCount()
58 return m_matchlist.count();
61 Match* BackendKicker::getMatch(int index)
65 match = m_matchlist.at(index);
67 qWarning() << "No match at index " << index;
73 QVariant BackendKicker::serializableData()
75 QVariantMap matchvariantmap;
77 QListIterator<Match*> iter(m_matchlist);
80 while (iter.hasNext()) {
83 matchvariantmap = QJson::QObjectHelper::qobject2qvariant(match);
84 list.append(QVariant(matchvariantmap));
87 return matchvariantmap;
90 static QDateTime parseDate(QString datehtml)
92 static QDateTime lastParsedDate;
96 int month, day, hour, minute;
98 //qDebug() << "parseDate in: " << datehtml;
100 tokens = datehtml.split(QRegExp("[>.&;:<\"]"), QString::SkipEmptyParts);
101 date = QDate::currentDate();
103 //qDebug() << tokens;
104 if (tokens.count() < 6) {
105 return lastParsedDate;
108 month = (tokens.at(2)).toInt();
109 day = (tokens.at(1)).toInt();
110 hour = (tokens.at(4)).toInt();
111 minute = (tokens.at(5)).toInt();
113 lastParsedDate = QDateTime(QDate(date.year(), month, day),
114 QTime(hour, minute));
116 return lastParsedDate;
119 static QString parseTeam(QString teamhtml)
123 //qDebug() << "parseTeam in: " << teamhtml;
125 teamhtml.truncate(teamhtml.indexOf("</a>"));
126 team = teamhtml.mid(teamhtml.lastIndexOf(">") + 1);
128 //qDebug() << "parseTeam out: " << team;
132 void BackendKicker::parseScore(Match* match, QString scorehtml)
136 //qDebug() << "parseScore in: " << scorehtml;
137 tokens = scorehtml.split(QRegExp("[>&();:<]"), QString::SkipEmptyParts);
138 //qDebug() << tokens;
140 if (tokens.count() == 7) {
141 // no extra color tag -> either not started, halftime or finished
142 if (tokens.at(4) == "-") {
143 // no first half results -> match not started yet
144 match->setState(Match::NotStarted, m_initialUpdateDone);
145 } else if (tokens.at(1) == "-") {
146 // second half has not been started but there are first
147 // half results -> currently half time
148 match->setScore(tokens.at(4).toInt(), tokens.at(5).toInt(),
149 m_initialUpdateDone);
150 match->setState(Match::HalfTime, m_initialUpdateDone);
152 // no color tag and no "-" -> game is finished
153 match->setScore(tokens.at(1).toInt(), tokens.at(2).toInt(),
154 m_initialUpdateDone);
155 match->setState(Match::Finished, m_initialUpdateDone);
158 // there is a color tag which means that either first
159 // half or second half are currently running
160 if (tokens.at(4).contains("color")) {
161 // first half score marked red -> first half running
162 match->setScore(tokens.at(5).toInt(), tokens.at(6).toInt(),
163 m_initialUpdateDone);
164 match->setState(Match::FirstHalf, m_initialUpdateDone);
165 } else if (tokens.at(1).contains("color")) {
166 // second half score marked res -> second half running
167 match->setState(Match::SecondHalf, m_initialUpdateDone);
168 match->setScore(tokens.at(2).toInt(), tokens.at(3).toInt(),
169 m_initialUpdateDone);
173 qDebug() << "match state: " << match->state();
174 qDebug() << "match home: " << match->homeScore();
175 qDebug() << "match away: " << match->awayScore();
176 qDebug() << "notify: " << m_initialUpdateDone;
179 void BackendKicker::parsePage (QString htmlstr)
181 QStringList rawmatches;
182 QString hometeam, awayteam, tmp;
190 //qDebug() << "parsePage in: " << htmlstr;
192 rx.setPattern("<td class=\"first\">(.*)<td class=\"aligncenter last\">");
194 while ((pos = rx.indexIn(htmlstr, pos)) != -1) {
196 rawmatches.append(htmlstr.mid(pos, rx.matchedLength()));
197 //qDebug() << "MATCH " << count << ":" << htmlstr.mid(pos, rx.matchedLength()) << "\n\n";
198 pos += rx.matchedLength();
201 rx.setPattern("<td.*>(.*)</td>");
203 QStringList::iterator i;
204 for (i = rawmatches.begin(); i != rawmatches.end(); ++i) {
207 while ((pos = rx.indexIn(*i, pos)) != -1) {
209 tmp = (*i).mid(pos, rx.matchedLength());
210 pos += rx.matchedLength();
213 date = parseDate(tmp);
216 hometeam = parseTeam(tmp);
219 awayteam = parseTeam(tmp);
220 match = getOrAddMatch(hometeam, awayteam, date);
223 parseScore(match, tmp);
232 bool BackendKicker::selectLeague(QString league)
234 bool leagueIsSupported = true;
236 if (league == "1. Bundesliga") {
237 m_URL = "http://www.kicker.de/news/fussball/bundesliga/spieltag/1-bundesliga/2010-11/spieltag.html";
238 } else if (league == "2. Bundesliga") {
239 m_URL = "http://www.kicker.de/news/fussball/bundesliga/spieltag/2-bundesliga/2010-11/spieltag.html";
240 } else if (league == "tipp3 Bundesliga") {
241 m_URL = "http://www.kicker.de/news/fussball/intligen/oesterreich/tipp3-bundesliga/2010-11/spieltag.html";
243 leagueIsSupported = false;
247 m_initialUpdateDone = false;
248 this->m_matchlist.clear();
251 return leagueIsSupported;
254 void BackendKicker::update()
256 emit updateStarted();
258 qDebug() << "Start Update with URL: " << m_URL;
259 m_netaccmgr->get(QNetworkRequest(QUrl(m_URL)));
262 void BackendKicker::dlndFinished(QNetworkReply *reply)
265 int secstonextupdate;
267 if (reply->error() != QNetworkReply::NoError) {
268 qWarning() << "Download failed with error: " << reply->error();
270 rawdata = reply->readAll();
274 secstonextupdate = secsToNextGame();
275 if ((secstonextupdate == -1) ||
276 (secstonextupdate > 6 * 3600)) {
277 // all games finished for this matchday
278 secstonextupdate = 6 * 3600;
279 } else if (secstonextupdate < INTERVAL_FAST) {
280 secstonextupdate = INTERVAL_FAST;
282 m_updateTimer.start(secstonextupdate * 1000);
284 emit updateFinished(reply->error());
285 m_initialUpdateDone = true;
286 qDebug() << "Update finished, next update in: " << secstonextupdate << "seconds.";
289 int BackendKicker::secsToNextGame()
291 QListIterator<Match*> iter(m_matchlist);
294 int secstonextgame = -1;
296 while (iter.hasNext()) {
298 if (match->state() == Match::FirstHalf ||
299 match->state() == Match::SecondHalf ||
300 match->state() == Match::HalfTime) {
303 return secstonextgame;
305 } else if (match->state() == Match::NotStarted) {
306 secstogame = QDateTime::currentDateTime().secsTo(match->date());
307 if (secstonextgame == -1) {
308 secstonextgame = secstogame;
309 } else if (secstogame < secstonextgame) {
310 secstonextgame = secstogame;
315 return secstonextgame;