#include #include #include #include #include #include "colors.h" #define QOVERVIEW 'o' #define QRPLAYER 'p' #define QMLEADERBOARD 'm' static inline char *get_filename(char * const c) { char *qout = "queries/mranks.sql"; if (c != NULL) { switch(*c) { default: *c = QOVERVIEW; break; case QMLEADERBOARD: qout = "queries/mleaderboard-ojoin.sql"; break; case QRPLAYER: qout = "queries/rplayers.sql"; break; } } return qout; } static inline void print_tblheader(const char *c) { char *labels; switch (*c) { default: labels = "\ \ \ \ \ \ \ "; break; case QMLEADERBOARD: labels = "


Map List

NameRecordsBest TimeHeld By
\ \ \ \ \ \ "; break; case QRPLAYER: labels = "


Leaderboard

RankNameTime
\ \ \ \ \ \ "; break; } printf("%s", labels); } // input is an integer as a string. // the time is in centiseconds. // this means the longest XDF run this can support is // 21,474,836.47 seconds // someone would need to idle in-game for 248 days static void print_time(const unsigned char *strcs) { const unsigned long num = strtoul((const char*)strcs, NULL, 10); unsigned long s = num/100; const unsigned long cs = num % 100; const unsigned long min = s/60; s = s % 60; if (min > 0) { printf("", min, s, cs); } else { printf("", s, cs); } } // display and format the results of the query. static void qresult(sqlite3_stmt * const sp, const char *c) { #define ISPLAYERNAME(x, y) (y == 1 && *x == QMLEADERBOARD) || \ (y == 3 && *x == QOVERVIEW)|| \ (y == 0 && *x == QRPLAYER) #define ISMAPNAME(x, y) (y == 0 && *x == QOVERVIEW) ||\ (y == 1 && *x == QRPLAYER) int e; unsigned int i; const unsigned int cc = sqlite3_column_count(sp); print_tblheader(c); while ((e = sqlite3_step(sp)) == SQLITE_ROW) { printf(""); for (i = 0; i < cc; ++i) { unsigned const char * const field = sqlite3_column_text(sp, i); if (ISPLAYERNAME(c, i)) { print_plname(field); } else if (ISMAPNAME(c, i)) { printf("", field, field); } else if (i == 2 && (*c == QMLEADERBOARD || *c == QOVERVIEW)) { print_time(field); } else { printf("", field); } } printf(""); } printf("


Ranks

NameMapRank
%u:%.2u.%.2u%u.%.2u
%s%s
"); } // const char 'sql' is never NULL. // const char 'str' may be NULL, however it is only when // the contents of mranks.sql is in const char 'sql'. static bool executequery(const char *sql, const char *str) { const char *p = (str != NULL) ? strchr(str, '=') + 1 : NULL; const char qc = (str != NULL) ? str[0] : QOVERVIEW; sqlite3 *db; int con = sqlite3_open("db/cts.db", &db); if (con != SQLITE_OK) { fprintf(stderr, "Can not open database: %s\n", sqlite3_errmsg(db)); return false; } sqlite3_stmt *s; // prepare sql to s, reading until null character. con = sqlite3_prepare_v2(db, sql, -1, &s, NULL); if (con != SQLITE_OK) { fprintf(stderr, "Could not prepare SQL statement: %s\n\n%s", sqlite3_errmsg(db), sql); return false; } // bind parameter with a string length that is the # of bytes to null char. con = sqlite3_bind_text(s, 1, p, -1, NULL); qresult(s, &qc); sqlite3_finalize(s); sqlite3_close(db); return true; } // both allocates and frees memory used up by the string.. // containing the data from query files. void getquery(char * const qs) { char *qf = NULL; char *fname = get_filename(qs); if (fname != NULL) { FILE *f = fopen(fname, "r"); if (f != NULL) { // change from fseek/SEEK_END when sql queries are >2 GB in size. fseek(f, 0, SEEK_END); // go to the end of file unsigned int size = ftell(f); qf = calloc(size, sizeof(char)); if (qf != NULL) { fseek(f, 0, SEEK_SET); // go to the start of file fread(qf, sizeof(char), size, f); } } fclose(f); } executequery(qf, qs); free(qf); }