]> git.sesse.net Git - pkanalytics/blob - json.cpp
Support filtering passes by thrower and receiver.
[pkanalytics] / json.cpp
1 #include <QJsonArray>
2 #include <QJsonDocument>
3 #include <QJsonObject>
4 #include <sqlite3.h>
5 #include "json.h"
6
7 QJsonArray export_players_to_json(sqlite3 *db)
8 {
9         QJsonArray players;
10
11         sqlite3_stmt *stmt;
12         int ret = sqlite3_prepare_v2(db, "SELECT player, number, name, gender FROM player ORDER BY (number+0), number", -1, &stmt, 0);
13         if (ret != SQLITE_OK) {
14                 fprintf(stderr, "SELECT prepare: %s\n", sqlite3_errmsg(db));
15                 abort();
16         }
17         for ( ;; ) {
18                 ret = sqlite3_step(stmt);
19                 if (ret == SQLITE_ROW) {
20                         QJsonObject p;
21                         p.insert("player_id", sqlite3_column_int(stmt, 0));
22                         p.insert("number", (const char *)sqlite3_column_text(stmt, 1));
23                         p.insert("name", (const char *)sqlite3_column_text(stmt, 2));
24                         p.insert("gender", (const char *)sqlite3_column_text(stmt, 3));
25                         players.push_back(std::move(p));
26                 } else if (ret == SQLITE_DONE) {
27                         break;
28                 } else {
29                         fprintf(stderr, "SELECT step: %s\n", sqlite3_errmsg(db));
30                         abort();
31                 }
32         }
33         ret = sqlite3_finalize(stmt);
34         if (ret != SQLITE_OK) {
35                 fprintf(stderr, "SELECT finalize: %s\n", sqlite3_errmsg(db));
36                 abort();
37         }
38
39         return players;
40 }
41
42 QJsonArray export_formations_to_json(sqlite3 *db)
43 {
44         QJsonArray formations;
45
46         sqlite3_stmt *stmt;
47         int ret = sqlite3_prepare_v2(db, "SELECT formation, offense, name FROM formation ORDER BY name", -1, &stmt, 0);
48         if (ret != SQLITE_OK) {
49                 fprintf(stderr, "SELECT prepare: %s\n", sqlite3_errmsg(db));
50                 abort();
51         }
52         for ( ;; ) {
53                 ret = sqlite3_step(stmt);
54                 if (ret == SQLITE_ROW) {
55                         QJsonObject f;
56                         f.insert("formation_id", sqlite3_column_int(stmt, 0));
57                         f.insert("offense", bool(sqlite3_column_int(stmt, 1)));
58                         f.insert("name", (const char *)sqlite3_column_text(stmt, 2));
59                         formations.push_back(std::move(f));
60                 } else if (ret == SQLITE_DONE) {
61                         break;
62                 } else {
63                         fprintf(stderr, "SELECT step: %s\n", sqlite3_errmsg(db));
64                         abort();
65                 }
66         }
67         ret = sqlite3_finalize(stmt);
68         if (ret != SQLITE_OK) {
69                 fprintf(stderr, "SELECT finalize: %s\n", sqlite3_errmsg(db));
70                 abort();
71         }
72
73         return formations;
74 }
75
76 QJsonArray export_matches_to_json(sqlite3 *db)
77 {
78         QJsonArray matches;
79
80         // Load the events, splitting them into matches as we go.
81         std::map<int, QJsonArray *> events_per_match;
82         sqlite3_stmt *stmt;
83         int ret = sqlite3_prepare_v2(db, "SELECT match, t, player, formation, type FROM event ORDER BY t", -1, &stmt, 0);
84         if (ret != SQLITE_OK) {
85                 fprintf(stderr, "SELECT prepare: %s\n", sqlite3_errmsg(db));
86                 abort();
87         }
88         for ( ;; ) {
89                 ret = sqlite3_step(stmt);
90                 if (ret == SQLITE_ROW) {
91                         int match = sqlite3_column_int(stmt, 0);
92                         if (events_per_match.count(match) == 0) {
93                                 events_per_match[match] = new QJsonArray;
94                         }
95
96                         QJsonObject e;
97                         e.insert("t", sqlite3_column_int(stmt, 1));
98                         if (sqlite3_column_type(stmt, 2) == SQLITE_INTEGER) {
99                                 e.insert("player", sqlite3_column_int(stmt, 2));
100                         } else {
101                                 e.insert("player", QJsonValue());  // null
102                         }
103                         if (sqlite3_column_type(stmt, 3) == SQLITE_INTEGER) {
104                                 e.insert("formation", sqlite3_column_int(stmt, 3));
105                         } else {
106                                 e.insert("formation", QJsonValue());  // null
107                         }
108                         e.insert("type", (const char *)sqlite3_column_text(stmt, 4));
109                         events_per_match[match]->push_back(std::move(e));
110                 } else if (ret == SQLITE_DONE) {
111                         break;
112                 } else {
113                         fprintf(stderr, "SELECT step: %s\n", sqlite3_errmsg(db));
114                         abort();
115                 }
116         }
117         ret = sqlite3_finalize(stmt);
118         if (ret != SQLITE_OK) {
119                 fprintf(stderr, "SELECT finalize: %s\n", sqlite3_errmsg(db));
120                 abort();
121         }
122
123         // Load the matches themselves.
124         ret = sqlite3_prepare_v2(db, "SELECT match, description, gender_rule_a, gender_pull_rule FROM match ORDER BY match", -1, &stmt, 0);
125         if (ret != SQLITE_OK) {
126                 fprintf(stderr, "SELECT prepare: %s\n", sqlite3_errmsg(db));
127                 abort();
128         }
129         for ( ;; ) {
130                 ret = sqlite3_step(stmt);
131                 if (ret == SQLITE_ROW) {
132                         int match = sqlite3_column_int(stmt, 0);
133                         QJsonObject m;
134                         m.insert("match_id", match);
135                         m.insert("description", (const char *)sqlite3_column_text(stmt, 1));
136                         m.insert("gender_rule_a", (bool)sqlite3_column_int64(stmt, 2));
137                         m.insert("gender_pull_rule", (bool)sqlite3_column_int64(stmt, 3));
138                         if (events_per_match.count(match)) {
139                                 m.insert("events", std::move(*events_per_match[match]));
140                                 delete events_per_match[match];
141                         } else {
142                                 m.insert("events", QJsonArray());
143                         }
144                         matches.push_back(std::move(m));
145                 } else if (ret == SQLITE_DONE) {
146                         break;
147                 } else {
148                         fprintf(stderr, "SELECT step: %s\n", sqlite3_errmsg(db));
149                         abort();
150                 }
151         }
152         ret = sqlite3_finalize(stmt);
153         if (ret != SQLITE_OK) {
154                 fprintf(stderr, "SELECT finalize: %s\n", sqlite3_errmsg(db));
155                 abort();
156         }
157
158         return matches;
159 }
160
161 void export_to_json(sqlite3 *db, const char *filename)
162 {
163         QJsonObject obj;
164         obj.insert("players", export_players_to_json(db));
165         obj.insert("formations", export_formations_to_json(db));
166         obj.insert("matches", export_matches_to_json(db));
167
168         QByteArray serialized = QString(QJsonDocument(obj).toJson(QJsonDocument::Compact)).toUtf8();
169         FILE *fp = fopen("ultimate.json", "w");
170         if (fp == nullptr) {
171                 perror("ultimate.json");
172                 exit(1);
173         }
174         if (fwrite(serialized.data(), serialized.size(), 1, fp) != 1) {
175                 perror("fwrite");
176                 exit(1);
177         }
178         if (fclose(fp) != 0) {
179                 perror("fclose");
180                 exit(1);
181         }
182 }