]> git.sesse.net Git - pkanalytics/blob - json.cpp
Fix various issues with setting the special “none/unknown” formation.
[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_matches_to_json(sqlite3 *db)
43 {
44         QJsonArray matches;
45
46         // Load the events, splitting them into matches as we go.
47         std::map<int, QJsonArray *> events_per_match;
48         sqlite3_stmt *stmt;
49         int ret = sqlite3_prepare_v2(db, "SELECT match, t, player, type FROM event ORDER BY t", -1, &stmt, 0);
50         if (ret != SQLITE_OK) {
51                 fprintf(stderr, "SELECT prepare: %s\n", sqlite3_errmsg(db));
52                 abort();
53         }
54         for ( ;; ) {
55                 ret = sqlite3_step(stmt);
56                 if (ret == SQLITE_ROW) {
57                         int match = sqlite3_column_int(stmt, 0);
58                         if (events_per_match.count(match) == 0) {
59                                 events_per_match[match] = new QJsonArray;
60                         }
61
62                         QJsonObject e;
63                         e.insert("t", sqlite3_column_int(stmt, 1));
64                         if (sqlite3_column_type(stmt, 2) == SQLITE_INTEGER) {
65                                 e.insert("player", sqlite3_column_int(stmt, 2));
66                         } else {
67                                 e.insert("player", QJsonValue());  // null
68                         }
69                         e.insert("type", (const char *)sqlite3_column_text(stmt, 3));
70                         events_per_match[match]->push_back(std::move(e));
71                 } else if (ret == SQLITE_DONE) {
72                         break;
73                 } else {
74                         fprintf(stderr, "SELECT step: %s\n", sqlite3_errmsg(db));
75                         abort();
76                 }
77         }
78         ret = sqlite3_finalize(stmt);
79         if (ret != SQLITE_OK) {
80                 fprintf(stderr, "SELECT finalize: %s\n", sqlite3_errmsg(db));
81                 abort();
82         }
83
84         // Load the matches themselves.
85         ret = sqlite3_prepare_v2(db, "SELECT match, description FROM match ORDER BY match", -1, &stmt, 0);
86         if (ret != SQLITE_OK) {
87                 fprintf(stderr, "SELECT prepare: %s\n", sqlite3_errmsg(db));
88                 abort();
89         }
90         for ( ;; ) {
91                 ret = sqlite3_step(stmt);
92                 if (ret == SQLITE_ROW) {
93                         int match = sqlite3_column_int(stmt, 0);
94                         QJsonObject m;
95                         m.insert("match_id", match);
96                         m.insert("description", (const char *)sqlite3_column_text(stmt, 1));
97                         if (events_per_match.count(match)) {
98                                 m.insert("events", std::move(*events_per_match[match]));
99                                 delete events_per_match[match];
100                         } else {
101                                 m.insert("events", QJsonArray());
102                         }
103                         matches.push_back(std::move(m));
104                 } else if (ret == SQLITE_DONE) {
105                         break;
106                 } else {
107                         fprintf(stderr, "SELECT step: %s\n", sqlite3_errmsg(db));
108                         abort();
109                 }
110         }
111         ret = sqlite3_finalize(stmt);
112         if (ret != SQLITE_OK) {
113                 fprintf(stderr, "SELECT finalize: %s\n", sqlite3_errmsg(db));
114                 abort();
115         }
116
117         return matches;
118 }
119
120 void export_to_json(sqlite3 *db, const char *filename)
121 {
122         QJsonObject obj;
123         obj.insert("players", export_players_to_json(db));
124         obj.insert("matches", export_matches_to_json(db));
125
126         QByteArray serialized = QString(QJsonDocument(obj).toJson(QJsonDocument::Compact)).toUtf8();
127         FILE *fp = fopen("ultimate.json", "w");
128         if (fp == nullptr) {
129                 perror("ultimate.json");
130                 exit(1);
131         }
132         if (fwrite(serialized.data(), serialized.size(), 1, fp) != 1) {
133                 perror("fwrite");
134                 exit(1);
135         }
136         if (fclose(fp) != 0) {
137                 perror("fclose");
138                 exit(1);
139         }
140 }