Average journey time for each weekday.
Average number of cyclists passed for each weekday.
src/imageprovider.cpp \
src/graph.cpp \
src/statsmodel.cpp \
- src/stats.cpp
+ src/stats.cpp \
+ src/statsweekdayave.cpp \
+ src/statsweekdaycongestion.cpp
DISTFILES += qml/harbour-pedalo.qml \
qml/cover/CoverPage.qml \
src/imageprovider.h \
src/graph.h \
src/statsmodel.h \
- src/stats.h
+ src/stats.h \
+ src/statsweekdayave.h \
+ src/statsweekdaycongestion.h
height: (isPortrait ? statsPage.height / 2.0 : statsPage.height) - Theme.paddingLarge
itemWidth: width
clip: true
+ anchors.left: isPortrait ? statsColumn.left : statsColumn.right
+ anchors.leftMargin: 0
y: (isPortrait ? (statsPage.height / 2.0) : statsColumn.y)
+ onModelChanged: {
+ console.log("Model changed");
+ model.updateAll();
+ }
+
model: statsmodel
delegate: Rectangle {
width: graphsView.itemWidth
SectionHeader {
id: sectionHeaderItem
- text: "item " + index
+ text: title
}
Graph {
id: graph
- width: parent.width - 2 * Theme.horizontalPageMargin
+ width: parent.width - Theme.horizontalPageMargin
anchors.top: sectionHeaderItem.bottom
height: (isPortrait ? (statsPage.height / 2.0) - Theme.paddingLarge : statsPage.height - Theme.paddingLarge - headerItem.height) - sectionHeaderItem.height
- anchors.horizontalCenter: parent.horizontalCenter
+ anchors.left: parent.left
model: values
labelsx: labels
//labelsy: ["0%", "10%", "20%", "30%", "40%", "50%", "60%", "70%", "80%", "90%", "100%"]
- unitsy: "%"
+ unitsy: units
primary: Theme.primaryColor
secondary: Theme.highlightColor
highlight: Theme.highlightColor
- miny: 0.0
- maxy: 1.0
- stepy: 0.1
+ miny: minval
+ maxy: maxval
+ stepy: step
gap: 0.1
fontsize: Theme.fontSizeExtraSmall
/*
#include "settings.h"
#include "imageprovider.h"
#include "graph.h"
+#include "statsweekdayave.h"
+#include "statsweekdaycongestion.h"
#include "harbour-pedalo.h"
Settings::getInstance().loadSettings();
StatsModel statsmodel;
- Stats stats;
- QList<float> data{0.1, 0.1, 0.2};
- QStringList labels{"A", "B", "C"};
- stats.setValues(data);
- stats.setLabels(labels);
- statsmodel.addStats(stats);
-
- data = QList<float>{0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.5};
- labels = QStringList{"M", "T", "W", "Th", "F", "S", "Su"};
- stats.setValues(data);
- stats.setLabels(labels);
- statsmodel.addStats(stats);
+ StatsWeekdayAve statsweekdayave(&journeys);
+ statsmodel.addStats(statsweekdayave);
+
+ StatsWeekdayCongestion statsweekdaycongestion(&journeys);
+ statsmodel.addStats(statsweekdaycongestion);
QFile file;
file.setFileName(Settings::getConfigDir() + "/journeys.csv");
#include "stats.h"
-Stats::Stats()
+Stats::Stats() :
+ title("Empty graph"),
+ units("%"),
+ minval(0.0),
+ maxval(1.0),
+ step(0.1)
{
}
+void Stats::update() {
+ // Do nothing
+}
+
+QString Stats::getTitle() const {
+ return title;
+}
+
QStringList Stats::getLabels() const {
return labels;
}
return values;
}
+QString Stats::getUnits() const {
+ return units;
+}
+
+float Stats::getMinVal() const {
+ return minval;
+}
+
+float Stats::getMaxVal() const {
+ return maxval;
+}
+
+float Stats::getStep() const {
+ return step;
+}
+
+void Stats::setTitle(QString &value) {
+ title = value;
+}
+
void Stats::setLabels(QStringList &value) {
labels = value;
}
values = value;
}
+void Stats::setUnits(QString &value) {
+ units = value;
+}
+
+void Stats::setMinVal(float value) {
+ minval = value;
+}
+
+void Stats::setMaxVal(float value) {
+ maxval = value;
+}
+
+void Stats::setStep(float value) {
+ step = value;
+}
public:
Stats();
- QStringList getLabels() const;
- QList<float> getValues() const;
+ virtual void update();
- void setLabels(QStringList &value);
- void setValues(QList<float> &value);
+ virtual QString getTitle() const;
+ virtual QStringList getLabels() const;
+ virtual QList<float> getValues() const;
+ virtual QString getUnits() const;
+ virtual float getMinVal() const;
+ virtual float getMaxVal() const;
+ virtual float getStep() const;
-private:
+ virtual void setTitle(QString &value);
+ virtual void setLabels(QStringList &value);
+ virtual void setValues(QList<float> &value);
+ virtual void setUnits(QString &value);
+ virtual void setMinVal(float value);
+ virtual void setMaxVal(float value);
+ virtual void setStep(float value);
+
+protected:
+ QString title;
QStringList labels;
QList<float> values;
+ QString units;
+ float minval;
+ float maxval;
+ float step;
};
#endif // STATS_H
#include "statsmodel.h"
StatsModel::StatsModel(QObject *parent) : QAbstractListModel(parent) {
+ roles[TitleRole] = "title";
roles[ValuesRole] = "values";
roles[LabelsRole] = "labels";
+ roles[UnitsRole] = "units";
+ roles[MinValRole] = "minval";
+ roles[MaxValRole] = "maxval";
+ roles[StepRole] = "step";
}
-void StatsModel::addStats(const Stats &stats) {
- this->stats.append(stats);
+void StatsModel::addStats(Stats &stats) {
+ this->stats.append(&stats);
}
QHash<int, QByteArray> StatsModel::roleNames() const {
if (index.row() < 0 || index.row() > stats.count())
return QVariant();
- const Stats &stat = stats[index.row()];
- if (role == ValuesRole)
- return QVariant::fromValue<QList<float>>(stat.getValues());
+ const Stats *stat = stats[index.row()];
+ if (role == TitleRole)
+ return stat->getTitle();
+ else if (role == ValuesRole)
+ return QVariant::fromValue<QList<float>>(stat->getValues());
else if (role == LabelsRole)
- return stat.getLabels();
+ return stat->getLabels();
+ else if (role == UnitsRole)
+ return stat->getUnits();
+ else if (role == MinValRole)
+ return stat->getMinVal();
+ else if (role == MaxValRole)
+ return stat->getMaxVal();
+ else if (role == StepRole)
+ return stat->getStep();
return QVariant();
}
stats.clear();
}
+void StatsModel::updateAll() {
+ foreach (Stats * stat, stats) {
+ stat->update();
+ }
+}
Q_OBJECT
public:
enum StatsRoles {
- ValuesRole = Qt::UserRole + 1,
- LabelsRole
+ TitleRole = Qt::UserRole + 1,
+ ValuesRole,
+ LabelsRole,
+ UnitsRole,
+ MinValRole,
+ MaxValRole,
+ StepRole
};
QHash<int, QByteArray> roleNames() const;
StatsModel(QObject *parent = 0);
- void addStats(const Stats &stats);
+ void addStats(Stats &stats);
int rowCount(const QModelIndex & parent = QModelIndex()) const;
void clear();
+ Q_INVOKABLE void updateAll();
+
private:
QHash<int, QByteArray> roles;
- QList<Stats> stats;
+ QList<Stats *> stats;
};
#endif // STATSMODEL_H
--- /dev/null
+#include <QDebug>
+
+#include "statsweekdayave.h"
+
+StatsWeekdayAve::StatsWeekdayAve(JourneyModel * journeys) :
+ journeys(journeys)
+{
+ title = "Average journey time (mins)";
+ units = "";
+ labels = QStringList{"M", "T", "W", "Th", "F", "S", "Su"};
+}
+
+void StatsWeekdayAve::update() {
+ double duration[7];
+ unsigned int count[7];
+ int pos;
+
+ qDebug() << "Calculating values";
+ values.clear();
+
+ for (pos = 0; pos < 7; pos++) {
+ duration[pos] = 0.0;
+ count[pos] = 0u;
+ }
+
+ foreach (Journey const &journey, journeys->getData()) {
+ QDate date = journey.getStartDate();
+ int dayofweek = date.dayOfWeek() - 1;
+ if (dayofweek >= 0) {
+ duration[dayofweek] += journey.getDuration();
+ count[dayofweek]++;
+ }
+ }
+
+ maxval = 0.0;
+ for (pos = 0; pos < 7; pos++) {
+ float result = 0.0f;
+ if (count[pos] > 0) {
+ result = ((duration[pos] / 60.0) / (double)count[pos]);
+ }
+ if (result > maxval) {
+ maxval = result;
+ }
+ values << result;
+ }
+
+ step = qRound(maxval / 5.0);
+
+ qDebug() << "Calculated values";
+}
+
+
--- /dev/null
+#ifndef STATSWEEKDAYAVE_H
+#define STATSWEEKDAYAVE_H
+
+#include "journeymodel.h"
+
+#include "stats.h"
+
+class StatsWeekdayAve : public Stats
+{
+public:
+ StatsWeekdayAve(JourneyModel * journeys);
+
+ void update();
+private:
+ JourneyModel * journeys;
+};
+
+#endif // STATSWEEKDAYAVE_H
--- /dev/null
+#include <QDebug>
+
+#include "statsweekdaycongestion.h"
+
+StatsWeekdayCongestion::StatsWeekdayCongestion(JourneyModel * journeys) :
+ journeys(journeys)
+{
+ title = "Congested days (cycles passed)";
+ units = "";
+ labels = QStringList{"M", "T", "W", "Th", "F", "S", "Su"};
+}
+
+void StatsWeekdayCongestion::update() {
+ quint32 passed[7];
+ unsigned int count[7];
+ int pos;
+
+ qDebug() << "Calculating values";
+ values.clear();
+
+ for (pos = 0; pos < 7; pos++) {
+ passed[pos] = 0u;
+ count[pos] = 0u;
+ }
+
+ foreach (Journey const &journey, journeys->getData()) {
+ QDate date = journey.getStartDate();
+ int dayofweek = date.dayOfWeek() - 1;
+ if (dayofweek >= 0) {
+ passed[dayofweek] += journey.getOvertook() + journey.getOvertakenBy();
+ count[dayofweek]++;
+ }
+ }
+
+ maxval = 0.0;
+ for (pos = 0; pos < 7; pos++) {
+ float result = 0.0f;
+ if (count[pos] > 0) {
+ result = ((double)passed[pos] / (double)count[pos]);
+ }
+ if (result > maxval) {
+ maxval = result;
+ }
+ values << result;
+ }
+
+ step = qRound(maxval / 5.0);
+
+ qDebug() << "Calculated values";
+}
--- /dev/null
+#ifndef STATSWEEKDAYCONGESTION_H
+#define STATSWEEKDAYCONGESTION_H
+
+#include "journeymodel.h"
+
+#include "stats.h"
+
+class StatsWeekdayCongestion : public Stats
+{
+public:
+ StatsWeekdayCongestion(JourneyModel * journeys);
+
+ void update();
+
+private:
+ JourneyModel * journeys;
+};
+
+#endif // STATSWEEKDAYCONGESTION_H