X-Git-Url: https://harrygodden.com/git/?a=blobdiff_plain;ds=sidebyside;f=highscores.h;h=0c4ae54131fe58546f0a2798652a56d05af5d636;hb=6e6c7f31b8f17af3814727109e48fc6f85ef04b1;hp=84ab9a4164a5c9e0a8ab14e9d61179d4ca60437e;hpb=f9656a800d0262a2096c3525c2160ce38bc16828;p=carveJwlIkooP6JGAAIwe30JlM.git diff --git a/highscores.h b/highscores.h index 84ab9a4..0c4ae54 100644 --- a/highscores.h +++ b/highscores.h @@ -1,8 +1,13 @@ +/* + * Copyright (C) 2021-2022 Mt.ZERO Software, Harry Godden - All Rights Reserved + */ + #ifndef HIGHSCORES_H #define HIGHSCORES_H #include "vg/vg_store.h" #include "vg/vg_stdint.h" +#include "world_info.h" /* * Designed to be used across client and server, @@ -86,393 +91,22 @@ static struct highscore_system aainfo_playerinfo_playerid, aainfo_playerinfo; - void *data, *playerinfo_data; -} -highscore_system; - -static int highscore_cmp_points( void *a, void *b ) -{ - highscore_record *pa = a, *pb = b; - return (int)pa->points - (int)pb->points; -} - -static int highscore_cmp_datetime( void *a, void *b ) -{ - highscore_record *pa = a, *pb = b; - - if( pa->datetime == pb->datetime ) return 0; - return pa->datetime < pb->datetime? 1: -1; -} - -static int highscore_cmp_time( void *a, void *b ) -{ - highscore_record *pa = a, *pb = b; - return (int)pb->time - (int)pa->time; -} - -static int highscore_cmp_playerid( void *a, void *b ) -{ - highscore_record *pa = a, *pb = b; - if( pa->playerid == pb->playerid ) return 0; - return pa->playerid < pb->playerid? -1: 1; -} - -static int highscore_cmp_playerinfo_playerid( void *a, void *b ) -{ - highscore_playerinfo *pa = a, *pb = b; - if( pa->playerid == pb->playerid ) return 0; - return pa->playerid < pb->playerid? -1: 1; -} - -static void *highscore_malloc( u32 count, u32 size ) -{ - size_t requested_mem = size * count; - void *data = malloc( requested_mem ); - - requested_mem /= 1024; - requested_mem /= 1024; - - if( !data ) - { - vg_error( "Could not allocated %dmb of memory\n", requested_mem ); - return NULL; - } - else - vg_success( "Allocated %dmb for %u records\n", requested_mem, count ); - - return data; -} - -static void highscores_free(void) -{ - free( highscore_system.data ); - free( highscore_system.playerinfo_data ); -} - -static int highscores_init( u32 pool_size, u32 playerinfo_pool_size ) -{ - struct highscore_system *sys = &highscore_system; - - sys->data = highscore_malloc( pool_size, sizeof(highscore_record) ); - if( !sys->data ) return 0; - - sys->playerinfo_data = - highscore_malloc( playerinfo_pool_size, sizeof(highscore_playerinfo)); - if( !sys->playerinfo_data ) - { - free( sys->data ); - return 0; - } - - /* This is ugly.. too bad! */ - sys->aainfo.base = highscore_system.data; - sys->aainfo.stride = sizeof(highscore_record); - sys->aainfo.offset = offsetof(highscore_record,pool); - sys->aainfo.p_cmp = NULL; - - sys->aainfo_datetime.base = highscore_system.data; - sys->aainfo_datetime.stride = sizeof(highscore_record); - sys->aainfo_datetime.offset = offsetof(highscore_record,aa.datetime); - sys->aainfo_datetime.p_cmp = highscore_cmp_datetime; - - sys->aainfo_points.base = highscore_system.data; - sys->aainfo_points.stride = sizeof(highscore_record); - sys->aainfo_points.offset = offsetof(highscore_record,aa.points); - sys->aainfo_points.p_cmp = highscore_cmp_points; - - sys->aainfo_time.base = highscore_system.data; - sys->aainfo_time.stride = sizeof(highscore_record); - sys->aainfo_time.offset = offsetof(highscore_record,aa.time); - sys->aainfo_time.p_cmp = highscore_cmp_time; - - sys->aainfo_playerid.base = highscore_system.data; - sys->aainfo_playerid.stride = sizeof(highscore_record); - sys->aainfo_playerid.offset = offsetof(highscore_record,aa.playerid); - sys->aainfo_playerid.p_cmp = highscore_cmp_playerid; - - sys->aainfo_playerinfo_playerid.base = highscore_system.playerinfo_data; - sys->aainfo_playerinfo_playerid.stride = sizeof(highscore_playerinfo); - sys->aainfo_playerinfo_playerid.offset = - offsetof(highscore_playerinfo,aa_playerid); - sys->aainfo_playerinfo_playerid.p_cmp = highscore_cmp_playerinfo_playerid; - - sys->aainfo_playerinfo.base = highscore_system.playerinfo_data; - sys->aainfo_playerinfo.stride = sizeof(highscore_playerinfo); - sys->aainfo_playerinfo.offset = offsetof(highscore_playerinfo,aapn); - sys->aainfo_playerinfo.p_cmp = NULL; - - FILE *fp = fopen( ".aadb", "rb" ); - if( fp ) - { - vg_info( "Loading existing database\n" ); - - u64 count = fread( &sys->dbheader, sizeof(highscore_database), 1, fp ); - - if( count != 1 ) - { - vg_error( "Unexpected EOF reading database header\n" ); - - highscores_free(); - return 0; - } - - count = fread( sys->data, sizeof(highscore_record), pool_size, fp ); - if( count != pool_size ) - { - vg_error( "Unexpected EOF reading database contents;" - " %lu records of %u were read\n", count, pool_size ); - - highscores_free(); - return 0; - } - - count = fread( sys->playerinfo_data, sizeof(highscore_playerinfo), - playerinfo_pool_size, fp ); - if( count != playerinfo_pool_size ) - { - vg_error( "Unexpected EOF reading playerinfo contents;" - " %lu records of %u were read\n", count, - playerinfo_pool_size ); - - highscores_free(); - return 0; - } - - fclose( fp ); - } - else - { - vg_log( "No existing database found (.aadb)\n" ); - vg_info( "Initializing database nodes\n" ); - memset( &sys->dbheader, 0, sizeof(highscore_database) ); - - sys->dbheader.pool_head = aatree_init_pool( &sys->aainfo, pool_size ); - sys->dbheader.entry_capacity = pool_size; - - for( int i=0; idbheader.tracks); i++ ) - { - highscore_track_table *table = &sys->dbheader.tracks[i]; - table->root_points = AATREE_PTR_NIL; - table->root_playerid = AATREE_PTR_NIL; - table->root_time = AATREE_PTR_NIL; - table->root_datetime = AATREE_PTR_NIL; - } - - /* Initialize secondary db */ - sys->dbheader.playerinfo_head = aatree_init_pool( - &sys->aainfo_playerinfo, - playerinfo_pool_size ); - sys->dbheader.playerinfo_capacity = playerinfo_pool_size; - sys->dbheader.playerinfo_root = AATREE_PTR_NIL; - } - - return 1; -} - -static int highscores_serialize_all(void) -{ - struct highscore_system *sys = &highscore_system; - vg_info( "Serializing database\n" ); - - FILE *fp = fopen( ".aadb", "wb" ); - - if( !fp ) - { - vg_error( "Could not open .aadb\n" ); - return 0; - } + void *data, + *playerinfo_data; - fwrite( &sys->dbheader, sizeof(highscore_database), 1, fp ); - fwrite( sys->data, sizeof(highscore_record), - sys->dbheader.entry_capacity, fp ); - fwrite( sys->playerinfo_data, sizeof(highscore_playerinfo), - sys->dbheader.playerinfo_capacity, fp ); - - fclose( fp ); - return 1; + u32 pool_size, playerinfo_pool_size; } +highscore_system; -static aatree_ptr highscores_push_record( highscore_record *record ) -{ - struct highscore_system *sys = &highscore_system; - - /* TODO: Verify steam ID */ - vg_log( "Inserting record into database for track %hu\n",record->trackid ); - - if( record->trackid >= vg_list_size(sys->dbheader.tracks) ) - { - vg_error( "TrackID out of range (%hu>=%d)\n", record->trackid, - vg_list_size(sys->dbheader.tracks) ); - - return AATREE_PTR_NIL; - } - - /* Search for existing record on this track */ - highscore_track_table *table = &sys->dbheader.tracks[record->trackid]; - aatree_ptr existing = aatree_find( &sys->aainfo_playerid, - table->root_playerid, - record ); - - if( existing != AATREE_PTR_NIL ) - { - highscore_record *crecord = aatree_get_data( &sys->aainfo_playerid, - existing ); - - if( crecord->time < record->time || - (crecord->time == record->time && crecord->points > record->points)) - { - vg_log( "Not overwriting better score\n" ); - return existing; - } - - vg_log( "Freeing existing record for player %lu\n", record->playerid ); - table->root_playerid = aatree_del( &sys->aainfo_playerid, existing ); - table->root_datetime = aatree_del( &sys->aainfo_datetime, existing ); - table->root_points = aatree_del( &sys->aainfo_points, existing ); - table->root_time = aatree_del( &sys->aainfo_time, existing ); - - aatree_pool_free( &sys->aainfo, existing, &sys->dbheader.pool_head ); - } - - aatree_ptr index = - aatree_pool_alloc( &sys->aainfo, &sys->dbheader.pool_head ); - - if( index == AATREE_PTR_NIL ) - { - vg_error( "Database records are over capacity!\n" ); - return index; - } - - highscore_record *dst = aatree_get_data( &sys->aainfo, index ); - memset( dst, 0, sizeof(highscore_record) ); - - dst->trackid = record->trackid; - dst->datetime = record->datetime; - dst->playerid = record->playerid; - dst->points = record->points; - dst->time = record->time; - - table->root_time = - aatree_insert( &sys->aainfo_time, table->root_time, index ); - table->root_datetime = - aatree_insert( &sys->aainfo_datetime, table->root_datetime, index ); - table->root_playerid = - aatree_insert( &sys->aainfo_playerid, table->root_playerid, index ); - table->root_points = - aatree_insert( &sys->aainfo_points, table->root_points, index ); - - return index; -} - -static aatree_ptr highscore_set_user_nickname( u64 steamid, char nick[16] ) -{ - vg_log( "Updating %lu's nickname\n", steamid ); - - struct highscore_system *sys = &highscore_system; - - highscore_playerinfo temp; - temp.playerid = steamid; - - aatree_ptr record = aatree_find( &sys->aainfo_playerinfo_playerid, - sys->dbheader.playerinfo_root, - &temp ); - highscore_playerinfo *info; - - if( record != AATREE_PTR_NIL ) - { - info = aatree_get_data( &sys->aainfo_playerinfo, record ); - } - else - { - record = aatree_pool_alloc( &sys->aainfo_playerinfo, - &sys->dbheader.playerinfo_head ); - - if( record == AATREE_PTR_NIL ) - { - vg_error( "Player info database is over capacity!\n" ); - return AATREE_PTR_NIL; - } - - info = aatree_get_data( &sys->aainfo_playerinfo, record ); - memset( info, 0, sizeof(highscore_playerinfo) ); - - info->playerid = steamid; - sys->dbheader.playerinfo_root = aatree_insert( - &sys->aainfo_playerinfo_playerid, - sys->dbheader.playerinfo_root, - record ); - } - - for( int i=0; i<16; i++ ) - info->nickname[i] = nick[i]; - - return AATREE_PTR_NIL; -} - -static void _highscore_showtime( void *data ) -{ - highscore_record *record = data; - printf( "%hu", record->time ); -} - -static void _highscore_showname( void *data ) -{ - char namebuf[17]; - namebuf[16] = '\0'; - - highscore_playerinfo *info = data; - for( int i=0; i<16; i++ ) - namebuf[i] = info->nickname[i]; - - printf( " %lu %s", info->playerid, namebuf ); -} - -static void highscores_print_track( u32 trackid, u32 count ) -{ - struct highscore_system *sys = &highscore_system; - - highscore_track_table *table = &sys->dbheader.tracks[ trackid ]; - aatree_ptr it = aatree_kth( &sys->aainfo_time, table->root_time, 0 ); - - vg_info( "Highscores: top %u fastest records for track %u\n", count, trackid ); - vg_info( "================================================\n" ); - vg_info( "%3s| %16s | %5s | %5s | %s\n", "#", "Player", "Time", "Score", - "TrackID" ); - vg_info( "================================================\n" ); - int i=0; - while( it != AATREE_PTR_NIL && i < 10 ) - { - highscore_record *record = aatree_get_data( &sys->aainfo_time, it ); - - highscore_playerinfo temp; - temp.playerid = record->playerid; - - aatree_ptr info_ptr = aatree_find( &sys->aainfo_playerinfo_playerid, - sys->dbheader.playerinfo_root, - &temp ); - - char namebuf[17]; - if( info_ptr == AATREE_PTR_NIL ) - snprintf( namebuf, 16, "[%lu]", record->playerid ); - else - { - highscore_playerinfo *inf = aatree_get_data( - &sys->aainfo_playerinfo_playerid, info_ptr ); - - for( int i=0; i<16; i++ ) - namebuf[i] = inf->nickname[i]; - namebuf[16] = '\0'; - } - - vg_info( "%3d| %16s %5hu %5hu %3hu\n", - i+1, namebuf, record->time, record->points, - record->trackid ); - - i++; - it = aatree_next( &sys->aainfo_time, it ); - } - - vg_info( "================================================\n" ); -} +static int highscore_intr( char *buf, int value, int len, char alt ); +static int highscore_intl( char *buf, int value, int len ); +static void highscores_board_printf( FILE *fp, const char *buf, u32 count ); +static aatree_ptr highscore_set_user_nickname( u64 steamid, char nick[16] ); +static aatree_ptr highscores_push_record( highscore_record *record ); +static void highscores_board_generate( char *buf, u32 id, u32 count ); +static void highscores_init( u32 pool_size, u32 playerinfo_pool_size ); +static int highscores_read( const char *path ); +static void highscores_create_db(void); +static int highscores_serialize_all(void); #endif /* HIGHSCORES_H */