improving lookup words experience: replace

util_userQuery(QUERY_ROBOT_MOVE) with new util_informMove(), into
which the number of words formed and the words themselves are passed.
The process of consing up the score explanation was already passing
over the model, so storing the words is very little effort, and will
save a call back into the model where the user actually wants to do
the lookup.
This commit is contained in:
Andy2 2011-10-02 16:21:09 -07:00
parent b7691d2997
commit 77b9fa11a5
7 changed files with 69 additions and 19 deletions

View file

@ -2033,11 +2033,6 @@ model_recentPassCountOk( ModelCtxt* model )
return count < okCount;
}
typedef struct _RecordWordsInfo {
XWStreamCtxt* stream;
XP_U16 nWords;
} RecordWordsInfo;
static XP_Bool
recordWord( const XP_UCHAR* word, XP_Bool isLegal, void* closure )
{
@ -2049,9 +2044,23 @@ recordWord( const XP_UCHAR* word, XP_Bool isLegal, void* closure )
stream_putU8( stream, '\n' );
}
stream_catString( stream, word );
if ( NULL != info->nWordsP ) {
*info->nWordsP = info->nWords;
}
return XP_TRUE;
}
WordNotifierInfo*
model_initWordCounter( ModelCtxt* model, XWStreamCtxt* stream, XP_U16* nWords )
{
model->vol.wni.proc = recordWord;
model->vol.wni.closure = &model->vol.rwi;
model->vol.rwi.stream = stream;
model->vol.rwi.nWordsP = nWords;
model->vol.rwi.nWords = 0;
return &model->vol.wni;
}
void
model_getWordsPlayed( ModelCtxt* model, XP_U16 nTurns, XWStreamCtxt* stream )
{
@ -2067,19 +2076,14 @@ model_getWordsPlayed( ModelCtxt* model, XP_U16 nTurns, XWStreamCtxt* stream )
}
if ( model_undoLatestMoves( model, NULL, nTurns, NULL, NULL ) ) {
RecordWordsInfo info = { .stream = stream, .nWords = 0 };
WordNotifierInfo notifyInfo = { .proc = recordWord,
.closure = &info,
};
WordNotifierInfo* ni = model_initWordCounter( model, stream, NULL );
/* Now push the undone moves back into the model one at a time.
recordWord() will add each played word to the stream as it's
scored */
buildModelFromStack( model, tmpStack, XP_TRUE,
nEntries - nTurns + nPlayers,/* skip assignments */
(XWStreamCtxt*)NULL, &notifyInfo,
(MovePrintFuncPre)NULL, (MovePrintFuncPost)NULL,
NULL );
(XWStreamCtxt*)NULL, ni, (MovePrintFuncPre)NULL,
(MovePrintFuncPost)NULL, NULL );
}
stack_destroy( tmpStack );
}

View file

@ -271,6 +271,10 @@ XP_U16 figureMoveScore( const ModelCtxt* model, XP_U16 turn, MoveInfo* mvInfo,
EngineCtxt* engine, XWStreamCtxt* stream,
WordNotifierInfo* notifyInfo );
/* tap into internal WordNotifierInfo */
WordNotifierInfo* model_initWordCounter( ModelCtxt* model, XWStreamCtxt* stream,
XP_U16* nWords );
/********************* persistence ********************/
#ifdef INCLUDE_IO_SUPPORT
void model_load( ModelCtxt* model, XP_Stream* inStream );

View file

@ -43,6 +43,12 @@ typedef struct PlayerCtxt {
PendingTile pendingTiles[MAX_TRAY_TILES];
} PlayerCtxt;
typedef struct _RecordWordsInfo {
XWStreamCtxt* stream;
XP_U16* nWordsP;
XP_U16 nWords;
} RecordWordsInfo;
typedef struct ModelVolatiles {
XW_UtilCtxt* util;
struct CurGameInfo* gi;
@ -55,6 +61,8 @@ typedef struct ModelVolatiles {
void* trayListenerData;
DictListener dictListenerFunc;
void* dictListenerData;
RecordWordsInfo rwi;
WordNotifierInfo wni;
XP_U16 nTilesOnBoard;
MPSLOT
} ModelVolatiles;

View file

@ -92,6 +92,8 @@ typedef struct ServerNonvolatiles {
RemoteAddress addresses[MAX_NUM_PLAYERS];
XWStreamCtxt* prevMoveStream; /* save it to print later */
XWStreamCtxt* prevWordsStream;
XP_U16 prevWordCount;
} ServerNonvolatiles;
struct ServerCtxt {
@ -174,7 +176,8 @@ getStateStr( XW_State st )
}
#endif
#ifdef DEBUG
#if 0
//def DEBUG
static void
logNewState( XW_State old, XW_State newst )
{
@ -739,9 +742,14 @@ makeRobotMove( ServerCtxt* server )
model_makeTurnFromMoveInfo( model, turn, &newMove );
if ( !!stream ) {
(void)model_checkMoveLegal( model, turn, stream, NULL );
XWStreamCtxt* wordsStream = mkServerStream( server );
WordNotifierInfo* ni =
model_initWordCounter( model, wordsStream,
&server->nv.prevWordCount );
(void)model_checkMoveLegal( model, turn, stream, ni );
XP_ASSERT( !server->nv.prevMoveStream );
server->nv.prevMoveStream = stream;
server->nv.prevWordsStream = wordsStream;
}
result = server_commitMove( server );
} else {
@ -848,8 +856,10 @@ showPrevScore( ServerCtxt* server )
stream_destroy( prevStream );
}
(void)util_userQuery( util, QUERY_ROBOT_MOVE, stream );
util_informMove( util, stream, server->nv.prevWordsStream,
server->nv.prevWordCount );
stream_destroy( stream );
stream_destroy( server->nv.prevWordsStream );
}
SETSTATE( server, server->nv.stateAfterShow );
} /* showPrevScore */

View file

@ -66,7 +66,6 @@ typedef enum {
typedef enum {
QUERY_COMMIT_TURN, /* 0 means cancel; 1 means commit */
QUERY_COMMIT_TRADE,
QUERY_ROBOT_MOVE,
QUERY_ROBOT_TRADE,
QUERY_LAST_COMMON
@ -131,6 +130,8 @@ typedef struct UtilVtable {
#ifdef XWFEATURE_TURNCHANGENOTIFY
void (*m_util_turnChanged)(XW_UtilCtxt* uc);
#endif
void (*m_util_informMove)( XW_UtilCtxt* uc, XWStreamCtxt* expl,
XWStreamCtxt* words, XP_U16 wordCount );
void (*m_util_notifyGameOver)( XW_UtilCtxt* uc );
XP_Bool (*m_util_hiliteCell)( XW_UtilCtxt* uc, XP_U16 col, XP_U16 row );
@ -227,6 +228,8 @@ struct XW_UtilCtxt {
# define util_turnChanged( uc )
#endif
#define util_informMove(uc,e,w,wc) \
(uc)->vtable->m_util_informMove( (uc),(e),(w),(wc) )
#define util_notifyGameOver( uc ) \
(uc)->vtable->m_util_notifyGameOver((uc))

View file

@ -282,7 +282,6 @@ curses_util_userQuery( XW_UtilCtxt* uc, UtilQueryID id, XWStreamCtxt* stream )
answers[numAnswers++] = "Cancel";
answers[numAnswers++] = "Ok";
break;
case QUERY_ROBOT_MOVE:
case QUERY_ROBOT_TRADE:
question = strFromStream( stream );
freeMe = XP_TRUE;
@ -332,6 +331,17 @@ cursesShowFinalScores( CursesAppGlobals* globals )
stream_destroy( stream );
} /* cursesShowFinalScores */
static void
curses_util_informMove( XW_UtilCtxt* uc, XWStreamCtxt* expl,
XWStreamCtxt* XP_UNUSED(words),
XP_U16 XP_UNUSED(wordCount) )
{
CursesAppGlobals* globals = (CursesAppGlobals*)uc->closure;
char* question = strFromStream( expl );
(void)cursesask( globals, question, 1, "Ok" );
free( question );
}
static void
curses_util_notifyGameOver( XW_UtilCtxt* uc )
{
@ -1465,6 +1475,7 @@ setupCursesUtilCallbacks( CursesAppGlobals* globals, XW_UtilCtxt* util )
util->vtable->m_util_userQuery = curses_util_userQuery;
util->vtable->m_util_userPickTile = curses_util_userPickTile;
util->vtable->m_util_trayHiddenChange = curses_util_trayHiddenChange;
util->vtable->m_util_informMove = curses_util_informMove;
util->vtable->m_util_notifyGameOver = curses_util_notifyGameOver;
util->vtable->m_util_hiliteCell = curses_util_hiliteCell;
util->vtable->m_util_engineProgressCallback =

View file

@ -1386,6 +1386,16 @@ gtkShowFinalScores( const CommonGlobals* cGlobals )
free( text );
} /* gtkShowFinalScores */
static void
gtk_util_informMove( XW_UtilCtxt* XP_UNUSED(uc), XWStreamCtxt* XP_UNUSED(expl),
XWStreamCtxt* words, XP_U16 wordCount )
{
XP_LOGF( "%s(wordCount=%d)", __func__, wordCount );
char* question = strFromStream( words/*expl*/ );
(void)gtkask( question, GTK_BUTTONS_OK );
free( question );
}
static void
gtk_util_notifyGameOver( XW_UtilCtxt* uc )
{
@ -1763,7 +1773,6 @@ gtk_util_userQuery( XW_UtilCtxt* XP_UNUSED(uc), UtilQueryID id,
case QUERY_COMMIT_TRADE:
question = "Are you sure you want to trade the selected tiles?";
break;
case QUERY_ROBOT_MOVE:
case QUERY_ROBOT_TRADE:
question = strFromStream( stream );
freeMe = XP_TRUE;
@ -1927,6 +1936,7 @@ setupGtkUtilCallbacks( GtkAppGlobals* globals, XW_UtilCtxt* util )
util->vtable->m_util_askPassword = gtk_util_askPassword;
util->vtable->m_util_trayHiddenChange = gtk_util_trayHiddenChange;
util->vtable->m_util_yOffsetChange = gtk_util_yOffsetChange;
util->vtable->m_util_informMove = gtk_util_informMove;
util->vtable->m_util_notifyGameOver = gtk_util_notifyGameOver;
util->vtable->m_util_hiliteCell = gtk_util_hiliteCell;
util->vtable->m_util_altKeyDown = gtk_util_altKeyDown;