update model format
[carveJwlIkooP6JGAAIwe30JlM.git] / highscores.h
index 84ab9a4164a5c9e0a8ab14e9d61179d4ca60437e..b1c9cc0a5d591794388213552ab1938a75003a0b 100644 (file)
@@ -3,6 +3,7 @@
 
 #include "vg/vg_store.h"
 #include "vg/vg_stdint.h"
+#include "world_info.h"
 
 /* 
  * Designed to be used across client and server,
@@ -20,7 +21,7 @@ typedef struct highscore_playerinfo highscore_playerinfo;
 
 struct highscore_playerinfo
 {
-   char nickname[16];
+   char nickname[10];
    u64 playerid;
 
    union
@@ -364,9 +365,14 @@ static aatree_ptr highscores_push_record( highscore_record *record )
    return index;
 }
 
-static aatree_ptr highscore_set_user_nickname( u64 steamid, char nick[16] )
+static aatree_ptr highscore_set_user_nickname( u64 steamid, char nick[10] )
 {
-   vg_log( "Updating %lu's nickname\n", steamid );
+   char name[11];
+   for( int i=0; i<10; i++ )
+      name[i] = nick[i];
+   name[10] = '\0';
+
+   vg_log( "Updating %lu's nickname -> %s\n", steamid, name );
 
    struct highscore_system *sys = &highscore_system;
    
@@ -403,76 +409,206 @@ static aatree_ptr highscore_set_user_nickname( u64 steamid, char nick[16] )
             record );
    }
 
-   for( int i=0; i<16; i++ )
+   for( int i=0; i<10; i++ )
       info->nickname[i] = nick[i];
 
    return AATREE_PTR_NIL;
 }
 
-static void _highscore_showtime( void *data )
+/* Get the length of a string, bounded by '\0' or len, whichever is first */
+static int highscore_strlen( const char *str, int len )
+{
+   int str_length;
+   for( str_length=0; str_length<len; str_length++ )
+      if( !str[str_length] )
+         return str_length;
+
+   return str_length;
+}
+
+/* Print the string(max length:len) centered into buf (has width:width) */
+static void highscore_strc( char *buf, const char *str, int len, int width )
+{
+   int str_length = highscore_strlen( str, len ),
+       offs = (width-str_length)/2;
+
+   for( int i=0; i<str_length; i++ )
+   {
+      int j=i+offs;
+
+      if( j >= width )
+         return;
+
+      buf[j] = str[i];
+   }
+}
+
+/* Print the string(max length:len) left aligned into buf */
+static void highscore_strl( char *buf, const char *str, int len )
 {
-   highscore_record *record = data;
-   printf( "%hu", record->time );
+   for( int i=0; i<len; i++ )
+   {
+      if( !str[i] )
+         return;
+
+      buf[i] = str[i];
+   }
+}
+
+/* Print the string (max length:len) right aligned into buf (has width:width) */
+static void highscore_strr( char *buf, const char *str, int len, int width )
+{
+   int str_length = highscore_strlen( str, len );
+   
+   for( int i=0; i<len; i++ )
+   {
+      if( !str[i] )
+         return;
+
+      buf[width-str_length+i] = str[i];
+   }
+}
+
+/* Print integer (padded with: alt), right aligned into buf(width: len) */
+static void highscore_intr( char *buf, int value, int len, char alt )
+{
+   int i=0;
+   while(value)
+   {
+      if( i>=len ) 
+         return;
+
+      buf[ len-1 - (i ++) ] = '0' + (value % 10);
+      value /= 10;
+   }
+
+   for( ;i<len; i ++ )
+      buf[ len-1 - i ] = alt;
 }
 
-static void _highscore_showname( void *data )
+/* Print integer into buffer with max length len */
+static void highscore_intl( char *buf, int value, int len )
 {
-   char namebuf[17];
-   namebuf[16] = '\0';
+   char temp[32];
+
+   int i=0;
+   while(value)
+   {
+      if( i>=len ) 
+         break;
 
-   highscore_playerinfo *info = data;
-   for( int i=0; i<16; i++ )
-      namebuf[i] = info->nickname[i];
+      temp[ i ++ ] = '0' + (value % 10);
+      value /= 10;
+   }
+   
+   if( i>len )
+      i = len;
 
-   printf( " %lu %s", info->playerid, namebuf );
+   for( int j=0; j<i; j ++ )
+   {
+      buf[j] = temp[ i-1-j ];
+   }
+}
+
+/* Clear buffer with length using clr character */
+static void highscore_clear( char *buf, char clr, int length )
+{
+   for( int i=0; i<length; i++ )
+      buf[i] = clr;
 }
 
-static void highscores_print_track( u32 trackid, u32 count )
+/*
+       Megapark Green      
+--------------------------
+ #|   Player |  Time | Pts 
+ 1|aaaabbbbcc 5:23.32 30000
+ 2|       jef 0:20.34 10000
+ 3|aaabbbcccl 2:30.45 20000
+ 4|
+ 5|
+ 6|
+ 7|
+ 8|
+ 9|
+10|
+*/
+
+/* Generate a highscores board in text form, the width is always 27. Buffer 
+ * must be (count+3)*27 in size. */
+static void highscores_board_generate( char *buf, u32 id, u32 count )
 {
+   int w=27;
+   highscore_clear( buf, ' ', (count+3)*w );
+
+   struct track_info *inf = &track_infos[id];
    struct highscore_system *sys = &highscore_system;
 
-   highscore_track_table *table = &sys->dbheader.tracks[ trackid ];
+   highscore_track_table *table = &sys->dbheader.tracks[ id ];
    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_strc ( buf+w*0, inf->name, w,w );
+   highscore_clear( buf+w*1, '-', w );
+   highscore_strl ( buf+w*2, " #|  Player  | Time  | Pts", 27 );
+
+   for( int i=0; i<count; i++ )
    {
-      highscore_record *record = aatree_get_data( &sys->aainfo_time, it );
+      char *line = buf+w*(3+i);
+      highscore_intr( line, i+1, 2, ' ' );
+      line[2] = '|';
 
+      if( it == AATREE_PTR_NIL )
+         continue;
+
+      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];
+      
+      /* Player name */
       if( info_ptr == AATREE_PTR_NIL )
-         snprintf( namebuf, 16, "[%lu]", record->playerid );
+         highscore_strl( line+3, "unknown", 10 );
       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';
+         highscore_strl( line+3, inf->nickname, 10 );
       }
 
-      vg_info( "%3d| %16s   %5hu   %5hu   %3hu\n",
-                  i+1, namebuf, record->time, record->points,
-                  record->trackid );
+      u16 miliseconds = record->time,
+          seconds     = miliseconds / 100,
+          minutes     = seconds / 60;
+
+      miliseconds %= 100;
+      seconds     %= 60;
+      minutes     %= 60;
 
-      i++;
+      if( minutes > 9 ) minutes = 9;
+      
+      /* Timer */
+      highscore_intr( line+14, minutes, 1, '0' );
+      line[15] = ':';
+      highscore_intr( line+16, seconds, 2, '0' );
+      line[18] = '.';
+      highscore_intr( line+19, miliseconds, 2, '0' );
+
+      /* Score */
+      highscore_intl( line+22, record->time, 5 );
       it = aatree_next( &sys->aainfo_time, it );
    }
+}
+
+/* Print string out to file using newlines. Count is number of records 
+ * ( this requires a buffer of (count+3)*27 size */
+static void highscores_board_printf( FILE *fp, const char *buf, u32 count )
+{
+   int w=27;
 
-   vg_info( "================================================\n" );
+   for( int i=0; i<count+3; i++ )
+      fprintf( fp, "%.27s\n", &buf[i*w] );
 }
 
 #endif /* HIGHSCORES_H */