]> git.sesse.net Git - pkanalytics/blobdiff - json.cpp
Implement JSON export. (For the time being, automatically on startup only, and nothin...
[pkanalytics] / json.cpp
diff --git a/json.cpp b/json.cpp
new file mode 100644 (file)
index 0000000..56b2000
--- /dev/null
+++ b/json.cpp
@@ -0,0 +1,136 @@
+#include <QJsonArray>
+#include <QJsonDocument>
+#include <QJsonObject>
+#include <sqlite3.h>
+#include "json.h"
+
+QJsonArray export_players_to_json(sqlite3 *db)
+{
+       QJsonArray players;
+
+       sqlite3_stmt *stmt;
+       int ret = sqlite3_prepare_v2(db, "SELECT player, number, name, gender FROM player ORDER BY (number+0), number", -1, &stmt, 0);
+       if (ret != SQLITE_OK) {
+               fprintf(stderr, "SELECT prepare: %s\n", sqlite3_errmsg(db));
+               abort();
+       }
+       for ( ;; ) {
+               ret = sqlite3_step(stmt);
+               if (ret == SQLITE_ROW) {
+                       QJsonObject p;
+                       p.insert("player_id", sqlite3_column_int(stmt, 0));
+                       p.insert("number", (const char *)sqlite3_column_text(stmt, 1));
+                       p.insert("name", (const char *)sqlite3_column_text(stmt, 2));
+                       p.insert("gender", (const char *)sqlite3_column_text(stmt, 3));
+                       players.push_back(std::move(p));
+               } else if (ret == SQLITE_DONE) {
+                       break;
+               } else {
+                       fprintf(stderr, "SELECT step: %s\n", sqlite3_errmsg(db));
+                       abort();
+               }
+       }
+       ret = sqlite3_finalize(stmt);
+       if (ret != SQLITE_OK) {
+               fprintf(stderr, "SELECT finalize: %s\n", sqlite3_errmsg(db));
+               abort();
+       }
+
+       return players;
+}
+
+QJsonArray export_matches_to_json(sqlite3 *db)
+{
+       QJsonArray matches;
+
+       // Load the events, splitting them into matches as we go.
+       std::map<int, QJsonArray *> events_per_match;
+       sqlite3_stmt *stmt;
+       int ret = sqlite3_prepare_v2(db, "SELECT match, t, player, type FROM event ORDER BY t", -1, &stmt, 0);
+       if (ret != SQLITE_OK) {
+               fprintf(stderr, "SELECT prepare: %s\n", sqlite3_errmsg(db));
+               abort();
+       }
+       for ( ;; ) {
+               ret = sqlite3_step(stmt);
+               if (ret == SQLITE_ROW) {
+                       int match = sqlite3_column_int(stmt, 0);
+                       if (events_per_match.count(match) == 0) {
+                               events_per_match[match] = new QJsonArray;
+                       }
+
+                       QJsonObject e;
+                       e.insert("t", sqlite3_column_int(stmt, 1));
+                       e.insert("player", sqlite3_column_int(stmt, 2));
+                       e.insert("type", (const char *)sqlite3_column_text(stmt, 3));
+                       events_per_match[match]->push_back(std::move(e));
+               } else if (ret == SQLITE_DONE) {
+                       break;
+               } else {
+                       fprintf(stderr, "SELECT step: %s\n", sqlite3_errmsg(db));
+                       abort();
+               }
+       }
+       ret = sqlite3_finalize(stmt);
+       if (ret != SQLITE_OK) {
+               fprintf(stderr, "SELECT finalize: %s\n", sqlite3_errmsg(db));
+               abort();
+       }
+
+       // Load the matches themselves.
+       ret = sqlite3_prepare_v2(db, "SELECT match, description FROM match ORDER BY match", -1, &stmt, 0);
+       if (ret != SQLITE_OK) {
+               fprintf(stderr, "SELECT prepare: %s\n", sqlite3_errmsg(db));
+               abort();
+       }
+       for ( ;; ) {
+               ret = sqlite3_step(stmt);
+               if (ret == SQLITE_ROW) {
+                       int match = sqlite3_column_int(stmt, 0);
+                       QJsonObject m;
+                       m.insert("match_id", match);
+                       m.insert("description", (const char *)sqlite3_column_text(stmt, 1));
+                       if (events_per_match.count(match)) {
+                               m.insert("events", std::move(*events_per_match[match]));
+                               delete events_per_match[match];
+                       } else {
+                               m.insert("events", QJsonArray());
+                       }
+                       matches.push_back(std::move(m));
+               } else if (ret == SQLITE_DONE) {
+                       break;
+               } else {
+                       fprintf(stderr, "SELECT step: %s\n", sqlite3_errmsg(db));
+                       abort();
+               }
+       }
+       ret = sqlite3_finalize(stmt);
+       if (ret != SQLITE_OK) {
+               fprintf(stderr, "SELECT finalize: %s\n", sqlite3_errmsg(db));
+               abort();
+       }
+
+       return matches;
+}
+
+void export_to_json(sqlite3 *db, const char *filename)
+{
+       QJsonObject obj;
+       obj.insert("players", export_players_to_json(db));
+       obj.insert("matches", export_matches_to_json(db));
+
+       QByteArray serialized = QString(QJsonDocument(obj).toJson(QJsonDocument::Compact)).toUtf8();
+       FILE *fp = fopen("ultimate.json", "w");
+       if (fp == nullptr) {
+               perror("ultimate.json");
+               exit(1);
+       }
+       if (fwrite(serialized.data(), serialized.size(), 1, fp) != 1) {
+               perror("fwrite");
+               exit(1);
+       }
+       if (fclose(fp) != 0) {
+               perror("fclose");
+               exit(1);
+       }
+}