From 0613ccbba93e2941f5e999f7c9beca972a464eec Mon Sep 17 00:00:00 2001 From: Max Lapan Date: Tue, 9 Mar 2010 14:51:39 +0300 Subject: [PATCH] Traffic information parsing. --- tests/traffic/mainwindow.hpp | 8 +- traffic.cpp | 186 +++++++++++++++++++++++++++++++++++++++++- traffic.hpp | 48 ++++++++++- yandex-traffic-core.pri | 2 +- 4 files changed, 234 insertions(+), 10 deletions(-) diff --git a/tests/traffic/mainwindow.hpp b/tests/traffic/mainwindow.hpp index 4754d0c..b45ffca 100644 --- a/tests/traffic/mainwindow.hpp +++ b/tests/traffic/mainwindow.hpp @@ -21,7 +21,13 @@ protected slots: void trafficUpdated () { - printf ("Traffic data updated\n"); + ExtendedTrafficInfo info; + + printf ("Traffic data updated:\n"); + printf ("ts: %s\n", _traffic.ts ().toString ().toUtf8 ().data ()); + + info = _traffic.lookup_ext ("1"); + printf ("Moscow: %d, %d, %s\n", info.level (), info.tend (), info.hint ().toUtf8 ().data ()); } public: diff --git a/traffic.cpp b/traffic.cpp index 6b29452..033d083 100644 --- a/traffic.cpp +++ b/traffic.cpp @@ -1,20 +1,112 @@ #include +#include + #include "traffic.hpp" // -------------------------------------------------- // TrafficInfo // -------------------------------------------------- -TrafficInfo::TrafficInfo () +TrafficInfo::TrafficInfo (const QDomElement& elem) throw (const QString&) +{ + _valid = false; + _len1 = getFloatNode (elem, "length_1", 0); + _len2 = getFloatNode (elem, "length_2", 0); + _len = getFloatNode (elem, "length", 0); + _ts = getTSNode (elem, "timestamp"); + _isotime = getStringNode (elem, "isotime"); + _localtime = getStringNode (elem, "localtime"); + _valid = true; +} + + +float TrafficInfo::getFloatNode (const QDomElement& elem, const char* node, float def) +{ + QDomElement e; + bool ok; + float val; + + e = elem.firstChildElement (node); + if (e.isNull ()) + return def; + val = e.text ().toFloat (&ok); + if (!ok) + return def; + return val; +} + + +int TrafficInfo::getIntNode (const QDomElement& elem, const char* node, int def) +{ + QDomElement e; + bool ok; + int val; + + e = elem.firstChildElement (node); + if (e.isNull ()) + return def; + val = e.text ().toInt (&ok); + if (!ok) + return def; + return val; +} + + +QString TrafficInfo::getStringNode (const QDomElement& elem, const char* node) throw (const QString&) { + QDomElement e; + QString val; + + e = elem.firstChildElement (node); + if (e.isNull ()) + throw QString (QString::fromAscii (node) + " not found"); + return e.text (); +} + + +QDateTime TrafficInfo::getTSNode (const QDomElement& elem, const char* node) throw (const QString&) +{ + QDomElement e; + bool ok; + uint val; + QDateTime ts; + + e = elem.firstChildElement (node); + if (e.isNull ()) + throw QString (QString::fromAscii (node) + " not found"); + val = e.text ().toUInt (&ok); + if (!ok) + throw QString (QString::fromAscii (node) + " is not a timestamp"); + ts.setTime_t (val); + return ts; } // -------------------------------------------------- // ExtendedTrafficInfo // -------------------------------------------------- -ExtendedTrafficInfo::ExtendedTrafficInfo () +ExtendedTrafficInfo::ExtendedTrafficInfo (const QDomElement& elem) throw (const QString&) + : TrafficInfo (elem) { + QString color; + + setValid (false); + _level_raw = getFloatNode (elem, "level_raw", 0); + _level = getIntNode (elem, "level", 1); + _tend = getIntNode (elem, "tend", 0); + _hint = getStringNode (elem, "hint"); + + color = getStringNode (elem, "icon"); + if (color == "green") + _color = Green; + else if (color == "yellow") + _color = Yellow; + else if (color == "red") + _color = Red; + else + throw "Color is unknown"; + + setValid (true); } @@ -43,7 +135,93 @@ void Traffic::update () void Traffic::fetchDone (const QByteArray& data) { printf ("Got %d bytes of data\n", data.size ()); -// printf ("Data:\n%s\n", data.data ()); - updated (); + // parse data got + if (parse_traffic_data (QString::fromUtf8 (data.data ()))) + updated (); + else + printf ("Parse failed\n"); +} + + +bool Traffic::parse_traffic_data (const QString& xml) +{ + QDomDocument doc; + QDateTime new_ts; + QDomElement e; + QDomNode n; + bool ok; + QString s; + QMap new_info; + QMap new_ext_info; + + if (!doc.setContent (xml)) + return false; + + // get timestamp + e = doc.documentElement (); + if (e.isNull () || e.tagName () != "jams_stat") + return false; + + s = e.attribute ("timestamp"); + if (s.isNull ()) + return false; + + new_ts.setTime_t (s.toUInt (&ok)); + if (!ok) + return false; + + // parse all regions + n = e.firstChild (); + while (!n.isNull ()) { + e = n.toElement (); + if (!e.isNull () && e.tagName () == "region") { + s = e.attribute ("id"); + printf ("Process region %s\n", s.toUtf8 ().data ()); + try { + // Check that it is an extended traffic info + if (!e.firstChildElement ("level").isNull ()) { + ExtendedTrafficInfo info (e); + if (info.valid ()) + new_ext_info[s] = info; + } + else { + TrafficInfo info (e); + if (info.valid ()) + new_info[s] = info; + } + } + catch (const QString& msg) { + printf ("Region %s parse failed: %s\n", s.toUtf8 ().data (), msg.toUtf8 ().data ()); + } + } + n = n.nextSibling (); + } + + _ts = new_ts; + _info = new_info; + _ext_info = new_ext_info; + + return true; } + +TrafficInfo Traffic::lookup (const QString &id) const +{ + QMap::const_iterator it = _info.find (id); + + if (it == _info.end ()) + return TrafficInfo (); + else + return it.value (); +} + + +ExtendedTrafficInfo Traffic::lookup_ext (const QString &id) const +{ + QMap::const_iterator it = _ext_info.find (id); + + if (it == _ext_info.end ()) + return ExtendedTrafficInfo (); + else + return it.value (); +} diff --git a/traffic.hpp b/traffic.hpp index dbbfc56..333fa86 100644 --- a/traffic.hpp +++ b/traffic.hpp @@ -3,6 +3,7 @@ #include #include +#include #include "http_fetcher.hpp" @@ -16,8 +17,26 @@ private: QString _isotime; QString _localtime; + bool _valid; + +protected: + float getFloatNode (const QDomElement& elem, const char* node, float def); + int getIntNode (const QDomElement& elem, const char* node, int def); + QString getStringNode (const QDomElement& elem, const char* node) throw (const QString&); + QDateTime getTSNode (const QDomElement& elem, const char* node) throw (const QString&); + + void setValid (bool new_val) + { _valid = new_val; }; + public: - TrafficInfo (); + TrafficInfo () + : _valid (false) + {}; + + TrafficInfo (const QDomElement& elem) throw (const QString&); + + bool valid () const + { return _valid; }; }; @@ -32,13 +51,26 @@ public: private: float _level_raw; - quint8 _level; + int _level; light_color _color; - quint8 _tend; + int _tend; QString _hint; public: - ExtendedTrafficInfo (); + ExtendedTrafficInfo () + : TrafficInfo () + {}; + + ExtendedTrafficInfo (const QDomElement& elem) throw (const QString&); + + int level () const + { return _level; }; + + int tend () const + { return _tend; }; + + QString hint () const + { return _hint; }; }; @@ -54,6 +86,8 @@ private: HttpFetcher _fetcher; + bool parse_traffic_data (const QString& xml); + private slots: void fetchDone (const QByteArray& data); @@ -64,6 +98,12 @@ public: Traffic (); void update (); + + QDateTime ts () const + { return _ts; }; + + TrafficInfo lookup (const QString &id) const; + ExtendedTrafficInfo lookup_ext (const QString &id) const; }; diff --git a/yandex-traffic-core.pri b/yandex-traffic-core.pri index 08521a2..8fd5d6e 100644 --- a/yandex-traffic-core.pri +++ b/yandex-traffic-core.pri @@ -1,6 +1,6 @@ HEADERS += $$PWD/regions.hpp $$PWD/settings.hpp $$PWD/traffic.hpp $$PWD/http_fetcher.hpp SOURCES += $$PWD/regions.cpp $$PWD/settings.cpp $$PWD/traffic.cpp $$PWD/http_fetcher.cpp -QT += network +QT += network xml INCLUDEPATH += $$PWD \ No newline at end of file -- 1.7.9.5