BUG 2503: statistics API, logging monster creation

This commit is contained in:
Enno Rehling 2018-10-21 19:22:30 +02:00
parent 0f3f7a68b9
commit 38c1dfe26f
7 changed files with 133 additions and 1 deletions

View File

@ -334,6 +334,8 @@ int main(int argc, char **argv)
game_done();
lua_done(L);
log_close();
stats_write(stdout, "");
stats_close();
if (d) {
iniparser_freedict(d);
}

View File

@ -606,6 +606,7 @@ static void recruit_dracoids(unit * dragon, int size)
region *r = dragon->region;
const struct item *weapon = NULL;
unit *un = create_unit(r, f, size, get_race(RC_DRACOID), 0, NULL, NULL);
stats_count("monsters.create.dracoid", 1);
fset(un, UFL_ISNEW | UFL_MOVED);
@ -863,6 +864,7 @@ static int nrand(int handle_start, int sub)
unit *spawn_seaserpent(region *r, faction *f) {
unit *u = create_unit(r, f, 1, get_race(RC_SEASERPENT), 0, NULL, NULL);
stats_count("monsters.create.seaserpent", 1);
fset(u, UFL_ISNEW | UFL_MOVED);
equip_unit(u, "seed_seaserpent");
return u;
@ -903,6 +905,7 @@ void spawn_dragons(void)
else {
u = create_unit(r, monsters, nrand(30, 20) + 1, get_race(RC_DRAGON), 0, NULL, NULL);
}
stats_count("monsters.create.dragon", 1);
fset(u, UFL_ISNEW | UFL_MOVED);
equip_unit(u, "seed_dragon");
@ -963,6 +966,7 @@ void spawn_undead(void)
}
u = create_unit(r, monsters, undead, rc, 0, NULL, NULL);
stats_count("monsters.create.undead", 1);
fset(u, UFL_ISNEW | UFL_MOVED);
if ((rc == get_race(RC_SKELETON) || rc == get_race(RC_ZOMBIE))
&& rng_int() % 10 < 4) {

View File

@ -173,6 +173,8 @@ int RunAllTests(int argc, char *argv[])
fail_count = summary->failCount;
CuSuiteDelete(summary);
game_done();
log_close();
stats_close();
return fail_count;
}
return 0;

View File

@ -229,6 +229,8 @@ static void test_reset(void) {
default_locale = 0;
calendar_cleanup();
close_orders();
log_close();
stats_close();
free_special_directions();
free_locales();
free_spells();

View File

@ -15,6 +15,8 @@ without prior permission by the authors of Eressea.
#include "unicode.h"
#include "strings.h"
#include <critbit.h>
#include <assert.h>
#include <errno.h>
#include <limits.h>
@ -317,3 +319,77 @@ int log_level(log_t * log, int flags)
log->flags = flags;
return old;
}
static critbit_tree stats = CRITBIT_TREE();
int stats_count(const char *stat, int delta) {
size_t len;
char data[128];
void * match;
if (cb_find_prefix_str(&stats, stat, &match, 1, 0) == 0) {
len = cb_new_kv(stat, strlen(stat), &delta, sizeof(delta), data);
cb_insert(&stats, data, len);
return delta;
}
else {
int *num;
cb_get_kv_ex(match, (void **)&num);
return *num += delta;
}
}
#if 0
#define STATS_BATCH 8
void stats_walk(const char *prefix, void(*callback)(const char *, int, void *), void *udata) {
void *match[STATS_BATCH];
int n, off = 0;
do {
int i;
n = cb_find_prefix_str(&stats, prefix, match, STATS_BATCH, off);
if (n == 0) {
break;
}
off += n;
for (i = 0; i != n; ++i) {
const void *kv = match[i];
int *num;
cb_get_kv_ex(kv, &(void *)num);
callback(kv, *num, udata);
}
} while (n == STATS_BATCH);
}
#else
struct walk_data {
int (*callback)(const char *, int, void *);
void *udata;
};
static int walk_cb(void * match, const void * key, size_t keylen, void *udata) {
struct walk_data *data = (struct walk_data *)udata;
int *num;
cb_get_kv_ex(match, (void **)&num);
return data->callback((const char*)match, *num, data->udata);
}
int stats_walk(const char *prefix, int (*callback)(const char *, int, void *), void *udata) {
struct walk_data data;
data.callback = callback;
data.udata = udata;
return cb_foreach(&stats, prefix, strlen(prefix), walk_cb, &data);
}
#endif
static int write_cb(const char *key, int val, void *udata) {
FILE * F = (FILE *)udata;
fprintf(F, "%s: %d\n", (const char *)key, val);
return 0;
}
void stats_write(FILE *F, const char *prefix) {
stats_walk(prefix, write_cb, F);
}
void stats_close(void) {
cb_clear(&stats);
}

View File

@ -36,6 +36,12 @@ extern "C" {
void log_printf(FILE * ios, const char *format, ...);
void errno_check(const char *file, int line);
int stats_count(const char *stat, int delta);
void stats_write(FILE *F, const char *prefix);
int stats_walk(const char *prefix, int (*callback)(const char *key, int val, void * udata), void *udata);
void stats_close(void);
#define ERRNO_CHECK() errno_check(__FILE__, __LINE__)

View File

@ -1,11 +1,13 @@
#ifdef _MSC_VER
#include <platform.h>
#endif
#include <CuTest.h>
#include "log.h"
#include "macros.h"
#include <CuTest.h>
#include <tests.h>
#include <stdarg.h>
#include <string.h>
@ -32,9 +34,47 @@ static void test_logging(CuTest * tc)
CuAssertStrEquals(tc, "World", str2);
}
static int stats_cb(const char *stat, int num, void *udata) {
int *counter = (int *)udata;
if (counter) {
*counter += num;
}
return 0;
}
static void test_stats(CuTest * tc)
{
int n = 0;
test_setup();
CuAssertIntEquals(tc, 1, stats_count("foobar", 1));
CuAssertIntEquals(tc, 2, stats_count("test.one", 2));
CuAssertIntEquals(tc, 1, stats_count("test.two", 1));
CuAssertIntEquals(tc, 4, stats_count("test.one", 2));
CuAssertIntEquals(tc, 1, stats_count("test.two", 0));
n = 0;
CuAssertIntEquals(tc, 0, stats_walk("", stats_cb, &n));
CuAssertIntEquals(tc, 6, n);
n = 0;
CuAssertIntEquals(tc, 0, stats_walk("test", stats_cb, &n));
CuAssertIntEquals(tc, 5, n);
n = 0;
CuAssertIntEquals(tc, 0, stats_walk("test.one", stats_cb, &n));
CuAssertIntEquals(tc, 4, n);
n = 0;
CuAssertIntEquals(tc, 0, stats_walk("foobar", stats_cb, &n));
CuAssertIntEquals(tc, 1, n);
test_teardown();
}
CuSuite *get_log_suite(void)
{
CuSuite *suite = CuSuiteNew();
SUITE_ADD_TEST(suite, test_logging);
SUITE_ADD_TEST(suite, test_stats);
return suite;
}