add name button and store wordlist

As a p.o.c., load the built-in wordlist into storage once, and
thereafter use it from there rather than as a file. Now it can go away
and a wordlist for the user's locale be downloaded and stored instead.
This commit is contained in:
Eric House 2021-02-26 21:09:58 -08:00
parent c829017150
commit 2ab2f5642e
7 changed files with 131 additions and 46 deletions

View file

@ -62,6 +62,7 @@
#define KEY_LAST_GID "cur_game"
#define KEY_PLAYER_NAME "player_name"
#define KEY_DICTS "dicts_3"
#define KEY_GAME "game_data"
#define KEY_NAME "game_name"
#define KEY_NEXT_GAME "next_game"
@ -89,6 +90,7 @@
#define BUTTON_GAME_OPEN "Open Game"
#define BUTTON_GAME_RENAME "Rename Game"
#define BUTTON_GAME_DELETE "Delete Game"
#define BUTTON_NAME "My Name"
#define MAX_BUTTONS 20 /* not sure what's safe here */
typedef struct _NewGameParams {
@ -471,6 +473,7 @@ onGameRanamed( void* closure, const char* newName )
if ( !!newName ) {
CAST_GS(GameState*, gs, closure);
nameGame( gs, newName );
show_name( newName );
}
}
@ -589,6 +592,28 @@ onDeleteConfirmed( void* closure, bool confirmed )
}
}
static void
getPlayerName( Globals* globals, char* playerName, size_t buflen )
{
XP_U32 len = buflen;
dutil_loadPtr( globals->dutil, NULL, KEY_PLAYER_NAME, NULL,
playerName, &len );
XP_LOGFF( "after: len: %d", len );
if ( 0 == len ) { /* not found? */
strcpy( playerName, "Player 1" );
}
}
static void
onPlayerNamed( void* closure, const char* name )
{
CAST_GLOB(Globals*, globals, closure);
if ( !!name ) {
dutil_storePtr( globals->dutil, NULL, KEY_PLAYER_NAME,
name, 1 + strlen(name) );
}
}
static void
onDeviceButton( void* closure, const char* button )
{
@ -610,6 +635,11 @@ onDeviceButton( void* closure, const char* button )
"\nThis action cannot be undone.",
curGS->gameName );
call_confirm( globals, msg, onDeleteConfirmed, curGS );
} else if ( 0 == strcmp(button, BUTTON_NAME ) ) {
char playerName[32];
getPlayerName( globals, playerName, sizeof(playerName)-1 );
call_get_string( "Set your (local) player name", playerName,
onPlayerNamed, globals );
}
}
@ -643,6 +673,7 @@ updateDeviceButtons( Globals* globals )
buttons[cur++] = BUTTON_GAME_RENAME;
buttons[cur++] = BUTTON_GAME_DELETE;
}
buttons[cur++] = BUTTON_NAME;
buttons[cur++] = NULL;
setButtons( BUTTONS_ID_DEVICE, buttons, onDeviceButton, globals );
@ -669,6 +700,46 @@ onFocussed( void* closure, const char* ignored )
/* } */
}
static DictionaryCtxt*
playLoadingDict( Globals* globals )
{
/* Looking at whether the storage system can hold a dict. Let's see if
it's stored, and if it isn't store it. They try passing a ptr for
making the actual dict from. */
XP_U32 len = 0;
dutil_loadIndxPtr( globals->dutil, NULL, KEY_DICTS, DICTNAME, NULL, &len );
if ( 0 == len ) {
XP_LOGFF( "not found; storing now..." );
XP_U32 dictLen;
uint8_t* dictBytes = wasm_dictionary_load(MPPARM(globals->mpool)
DICTNAME, &dictLen);
if ( !!dictBytes ) {
XP_LOGFF( "loaded %d bytes of dict", dictLen );
dutil_storeIndxPtr( globals->dutil, NULL, KEY_DICTS, DICTNAME,
dictBytes, dictLen );
XP_FREE( globals->mpool, dictBytes );
}
len = dictLen;
} else {
XP_LOGFF( "using stored wordlist of len %d", len );
}
XP_U32 oldLen = len;
XP_LOGFF( "oldLen: %d", oldLen );
uint8_t* bytes = XP_MALLOC( globals->mpool, len );
dutil_loadIndxPtr( globals->dutil, NULL, KEY_DICTS, DICTNAME,
bytes, &len );
XP_ASSERT( len == oldLen );
DictionaryCtxt* dict =
wasm_dictionary_make( MPPARM(globals->mpool) NULL,
globals, DICTNAME, false, bytes );
LOG_RETURNF( "%p", dict );
return dict;
}
static void
initDeviceGlobals( Globals* globals )
{
@ -687,8 +758,8 @@ initDeviceGlobals( Globals* globals )
globals->vtMgr = make_vtablemgr( MPPARM_NOCOMMA(globals->mpool) );
globals->dutil = wasm_dutil_make( MPPARM(globals->mpool) globals->vtMgr, globals );
globals->dictMgr = dmgr_make( MPPARM_NOCOMMA(globals->mpool) );
globals->dict = wasm_dictionary_make( MPPARM(globals->mpool) NULL,
globals, DICTNAME, true );
globals->dict = playLoadingDict( globals );
dict_ref( globals->dict, NULL );
@ -750,34 +821,6 @@ startGame( GameState* gs, const char* name )
LOG_RETURN_VOID();
}
typedef struct _AskReplaceState {
Globals* globals;
NetLaunchInfo invite;
} AskReplaceState;
static void
onPlayerNamed( void* closure, const char* name )
{
CAST_GS(GameState*, gs, closure);
if ( !!name ) {
dutil_storePtr( gs->globals->dutil, NULL, KEY_PLAYER_NAME,
name, 1 + strlen(name) );
startGame( gs, name );
}
}
static void
getPlayerName( Globals* globals, char* playerName, size_t buflen )
{
XP_U32 len = buflen;
dutil_loadPtr( globals->dutil, NULL, KEY_PLAYER_NAME, NULL,
playerName, &len );
XP_LOGFF( "after: len: %d", len );
if ( 0 == len ) { /* not found? */
strcpy( playerName, "Player 1" );
}
}
static GameState*
newFromInvite( Globals* globals, const NetLaunchInfo* invite )
{
@ -1051,8 +1094,6 @@ main_onGameMessage( Globals* globals, XP_U32 gameID,
if ( game_receiveMessage( &gs->game, NULL, stream, from ) ) {
updateScreen( gs, true );
}
if ( gs != getCurGame(gs->globals) ) {
}
} else {
char msg[128];
snprintf( msg, sizeof(msg), "Dropping move for deleted game (id: %X/%d)",

View file

@ -8,6 +8,10 @@
.emscripten { padding-right: 0; margin-left: auto; margin-right: auto; display: block; }
textarea.emscripten { font-family: monospace; width: 80%; }
body.centered { text-align: center; }
table.centered {
margin-left: auto;
margin-right: auto;
}
div.emscripten { text-align: center; }
div.emscripten_border { border: 1px solid black; }
/* the canvas *must not* have any border or padding, or mouse coords will be wrong */
@ -90,8 +94,11 @@
<hr/>
<div class='buttonRow' id="device_buttons"></div>
<hr/>
<div><span>MQTT Dev ID:</span><span id="mqtt_span"></span></div>
<div><span>MQTT Status:</span><span id="mqtt_status">Unconnected</span></div>
<table class='centered'>
<tr><td>MQTT Dev ID:</td><td id="mqtt_span"></td></tr>
<tr><td>MQTT Status:</td><td id="mqtt_status">Unconnected</td></tr>
<tr><td>Storage used:</td><td id="storage_used">0</td></tr>
</table>
<hr/>
<!-- Remove until I figure out how to this works
<div class="emscripten">

View file

@ -1,4 +1,4 @@
/* -*- compile-command: "cd ../wasm && make main.html -j3"; -*- */
/* -*- compile-command: "cd ../wasm && make MEMDEBUG=TRUE install -j3"; -*- */
/*
* Copyright 2021 by Eric House (xwords@eehouse.org). All rights reserved.
*
@ -49,7 +49,8 @@ getShortName( const DictionaryCtxt* dict )
}
static XP_Bool
initFromDictFile( WasmDictionaryCtxt* dctx, const char* fileName )
initFromDictFile( WasmDictionaryCtxt* dctx, const char* fileName,
uint8_t* dictBase )
{
XP_Bool formatOk = XP_TRUE;
size_t dictLength;
@ -71,7 +72,9 @@ initFromDictFile( WasmDictionaryCtxt* dctx, const char* fileName )
{
FILE* dictF = fopen( path, "r" );
XP_ASSERT( !!dictF );
if ( dctx->useMMap ) {
if ( !!dictBase ) {
dctx->dictBase = dictBase;
} else if ( dctx->useMMap ) {
dctx->dictBase = mmap( NULL, dctx->dictLength, PROT_READ,
MAP_PRIVATE, fileno(dictF), 0 );
} else {
@ -189,7 +192,8 @@ wasm_dictionary_destroy( DictionaryCtxt* dict, XWEnv xwe )
DictionaryCtxt*
wasm_dictionary_make( MPFORMAL XWEnv xwe, Globals* globals,
const char* dictFileName, bool useMMap )
const char* dictFileName, bool useMMap,
uint8_t* base )
{
WasmDictionaryCtxt* result = NULL;
if ( !!dictFileName ) {
@ -207,7 +211,7 @@ wasm_dictionary_make( MPFORMAL XWEnv xwe, Globals* globals,
result->useMMap = useMMap;
if ( !!dictFileName ) {
XP_Bool success = initFromDictFile( result, dictFileName );
XP_Bool success = initFromDictFile( result, dictFileName, base );
if ( success ) {
result->super.func_dict_getShortName = getShortName;
setBlankTile( &result->super );
@ -227,6 +231,25 @@ wasm_dictionary_make( MPFORMAL XWEnv xwe, Globals* globals,
return &result->super;
}
uint8_t*
wasm_dictionary_load(MPFORMAL const char* dictFileName, XP_U32* len )
{
uint8_t* result = NULL;
*len = 0;
struct stat statbuf;
if ( 0 == stat( dictFileName, &statbuf ) && 0 != statbuf.st_size ) {
result = XP_MALLOC( mpool, statbuf.st_size );
FILE* dictF = fopen( dictFileName, "r" );
size_t nRead = fread( result, 1, statbuf.st_size, dictF );
XP_ASSERT( nRead == statbuf.st_size );
fclose( dictF );
*len = statbuf.st_size;
XP_LOGFF( "loaded %d bytes", statbuf.st_size );
}
return result;
}
void
dict_splitFaces( DictionaryCtxt* dict, XWEnv xwe, const XP_U8* utf8,
XP_U16 nBytes, XP_U16 nFaces )

View file

@ -25,6 +25,8 @@
#include "main.h"
DictionaryCtxt* wasm_dictionary_make( MPFORMAL XWEnv xwe, Globals* globals,
const char* dictFileName, bool useMMap );
const char* dictFileName, bool useMMap,
uint8_t* base );
uint8_t* wasm_dictionary_load(MPFORMAL const char* dictFileName, XP_U32* len );
#endif

View file

@ -243,27 +243,29 @@ static void
wasm_dutil_loadPtr( XW_DUtilCtxt* duc, XWEnv xwe, const XP_UCHAR* key,
const XP_UCHAR* keySuffix, void* data, XP_U32* lenp )
{
// XP_LOGFF( "(key: %s)", key );
// XP_LOGFF( "(key: %s, len: %d)", key, *lenp );
MAKE_PREFIX(fullKey, key);
size_t len;
get_stored_value(fullKey, NULL, &len);
char val[len];
char* val = XP_MALLOC( duc->mpool, len );
if ( get_stored_value( fullKey, val, &len ) ) {
// XP_LOGFF( "get_stored_value(%s) => %s", fullKey, val );
len = XP_STRLEN(val);
XP_ASSERT( (len % 2) == 0 );
XP_U8 decodeBuf[len/2];
len = VSIZE(decodeBuf);
XP_U8* decodeBuf = XP_MALLOC( duc->mpool, len/2 );
len = len/2;
if ( len <= *lenp ) {
base16Decode( decodeBuf, len, val );
XP_MEMCPY( data, decodeBuf, len );
}
*lenp = len;
XP_FREE( duc->mpool, decodeBuf );
} else {
*lenp = 0; /* signal failure */
}
XP_FREE( duc->mpool, val );
// XP_LOGFF("(%s)=> len: %d", fullKey, *lenp );
}
@ -271,10 +273,11 @@ static void
wasm_dutil_storePtr( XW_DUtilCtxt* duc, XWEnv xwe, const XP_UCHAR* key,
const void* data, XP_U32 len )
{
XP_UCHAR out[len*2+1];
XP_UCHAR* out = XP_MALLOC( duc->mpool, len*2+1 );
base16Encode( data, len, out, sizeof(out) );
MAKE_PREFIX(fullKey, key);
set_stored_value( fullKey, out );
XP_FREE( duc->mpool, out );
}
static void

View file

@ -411,7 +411,8 @@ static DictionaryCtxt*
wasm_util_makeEmptyDict( XW_UtilCtxt* uc, XWEnv xwe )
{
LOG_FUNC(); /* firing */
return wasm_dictionary_make( MPPARM(uc->mpool) NULL, uc->closure, NULL, false );
return wasm_dictionary_make( MPPARM(uc->mpool) NULL, uc->closure,
NULL, false, NULL );
}
static void

View file

@ -136,6 +136,14 @@ function onHaveDevID(closure, devid, gitrev, now, noTabProc, focusProc) {
onFailure: function() { alert('onFailure'); },
});
// let's sum up storage
let total = 0;
for (let ii = 0; ii < localStorage.length; ++ii ) {
let key = localStorage.key(ii);
let val = localStorage.getItem(key);
total += key.length + val.length;
}
document.getElementById("storage_used").textContent=total + 'b';
}
function mqttSend( topic, ptr ) {