- Add non-volatile settings for hcp, home club, etc.
[scorecard] / src / stat-model.cpp
1 /*
2  * Copyright (C) 2009 Sakari Poussa
3  *
4  * This program is free software: you can redistribute it and/or modify
5  * it under the terms of the GNU General Public License as published by
6  * the Free Software Foundation, version 2.
7  */
8
9 #include <QVariant>
10
11 #include "stat-model.h"
12
13 StatModel::StatModel(QList<Club *> &cList, QList<Score *> &sList) : clubList(cList), scoreList(sList)
14 {
15   update();
16 }
17
18 int StatModel::rowCount(const QModelIndex & parent) const
19 {
20   Q_UNUSED(parent);
21   return ROWS;
22 }
23
24 int StatModel::columnCount(const QModelIndex & parent) const
25 {
26   Q_UNUSED(parent);
27   return COLS;
28 }
29
30 QVariant StatModel::data(const QModelIndex & index, int role) const
31 {
32   if (!index.isValid())
33     return QVariant();
34
35   int row = index.row();
36   int col = index.column();
37
38   if (col >= stat.size())
39     return QVariant();
40     
41   //
42   // ALIGNMENT
43   //
44   if (role == Qt::TextAlignmentRole ) {
45     return Qt::AlignCenter;
46   }
47
48   //
49   // NUMBERS
50   //
51   if (role == Qt::DisplayRole) {
52     switch (row) {
53     case ROW_ROUNDS: 
54       return stat.at(col)->rounds();
55     case ROW_AVERAGE: 
56       return stat.at(col)->average();
57     case ROW_MIN: 
58       return stat.at(col)->min();
59     case ROW_MAX: 
60       return stat.at(col)->max();
61     case ROW_BIRDIE: 
62       return stat.at(col)->birdies();
63     case ROW_PAR: 
64       return stat.at(col)->pars();
65     case ROW_BOGEY: 
66       return stat.at(col)->bogeys();
67     case ROW_MORE:
68       return stat.at(col)->more();
69     }
70   }
71   return QVariant();
72 }
73
74 QVariant StatModel::headerData(int section, Qt::Orientation orientation, int role) const
75 {
76   // Only vertical header -- horizontal is hidden
77   if (role != Qt::DisplayRole)
78     return QVariant();
79
80   if (orientation == Qt::Horizontal) {
81     // TODO: check when no or less data than cols
82     // HERE CRASH
83
84     if (section < stat.size())
85       return stat.at(section)->year();
86   }
87
88   if (orientation == Qt::Vertical) {
89     switch(section) {
90     case ROW_ROUNDS: 
91       return QString("Rounds");
92     case ROW_AVERAGE: 
93       return QString("Average");
94     case ROW_MIN: 
95       return QString("Best");
96     case ROW_MAX: 
97       return QString("Worst");
98     case ROW_BIRDIE: 
99       return QString("Birdies");
100     case ROW_PAR: 
101       return QString("Pars");
102     case ROW_BOGEY: 
103       return QString("Bogeys");
104     case ROW_MORE:
105       return QString("Double+");
106     }
107   }
108
109   return QVariant();
110 }
111
112 // TODO: dup code from table-model.cpp
113 Course *StatModel::findCourse(const QString &clubName, 
114                               const QString &courseName)
115 {
116   QListIterator<Club *> i(clubList);
117   Club *c;
118
119   while (i.hasNext()) {
120     c = i.next();
121     if (c->getName() == clubName) {
122       return c->getCourse(courseName);
123     }
124   }
125   return 0;
126 }
127
128 void StatModel::update(void)
129 {
130   QListIterator<Score *> iScore(scoreList);
131   QMultiMap<QString, Score *> yearMap;
132
133   // Create multi map with years as keys, scores as values
134   while (iScore.hasNext()) {
135     Score *score = iScore.next();
136     QString year = score->getDate().split("-").at(0);
137     yearMap.insert(year, score);
138   }
139   // Create uniq list of years
140   QList<QString> yearList = yearMap.uniqueKeys();
141
142   // For each year collect the statistics
143   QListIterator<QString> iYear(yearList);
144   while (iYear.hasNext()) {
145     QString year = iYear.next();
146
147     StatItem *item = new StatItem;
148     item->setYear(year);
149
150     QList<Score *> scoresPerYear = yearMap.values(year);
151     QListIterator<Score *> iScoresPerYear(scoresPerYear);
152     
153     item->setRounds(scoresPerYear.count());
154
155     // for each year, add score
156     int sum = 0;
157     int min = 200;
158     int max = 0;
159     int pars = 0;
160     int birdies = 0;
161     int bogeys = 0;
162     int more = 0;
163     while (iScoresPerYear.hasNext()) {
164       Score *s = iScoresPerYear.next();
165       int tot = s->getTotal(Total).toInt();
166       sum += tot;
167
168       if (tot > max)
169         max = tot;
170
171       if (tot < min)
172         min = tot;
173
174       Course *c = findCourse(s->getClubName(), s->getCourseName());
175
176       for (int i = 0; i < 18; i++) {
177         int par = c->getPar(i).toInt();
178         int shots = s->getScore(i).toInt();
179         
180         if (shots == (par - 1))
181           birdies++;
182         else if (shots == par)
183           pars++;
184         else if (shots == (par + 1))
185           bogeys++;
186         else if (shots >= (par + 2))
187           more++;
188       }
189     }
190     item->setBirdies(birdies);
191     item->setPars(pars);
192     item->setBogeys(bogeys);
193     item->setMore(more);
194
195     int avg = sum / scoresPerYear.count();
196     item->setAverage(avg);
197     item->setMin(min);
198     item->setMax(max);
199
200     stat << item;
201   }
202 }