1 #include <QtNetwork/QNetworkAccessManager>
2 #include <QtNetwork/QNetworkRequest>
9 #include <QApplication>
11 #include "backendkicker.h"
13 const int BackendKicker::INTERVAL_FAST = 180;
15 BackendKicker::BackendKicker(QObject *parent) :
16 MatchDayBackend(parent),
18 m_netaccmgr(new QNetworkAccessManager(this)),
19 m_initialUpdateDone(false)
21 QSettings settings(qApp->organizationName(), qApp->applicationName());
23 connect(m_netaccmgr, SIGNAL(finished(QNetworkReply*)),
24 this, SLOT(dlndFinished(QNetworkReply*)));
26 connect(&m_updateTimer, SIGNAL(timeout()),
27 this, SLOT(update()));
29 m_updateTimer.setSingleShot(true);
31 this->selectLeague(settings.value("League", "1. Bundesliga").toString());
34 Match* BackendKicker::getMatch(QString hometeam, QString awayteam, QDateTime date)
36 QListIterator<Match*> iter(m_matchlist);
39 while (iter.hasNext()) {
41 if (match->awayTeam() == awayteam &&
42 match->homeTeam() == hometeam) {
47 match = new Match(hometeam, awayteam, date, this);
48 m_matchlist.append(match);
49 emit matchAdded(match);
54 QList<Match*> BackendKicker::matchList()
59 static QDateTime parseDate(QString datehtml)
61 static QDateTime lastParsedDate;
65 int month, day, hour, minute;
67 //qDebug() << "parseDate in: " << datehtml;
69 tokens = datehtml.split(QRegExp("[>.&;:<\"]"), QString::SkipEmptyParts);
70 date = QDate::currentDate();
73 if (tokens.count() < 6) {
74 return lastParsedDate;
77 month = (tokens.at(2)).toInt();
78 day = (tokens.at(1)).toInt();
79 hour = (tokens.at(4)).toInt();
80 minute = (tokens.at(5)).toInt();
82 lastParsedDate = QDateTime(QDate(date.year(), month, day),
85 return lastParsedDate;
88 static QString parseTeam(QString teamhtml)
92 //qDebug() << "parseTeam in: " << teamhtml;
94 teamhtml.truncate(teamhtml.indexOf("</a>"));
95 team = teamhtml.mid(teamhtml.lastIndexOf(">") + 1);
97 //qDebug() << "parseTeam out: " << team;
101 void BackendKicker::parseScore(Match* match, QString scorehtml)
105 //qDebug() << "parseScore in: " << scorehtml;
106 tokens = scorehtml.split(QRegExp("[>&();:<]"), QString::SkipEmptyParts);
107 //qDebug() << tokens;
109 if (tokens.count() == 7) {
110 // no extra color tag -> either not started, halftime or finished
111 if (tokens.at(4) == "-") {
112 // no first half results -> match not started yet
113 match->setState(Match::NotStarted, m_initialUpdateDone);
114 } else if (tokens.at(1) == "-") {
115 // second half has not been started but there are first
116 // half results -> currently half time
117 match->setScore(tokens.at(4).toInt(), tokens.at(5).toInt(),
118 m_initialUpdateDone);
119 match->setState(Match::HalfTime, m_initialUpdateDone);
121 // no color tag and no "-" -> game is finished
122 match->setScore(tokens.at(1).toInt(), tokens.at(2).toInt(),
123 m_initialUpdateDone);
124 match->setState(Match::Finished, m_initialUpdateDone);
127 // there is a color tag which means that either first
128 // half or second half are currently running
129 if (tokens.at(4).contains("color")) {
130 // first half score marked red -> first half running
131 match->setScore(tokens.at(5).toInt(), tokens.at(6).toInt(),
132 m_initialUpdateDone);
133 match->setState(Match::FirstHalf, m_initialUpdateDone);
134 } else if (tokens.at(1).contains("color")) {
135 // second half score marked res -> second half running
136 match->setState(Match::SecondHalf, m_initialUpdateDone);
137 match->setScore(tokens.at(2).toInt(), tokens.at(3).toInt(),
138 m_initialUpdateDone);
142 qDebug() << "match state: " << match->state();
143 qDebug() << "match home: " << match->homeScore();
144 qDebug() << "match away: " << match->awayScore();
145 qDebug() << "notify: " << m_initialUpdateDone;
148 void BackendKicker::parsePage (QString htmlstr)
150 QStringList rawmatches;
151 QString hometeam, awayteam, tmp;
159 //qDebug() << "parsePage in: " << htmlstr;
161 rx.setPattern("<td class=\"first\">(.*)<td class=\"aligncenter last\">");
163 while ((pos = rx.indexIn(htmlstr, pos)) != -1) {
165 rawmatches.append(htmlstr.mid(pos, rx.matchedLength()));
166 //qDebug() << "MATCH " << count << ":" << htmlstr.mid(pos, rx.matchedLength()) << "\n\n";
167 pos += rx.matchedLength();
170 rx.setPattern("<td.*>(.*)</td>");
172 QStringList::iterator i;
173 for (i = rawmatches.begin(); i != rawmatches.end(); ++i) {
176 while ((pos = rx.indexIn(*i, pos)) != -1) {
178 tmp = (*i).mid(pos, rx.matchedLength());
179 pos += rx.matchedLength();
182 date = parseDate(tmp);
185 hometeam = parseTeam(tmp);
188 awayteam = parseTeam(tmp);
189 match = getMatch(hometeam, awayteam, date);
192 parseScore(match, tmp);
201 bool BackendKicker::selectLeague(QString league)
203 bool leagueIsSupported = true;
205 if (league == "1. Bundesliga") {
206 m_URL = "http://www.kicker.de/news/fussball/bundesliga/spieltag/1-bundesliga/2010-11/spieltag.html";
207 } else if (league == "2. Bundesliga") {
208 m_URL = "http://www.kicker.de/news/fussball/bundesliga/spieltag/2-bundesliga/2010-11/spieltag.html";
209 } else if (league == "tipp3 Bundesliga") {
210 m_URL = "http://www.kicker.de/news/fussball/intligen/oesterreich/tipp3-bundesliga/2010-11/spieltag.html";
212 leagueIsSupported = false;
216 m_initialUpdateDone = false;
217 this->m_matchlist.clear();
220 return leagueIsSupported;
223 void BackendKicker::update()
225 emit updateStarted();
227 qDebug() << "Start Update with URL: " << m_URL;
228 m_netaccmgr->get(QNetworkRequest(QUrl(m_URL)));
231 void BackendKicker::dlndFinished(QNetworkReply *reply)
234 int secstonextupdate;
236 if (reply->error() != QNetworkReply::NoError) {
237 qWarning() << "Download failed with error: " << reply->error();
239 rawdata = reply->readAll();
243 secstonextupdate = secsToNextGame();
244 if ((secstonextupdate == -1) ||
245 (secstonextupdate > 6 * 3600)) {
246 // all games finished for this matchday
247 secstonextupdate = 6 * 3600;
248 } else if (secstonextupdate < INTERVAL_FAST) {
249 secstonextupdate = INTERVAL_FAST;
251 m_updateTimer.start(secstonextupdate * 1000);
253 emit updateFinished(reply->error());
254 m_initialUpdateDone = true;
255 qDebug() << "Update finished, next update in: " << secstonextupdate << "seconds.";
258 int BackendKicker::secsToNextGame()
260 QListIterator<Match*> iter(m_matchlist);
263 int secstonextgame = -1;
265 while (iter.hasNext()) {
267 if (match->state() == Match::FirstHalf ||
268 match->state() == Match::SecondHalf ||
269 match->state() == Match::HalfTime) {
272 return secstonextgame;
274 } else if (match->state() == Match::NotStarted) {
275 secstogame = QDateTime::currentDateTime().secsTo(match->date());
276 if (secstonextgame == -1) {
277 secstonextgame = secstogame;
278 } else if (secstogame < secstonextgame) {
279 secstonextgame = secstogame;
284 return secstonextgame;