4 #include "vg/vg_store.h"
5 #include "vg/vg_stdint.h"
8 * Designed to be used across client and server,
9 * for the client its only storing the local users records, for server its
13 typedef struct highscore highscore
;
14 typedef struct highscore_record highscore_record
;
15 typedef struct highscore_track_table highscore_track_table
;
16 typedef struct highscore_database highscore_database
;
19 struct highscore_record
21 u16 trackid
, points
, time
, reserved0
;
40 /* TODO pool allocator */
47 struct highscore_track_table
49 aatree_ptr root_points
,
57 struct highscore_database
59 highscore_track_table tracks
[ 128 ];
67 static struct highscore_system
69 highscore_database dbheader
;
80 static int highscore_cmp_points( void *a
, void *b
)
82 highscore_record
*pa
= a
, *pb
= b
;
83 return (int)pa
->points
- (int)pb
->points
;
86 static int highscore_cmp_datetime( void *a
, void *b
)
88 highscore_record
*pa
= a
, *pb
= b
;
90 if( pa
->datetime
== pb
->datetime
) return 0;
91 return pa
->datetime
< pb
->datetime
? 1: -1;
94 static int highscore_cmp_time( void *a
, void *b
)
96 highscore_record
*pa
= a
, *pb
= b
;
97 return (int)pb
->time
- (int)pa
->time
;
100 static int highscore_cmp_playerid( void *a
, void *b
)
102 highscore_record
*pa
= a
, *pb
= b
;
103 if( pa
->playerid
== pb
->playerid
) return 0;
104 return pa
->playerid
< pb
->playerid
? -1: 1;
107 static int highscores_init( u32 pool_size
)
109 struct highscore_system
*sys
= &highscore_system
;
111 size_t requested_mem
= pool_size
* sizeof(highscore_record
);
112 sys
->data
= malloc( requested_mem
);
114 requested_mem
/= 1024;
115 requested_mem
/= 1024;
117 if( !highscore_system
.data
)
119 vg_error( "Could not allocated %dmb of memory for database\n",
124 vg_success( "Allocated %dmb for database\n", requested_mem
);
126 /* This is ugly.. too bad! */
127 sys
->aainfo
.base
= highscore_system
.data
;
128 sys
->aainfo
.stride
= sizeof(highscore_record
);
129 sys
->aainfo
.offset
= offsetof(highscore_record
,pool
);
130 sys
->aainfo
.p_cmp
= NULL
;
132 sys
->aainfo_datetime
.base
= highscore_system
.data
;
133 sys
->aainfo_datetime
.stride
= sizeof(highscore_record
);
134 sys
->aainfo_datetime
.offset
= offsetof(highscore_record
,aa
.datetime
);
135 sys
->aainfo_datetime
.p_cmp
= highscore_cmp_datetime
;
137 sys
->aainfo_points
.base
= highscore_system
.data
;
138 sys
->aainfo_points
.stride
= sizeof(highscore_record
);
139 sys
->aainfo_points
.offset
= offsetof(highscore_record
,aa
.points
);
140 sys
->aainfo_points
.p_cmp
= highscore_cmp_points
;
142 sys
->aainfo_time
.base
= highscore_system
.data
;
143 sys
->aainfo_time
.stride
= sizeof(highscore_record
);
144 sys
->aainfo_time
.offset
= offsetof(highscore_record
,aa
.time
);
145 sys
->aainfo_time
.p_cmp
= highscore_cmp_time
;
147 sys
->aainfo_playerid
.base
= highscore_system
.data
;
148 sys
->aainfo_playerid
.stride
= sizeof(highscore_record
);
149 sys
->aainfo_playerid
.offset
= offsetof(highscore_record
,aa
.playerid
);
150 sys
->aainfo_playerid
.p_cmp
= highscore_cmp_playerid
;
153 /* TODO: Load from disk if avalible */
160 vg_info( "Initializing database nodes\n" );
161 sys
->dbheader
.pool_head
= aatree_init_pool( &sys
->aainfo
, pool_size
);
163 for( int i
=0; i
<vg_list_size(sys
->dbheader
.tracks
); i
++ )
165 highscore_track_table
*table
= &sys
->dbheader
.tracks
[i
];
166 table
->root_points
= AATREE_PTR_NIL
;
167 table
->root_playerid
= AATREE_PTR_NIL
;
168 table
->root_time
= AATREE_PTR_NIL
;
169 table
->root_datetime
= AATREE_PTR_NIL
;
176 static void highscores_free(void)
178 free( highscore_system
.data
);
181 static aatree_ptr
highscores_push_record( highscore_record
*record
)
183 struct highscore_system
*sys
= &highscore_system
;
185 /* TODO: Verify steam ID */
186 vg_log( "Inserting record into database for track %hu\n",record
->trackid
);
188 if( record
->trackid
>= vg_list_size(sys
->dbheader
.tracks
) )
190 vg_error( "TrackID out of range (%hu>=%d)\n", record
->trackid
,
191 vg_list_size(sys
->dbheader
.tracks
) );
193 return AATREE_PTR_NIL
;
196 /* Search for existing record on this track */
197 highscore_track_table
*table
= &sys
->dbheader
.tracks
[record
->trackid
];
198 aatree_ptr existing
= aatree_find( &sys
->aainfo_playerid
,
199 table
->root_playerid
,
202 if( existing
!= AATREE_PTR_NIL
)
204 vg_log( "Freeing existing record for player %lu\n", record
->playerid
);
205 table
->root_playerid
= aatree_del( &sys
->aainfo_playerid
, existing
);
206 table
->root_datetime
= aatree_del( &sys
->aainfo_datetime
, existing
);
207 table
->root_points
= aatree_del( &sys
->aainfo_points
, existing
);
208 table
->root_time
= aatree_del( &sys
->aainfo_time
, existing
);
210 aatree_pool_free( &sys
->aainfo
, existing
, &sys
->dbheader
.pool_head
);
214 aatree_pool_alloc( &sys
->aainfo
, &sys
->dbheader
.pool_head
);
216 if( index
== AATREE_PTR_NIL
)
219 highscore_record
*dst
= aatree_get_data( &sys
->aainfo
, index
);
220 memset( dst
, 0, sizeof(highscore_record
) );
222 dst
->trackid
= record
->trackid
;
223 dst
->datetime
= record
->datetime
;
224 dst
->playerid
= record
->playerid
;
225 dst
->points
= record
->points
;
226 dst
->time
= record
->time
;
229 aatree_insert( &sys
->aainfo_time
, table
->root_time
, index
);
230 table
->root_datetime
=
231 aatree_insert( &sys
->aainfo_datetime
, table
->root_datetime
, index
);
232 table
->root_playerid
=
233 aatree_insert( &sys
->aainfo_playerid
, table
->root_playerid
, index
);
235 aatree_insert( &sys
->aainfo_points
, table
->root_points
, index
);
240 static void _highscore_showtime( void *data
)
242 highscore_record
*record
= data
;
243 printf( "%hu", record
->time
);
246 static void highscores_print_track( u32 trackid
, u32 count
)
248 struct highscore_system
*sys
= &highscore_system
;
250 highscore_track_table
*table
= &sys
->dbheader
.tracks
[ trackid
];
251 aatree_ptr it
= aatree_kth( &sys
->aainfo_time
, table
->root_time
, 0 );
253 vg_info( "Highscores, top %u records for track %u\n", count
, trackid
);
254 vg_info( "==============================================\n" );
257 while( it
!= AATREE_PTR_NIL
&& i
< 10 )
259 highscore_record
*record
= aatree_get_data( &sys
->aainfo_time
, it
);
260 vg_info( " [%d]: player(%lu), time: %hu, score: %hu, track:%hu\n",
261 i
+1, record
->playerid
, record
->time
, record
->points
,
265 it
= aatree_next( &sys
->aainfo_time
, it
);
268 vg_info( "==============================================\n" );
271 #endif /* HIGHSCORES_H */