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