]> git.sesse.net Git - pkanalytics/blob - events.cpp
Add some offense events, now working-ish.
[pkanalytics] / events.cpp
1 #include <algorithm>
2 #include <string>
3 #include <map>
4 #include <vector>
5 #include <optional>
6 #include <sqlite3.h>
7 #include "events.h"
8
9 using namespace std;
10
11 string format_timestamp(uint64_t pos);
12
13 QVariant EventsModel::headerData(int section, Qt::Orientation orientation, int role) const
14 {
15         if (role != Qt::DisplayRole) {
16                 return QVariant();
17         }
18         if (orientation == Qt::Horizontal) {
19                 if (section == 0) {
20                         return "Time";
21                 } else if (section == 1) {
22                         return "Player";
23                 } else {
24                         return "Type";
25                 }
26         } else {
27                 return "";
28         }
29 }
30
31 QVariant EventsModel::data(const QModelIndex &index, int role) const
32 {
33         if (role != Qt::DisplayRole) {
34                 return QVariant();
35         }
36         refresh_if_needed();
37         if (index.column() == 0) {
38                 return QString::fromUtf8(format_timestamp(events[index.row()].t));
39         } else if (index.column() == 1) {
40                 optional<int> player_id = events[index.row()].player_id;
41                 if (player_id) {
42                         const Player &p = players[*player_id];
43                         return QString::fromUtf8(p.name + " (" + p.number + ")");
44                 } else {
45                         return QVariant();
46                 }
47         } else if (index.column() == 2) {
48                 return QString::fromUtf8(events[index.row()].type);
49         }
50         return QVariant();
51 }
52
53 void EventsModel::refresh_if_needed() const
54 {
55         if (!stale) {
56                 return;
57         }
58
59         players.clear();
60         events.clear();
61         stale = false;
62
63         // Read the players.
64         sqlite3_stmt *stmt;
65         int ret = sqlite3_prepare_v2(db, "SELECT player, number, name FROM player", -1, &stmt, 0);
66         if (ret != SQLITE_OK) {
67                 fprintf(stderr, "SELECT prepare: %s\n", sqlite3_errmsg(db));
68                 abort();
69         }
70         for ( ;; ) {
71                 ret = sqlite3_step(stmt);
72                 if (ret == SQLITE_ROW) {
73                         Player p;
74                         p.player_id = sqlite3_column_int(stmt, 0);
75                         p.number = (const char *)sqlite3_column_text(stmt, 1);
76                         p.name = (const char *) sqlite3_column_text(stmt, 2);
77                         players[p.player_id] = std::move(p);
78                 } else if (ret == SQLITE_DONE) {
79                         break;
80                 } else {
81                         fprintf(stderr, "SELECT step: %s\n", sqlite3_errmsg(db));
82                         abort();
83                 }
84         }
85         ret = sqlite3_finalize(stmt);
86         if (ret != SQLITE_OK) {
87                 fprintf(stderr, "SELECT finalize: %s\n", sqlite3_errmsg(db));
88                 abort();
89         }
90
91         // Read the events.
92         ret = sqlite3_prepare_v2(db, "SELECT t, player, type FROM event", -1, &stmt, 0);
93         if (ret != SQLITE_OK) {
94                 fprintf(stderr, "SELECT prepare: %s\n", sqlite3_errmsg(db));
95                 abort();
96         }
97         for ( ;; ) {
98                 ret = sqlite3_step(stmt);
99                 if (ret == SQLITE_ROW) {
100                         Event e;
101                         e.t = sqlite3_column_int(stmt, 0);
102                         e.player_id = sqlite3_column_int(stmt, 1);
103                         e.type = (const char *)sqlite3_column_text(stmt, 2);
104                         events.push_back(std::move(e));
105                 } else if (ret == SQLITE_DONE) {
106                         break;
107                 } else {
108                         fprintf(stderr, "SELECT step: %s\n", sqlite3_errmsg(db));
109                         abort();
110                 }
111         }
112         ret = sqlite3_finalize(stmt);
113         if (ret != SQLITE_OK) {
114                 fprintf(stderr, "SELECT finalize: %s\n", sqlite3_errmsg(db));
115                 abort();
116         }
117
118         // TODO what if data changes externally?
119         //emit dataChanged(QModelIndex(
120 }
121
122 int EventsModel::insert_event(uint64_t t, int player_id)
123 {
124         auto it = lower_bound(events.begin(), events.end(), t,
125                 [](const Event &e, uint64_t t) { return e.t < t; });
126         int pos = distance(events.begin(), it);
127         beginInsertRows(QModelIndex(), pos, pos + 1);
128
129         Event e;
130         e.t = t;
131         e.player_id = player_id;
132         e.type = "unknown";
133         events.insert(events.begin() + pos, e);
134
135         endInsertRows();
136
137         // FIXME sqlite
138
139         return pos;
140 }
141
142 void EventsModel::set_event_type(unsigned pos, const string &type)
143 {
144         events[pos].type = type;
145         emit dataChanged(createIndex(pos, 0), createIndex(pos, 2));
146
147         // FIXME sqlite
148 }