snapshot: toward having a better description of the last move in

notifications.
This commit is contained in:
Eric House 2014-08-26 06:55:26 -07:00
parent 622760b71a
commit 2d08848715
16 changed files with 151 additions and 35 deletions

View file

@ -1603,19 +1603,22 @@ public final class R {
/** Text of progress indicator shown while check is being conducted
*/
public static final int msgs_progress=0x7f05009f;
/** body of warning notification reminder message
*/
public static final int nag_body_fmt=0x7f0502c8;
public static final int nag_days_fmt=0x7f0502cd;
public static final int nag_hours_fmt=0x7f0502cc;
public static final int nag_body_fmt=0x7f0502cb;
public static final int nag_days_fmt=0x7f0502ca;
public static final int nag_hours_fmt=0x7f0502c9;
public static final int nag_intervals=0x7f05008d;
public static final int nag_minutes_fmt=0x7f0502cb;
/** body of warning notification reminder message. First three
are used to build a string based on the length of time that's then
inserted in the fourth. E.g "PlayerName moved more than 2 day[s],
4 hour[s] ago."
*/
public static final int nag_minutes_fmt=0x7f0502c8;
/** Nagging: title of notification reminder message
*/
public static final int nag_title=0x7f0502c7;
/** above is inserted in this the last time I warn
*/
public static final int nag_warn_last_fmt=0x7f0502c9;
public static final int nag_warn_last_fmt=0x7f0502cc;
public static final int name_dict_fmt=0x7f050087;
/** text of checkbox. If this checkbox is checked, games created
for network play will by default have the hint feature
@ -2092,7 +2095,7 @@ public final class R {
public static final int prefs_names_summary=0x7f050134;
/** Used when prev player's name can't be looked up
*/
public static final int prev_player=0x7f0502ca;
public static final int prev_player=0x7f0502cd;
public static final int progress_title=0x7f0502be;
/**
*/

View file

@ -202,6 +202,16 @@ setJGI( JNIEnv* env, jobject jgi, const CurGameInfo* gi )
}
} /* setJGI */
static void
setLMI( JNIEnv* env, jobject jlmi, const LastMoveInfo* lmi )
{
setInt( env, jlmi, "score", lmi->score );
setInt( env, jlmi, "nTiles", lmi->nTiles );
setInt( env, jlmi, "moveType", lmi->moveType );
setString( env, jlmi, "name", lmi->name );
setString( env, jlmi, "word", lmi->word );
}
#ifdef COMMON_LAYOUT
static const SetInfo bd_ints[] = {
ARR_MEMBER( BoardDims, left )
@ -1135,17 +1145,19 @@ Java_org_eehouse_android_xw4_jni_XwJNI_model_1getNumTilesInTray
JNIEXPORT jstring JNICALL
Java_org_eehouse_android_xw4_jni_XwJNI_model_1getPlayersLastScore
(JNIEnv* env, jclass C, jint gamePtr, jint player )
( JNIEnv* env, jclass C, jint gamePtr, jint player, jobject jlmi )
{
jstring result = NULL;
XWJNI_START();
XP_ASSERT( !!state->game.model );
XP_UCHAR buf[64] = {0};
XP_U16 buflen = sizeof(buf);
if ( !model_getPlayersLastScore( state->game.model, player, buf,
&buflen ) ) {
LastMoveInfo lmi;
if ( !model_getPlayersLastScore( state->game.model, player, &lmi,
buf, &buflen ) ) {
buf[0] = '\0';
}
setLMI( env, jlmi, &lmi );
result = (*env)->NewStringUTF( env, buf );
XWJNI_END();
return result;

View file

@ -488,7 +488,7 @@ public class BTService extends XWService {
} else if ( haveGame &&
GameUtils.feedMessage( BTService.this, rowid,
buffer, addr,
m_btMsgSink ) ) {
m_btMsgSink, null ) ) {
postNotification( gameID, R.string.new_btmove_title,
R.string.new_move_body, rowid );
// do nothing

View file

@ -1415,8 +1415,10 @@ public class BoardDelegate extends DelegateBase
@Override
public void playerScoreHeld( int player )
{
LastMoveInfo lmi = new LastMoveInfo();
String expl = XwJNI.model_getPlayersLastScore( m_jniGamePtr,
player );
player, lmi );
expl = lmi.format( m_activity );
if ( expl.length() == 0 ) {
expl = getString( R.string.no_moves_made );
}

View file

@ -47,6 +47,7 @@ import org.eehouse.android.xw4.jni.*;
import org.eehouse.android.xw4.loc.LocUtils;
import org.eehouse.android.xw4.jni.CommsAddrRec.CommsConnType;
import org.eehouse.android.xw4.jni.CurGameInfo.DeviceRole;
import org.eehouse.android.xw4.jni.LastMoveInfo;
public class GameUtils {
@ -765,7 +766,7 @@ public class GameUtils {
public static boolean feedMessages( Context context, long rowid,
byte[][] msgs, CommsAddrRec ret,
MultiMsgSink sink )
MultiMsgSink sink, LastMoveInfo lmi )
{
boolean draw = false;
Assert.assertTrue( -1 != rowid );
@ -797,6 +798,10 @@ public class GameUtils {
DBUtils.saveThumbnail( context, lock, bitmap );
}
if ( null != lmi ) {
XwJNI.model_getPlayersLastScore( gamePtr, 0, lmi );
}
saveGame( context, gamePtr, gi, lock, false );
summarizeAndClose( context, lock, gamePtr, gi, feedImpl );
@ -813,12 +818,13 @@ public class GameUtils {
} // feedMessages
public static boolean feedMessage( Context context, long rowid, byte[] msg,
CommsAddrRec ret, MultiMsgSink sink )
CommsAddrRec ret, MultiMsgSink sink,
LastMoveInfo lmi )
{
Assert.assertTrue( DBUtils.ROWID_NOTFOUND != rowid );
byte[][] msgs = new byte[1][];
msgs[0] = msg;
return feedMessages( context, rowid, msgs, ret, sink );
return feedMessages( context, rowid, msgs, ret, sink, lmi );
}
// This *must* involve a reset if the language is changing!!!

View file

@ -51,6 +51,7 @@ import org.eehouse.android.xw4.jni.GameSummary;
import org.eehouse.android.xw4.jni.UtilCtxt;
import org.eehouse.android.xw4.jni.UtilCtxt.DevIDType;
import org.eehouse.android.xw4.jni.XwJNI;
import org.eehouse.android.xw4.jni.LastMoveInfo;
import org.eehouse.android.xw4.loc.LocUtils;
public class RelayService extends XWService
@ -365,23 +366,28 @@ public class RelayService extends XWService
startService( this ); // bad name: will *stop* threads too
}
private void setupNotification( String[] relayIDs )
private void setupNotifications( String[] relayIDs )
{
for ( String relayID : relayIDs ) {
long[] rowids = DBUtils.getRowIDsFor( this, relayID );
if ( null != rowids ) {
for ( long rowid : rowids ) {
setupNotification( rowid );
setupNotification( rowid, null );
}
}
}
}
private void setupNotification( long rowid )
private void setupNotification( long rowid, LastMoveInfo lmi )
{
Intent intent = GamesListDelegate.makeRowidIntent( this, rowid );
String msg = LocUtils.getString( this, R.string.notify_body_fmt,
GameUtils.getName( this, rowid ) );
String msg;
if ( null == lmi ) {
msg = LocUtils.getString( this, R.string.notify_body_fmt,
GameUtils.getName( this, rowid ) );
} else {
msg = lmi.format( this );
}
Utils.postNotification( this, intent, R.string.notify_title,
msg, (int)rowid );
}
@ -861,9 +867,10 @@ public class RelayService extends XWService
} else {
RelayMsgSink sink = new RelayMsgSink();
sink.setRowID( rowid );
LastMoveInfo lmi = new LastMoveInfo();
if ( GameUtils.feedMessage( this, rowid, msg, null,
sink ) ) {
setupNotification( rowid );
sink, lmi ) ) {
setupNotification( rowid, lmi );
} else {
DbgUtils.logf( "feedMessage(): background dropped it" );
}
@ -898,7 +905,7 @@ public class RelayService extends XWService
if ( BoardDelegate.feedMessages( rowIDs[ii], forOne )
|| GameUtils.feedMessages( this, rowIDs[ii],
forOne, null,
sink ) ) {
sink, null ) ) {
idsWMsgs.add( relayIDs[ii] );
} else {
DbgUtils.logf( "message for %s (rowid %d) not consumed",
@ -909,7 +916,7 @@ public class RelayService extends XWService
if ( 0 < idsWMsgs.size() ) {
String[] tmp = new String[idsWMsgs.size()];
idsWMsgs.toArray( tmp );
setupNotification( tmp );
setupNotifications( tmp );
}
sink.send( this );
}

View file

@ -776,7 +776,7 @@ public class SMSService extends XWService {
} else {
SMSMsgSink sink = new SMSMsgSink( this );
if ( GameUtils.feedMessage( this, rowid, msg, addr,
sink ) ) {
sink, null ) ) {
postNotification( gameID, R.string.new_smsmove_title,
getString(R.string.new_move_body),
rowid );

View file

@ -0,0 +1,35 @@
/* -*- compile-command: "find-and-ant.sh debug install"; -*- */
/*
* Copyright 2014 by Eric House (xwords@eehouse.org). All rights reserved.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation; either version 2 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
package org.eehouse.android.xw4.jni;
import android.content.Context;
public class LastMoveInfo {
public String name;
public int moveType;
public int score;
public int nTiles;
public String word;
public String format( Context context )
{
return String.format( "%s did move type %d", name, moveType );
}
}

View file

@ -271,7 +271,8 @@ public class XwJNI {
public static native int model_getNMoves( int gamePtr );
public static native int model_getNumTilesInTray( int gamePtr, int player );
public static native String model_getPlayersLastScore( int gamePtr,
int player );
int player,
LastMoveInfo lmi );
// Server
public static native void server_reset( int gamePtr );
public static native void server_handleUndo( int gamePtr );

View file

@ -29,6 +29,7 @@
typedef XP_Bool (*LastScoreCallback)( void* closure, XP_S16 player,
LastMoveInfo* lmi,
XP_UCHAR* expl, XP_U16* explLen );
typedef enum {

View file

@ -2189,9 +2189,9 @@ getFirstWord( const XP_UCHAR* word, XP_Bool XP_UNUSED(isLegal),
static void
scoreLastMove( ModelCtxt* model, MoveInfo* moveInfo, XP_U16 howMany,
XP_UCHAR* buf, XP_U16* bufLen )
LastMoveInfo* lmi, XP_UCHAR* buf, XP_U16* bufLen )
{
lmi->nTiles = moveInfo->nTiles;
if ( moveInfo->nTiles == 0 ) {
const XP_UCHAR* str = util_getUserString( model->vol.util, STR_PASSED );
XP_U16 len = XP_STRLEN( str );
@ -2224,6 +2224,8 @@ scoreLastMove( ModelCtxt* model, MoveInfo* moveInfo, XP_U16 howMany,
format = util_getUserString( model->vol.util, STRSD_SUMMARYSCORED );
*bufLen = XP_SNPRINTF( buf, *bufLen, format, data.word, score );
lmi->score = score;
XP_SNPRINTF( lmi->word, VSIZE(lmi->word), "%s", data.word );
}
} /* scoreLastMove */
@ -2374,12 +2376,14 @@ model_listWordsThrough( ModelCtxt* model, XP_U16 col, XP_U16 row,
XP_Bool
model_getPlayersLastScore( ModelCtxt* model, XP_S16 player,
LastMoveInfo* lmi,
XP_UCHAR* expl, XP_U16* explLen )
{
StackCtxt* stack = model->vol.stack;
XP_S16 nEntries, which;
StackEntry entry;
XP_Bool found = XP_FALSE;
XP_MEMSET( lmi, 0, sizeof(*lmi) );
XP_ASSERT( !!stack );
XP_ASSERT( player >= 0 );
@ -2398,13 +2402,16 @@ model_getPlayersLastScore( ModelCtxt* model, XP_S16 player,
if ( found ) { /* success? */
const XP_UCHAR* format;
XP_U16 nTiles;
lmi->name = model->vol.gi->players[player].name;
lmi->moveType = entry.moveType;
switch ( entry.moveType ) {
case MOVE_TYPE:
scoreLastMove( model, &entry.u.move.moveInfo,
nEntries - which, expl, explLen );
nEntries - which, lmi, expl, explLen );
break;
case TRADE_TYPE:
nTiles = entry.u.trade.oldTiles.nTiles;
lmi->nTiles = entry.u.trade.oldTiles.nTiles;
format = util_getUserString( model->vol.util, STRD_TRADED );
*explLen = XP_SNPRINTF( expl, *explLen, format, nTiles );
break;

View file

@ -76,6 +76,14 @@ typedef struct MoveInfo {
MoveInfoTile tiles[MAX_TRAY_TILES];
} MoveInfo;
typedef struct _LastMoveInfo {
const XP_UCHAR* name;
XP_U8 moveType;
XP_U16 score;
XP_U16 nTiles;
XP_UCHAR word[MAX_COLS+1];
} LastMoveInfo;
typedef XP_U8 TrayTile;
typedef struct TrayTileSet {
XP_U8 nTiles;
@ -264,6 +272,7 @@ XP_Bool getCurrentMoveScoreIfLegal( ModelCtxt* model, XP_S16 turn,
XP_S16 model_getPlayerScore( ModelCtxt* model, XP_S16 player );
XP_Bool model_getPlayersLastScore( ModelCtxt* model, XP_S16 player,
LastMoveInfo* info,
XP_UCHAR* expl, XP_U16* explLen );
#ifdef XWFEATURE_BOARDWORDS
void model_listWordsThrough( ModelCtxt* model, XP_U16 col, XP_U16 row,

View file

@ -29,12 +29,13 @@ extern "C" {
#endif
static XP_Bool
board_ScoreCallback( void* closure, XP_S16 player, XP_UCHAR* expl,
XP_U16* explLen)
board_ScoreCallback( void* closure, XP_S16 player,
LastMoveInfo* lmi,
XP_UCHAR* expl, XP_U16* explLen)
{
ModelCtxt* model = (ModelCtxt*)closure;
return model_getPlayersLastScore( model, player,
expl, explLen );
lmi, expl, explLen );
} /* board_ScoreCallback */
#ifdef XWFEATURE_SCOREONEPASS

View file

@ -53,6 +53,7 @@
#include "draw.h"
#include "game.h"
#include "movestak.h"
#include "gtkask.h"
#include "gtkaskm.h"
#include "gtkchat.h"
@ -2014,11 +2015,13 @@ gtk_util_playerScoreHeld( XW_UtilCtxt* uc, XP_U16 player )
GtkGameGlobals* globals = (GtkGameGlobals*)uc->closure;
XP_UCHAR scoreExpl[48] = {0};
XP_UCHAR scoreExpl[128] = {0};
XP_U16 explLen = sizeof(scoreExpl);
LastMoveInfo lmi;
if ( model_getPlayersLastScore( globals->cGlobals.game.model,
player, scoreExpl, &explLen ) ) {
player, &lmi, scoreExpl, &explLen ) ) {
formatLMI( &lmi, scoreExpl, VSIZE(scoreExpl) );
(void)gtkask( globals->window, scoreExpl, GTK_BUTTONS_OK, NULL );
}
}

View file

@ -29,6 +29,7 @@
# include <execinfo.h> /* for backtrace */
#endif
#include "movestak.h"
#include "linuxutl.h"
#include "main.h"
#include "linuxdict.h"
@ -570,6 +571,32 @@ linux_getErrString( UtilErrID id, XP_Bool* silent )
return (XP_UCHAR*)message;
} /* linux_getErrString */
void
formatLMI( const LastMoveInfo* lmi, XP_UCHAR* buf, XP_U16 len )
{
const XP_UCHAR* name = lmi->name;
switch( lmi->moveType ) {
case MOVE_TYPE:
if ( 0 == lmi->nTiles ) {
XP_SNPRINTF( buf, len, "%s passed", name );
} else {
XP_SNPRINTF( buf, len, "%s played %s for %d points", name,
lmi->word, lmi->score );
}
break;
case TRADE_TYPE:
XP_SNPRINTF( buf, len, "%s traded %d tiles",
name, lmi->nTiles );
break;
case PHONY_TYPE:
XP_SNPRINTF( buf, len, "%s lost a turn", name );
break;
default:
XP_ASSERT(0);
break;
}
}
void
formatConfirmTrade( const XP_UCHAR** tiles, XP_U16 nTiles,
char* buf, XP_U16 buflen )

View file

@ -24,6 +24,7 @@
#include "xptypes.h"
#include "dictnry.h"
#include "model.h"
#include "util.h"
#include "main.h"
@ -40,6 +41,7 @@ const XP_UCHAR* linux_getErrString( UtilErrID id, XP_Bool* silent );
void formatConfirmTrade( const XP_UCHAR** tiles, XP_U16 nTiles, char* buf,
XP_U16 buflen );
void formatLMI( const LastMoveInfo* lmi, XP_UCHAR* buf, XP_U16 len );
void initNoConnStorage( CommonGlobals* cGlobals );
XP_Bool storeNoConnMsg( CommonGlobals* cGlobals, const XP_U8* msg, XP_U16 len,