]> git.sesse.net Git - pkanalytics/blob - json.cpp
Implement JSON export. (For the time being, automatically on startup only, and nothin...
[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                         e.insert("player", sqlite3_column_int(stmt, 2));
65                         e.insert("type", (const char *)sqlite3_column_text(stmt, 3));
66                         events_per_match[match]->push_back(std::move(e));
67                 } else if (ret == SQLITE_DONE) {
68                         break;
69                 } else {
70                         fprintf(stderr, "SELECT step: %s\n", sqlite3_errmsg(db));
71                         abort();
72                 }
73         }
74         ret = sqlite3_finalize(stmt);
75         if (ret != SQLITE_OK) {
76                 fprintf(stderr, "SELECT finalize: %s\n", sqlite3_errmsg(db));
77                 abort();
78         }
79
80         // Load the matches themselves.
81         ret = sqlite3_prepare_v2(db, "SELECT match, description FROM match ORDER BY match", -1, &stmt, 0);
82         if (ret != SQLITE_OK) {
83                 fprintf(stderr, "SELECT prepare: %s\n", sqlite3_errmsg(db));
84                 abort();
85         }
86         for ( ;; ) {
87                 ret = sqlite3_step(stmt);
88                 if (ret == SQLITE_ROW) {
89                         int match = sqlite3_column_int(stmt, 0);
90                         QJsonObject m;
91                         m.insert("match_id", match);
92                         m.insert("description", (const char *)sqlite3_column_text(stmt, 1));
93                         if (events_per_match.count(match)) {
94                                 m.insert("events", std::move(*events_per_match[match]));
95                                 delete events_per_match[match];
96                         } else {
97                                 m.insert("events", QJsonArray());
98                         }
99                         matches.push_back(std::move(m));
100                 } else if (ret == SQLITE_DONE) {
101                         break;
102                 } else {
103                         fprintf(stderr, "SELECT step: %s\n", sqlite3_errmsg(db));
104                         abort();
105                 }
106         }
107         ret = sqlite3_finalize(stmt);
108         if (ret != SQLITE_OK) {
109                 fprintf(stderr, "SELECT finalize: %s\n", sqlite3_errmsg(db));
110                 abort();
111         }
112
113         return matches;
114 }
115
116 void export_to_json(sqlite3 *db, const char *filename)
117 {
118         QJsonObject obj;
119         obj.insert("players", export_players_to_json(db));
120         obj.insert("matches", export_matches_to_json(db));
121
122         QByteArray serialized = QString(QJsonDocument(obj).toJson(QJsonDocument::Compact)).toUtf8();
123         FILE *fp = fopen("ultimate.json", "w");
124         if (fp == nullptr) {
125                 perror("ultimate.json");
126                 exit(1);
127         }
128         if (fwrite(serialized.data(), serialized.size(), 1, fp) != 1) {
129                 perror("fwrite");
130                 exit(1);
131         }
132         if (fclose(fp) != 0) {
133                 perror("fclose");
134                 exit(1);
135         }
136 }