track games by row id (an sqlite built-in) rather than name (so that

names can be changed without constraints)
This commit is contained in:
Andy2 2011-08-03 06:53:42 -07:00
parent 294df7055e
commit 173e2e8423
9 changed files with 283 additions and 283 deletions

View file

@ -55,7 +55,7 @@ import org.eehouse.android.xw4.jni.CurGameInfo.DeviceRole;
public class BoardActivity extends XWActivity public class BoardActivity extends XWActivity
implements TransportProcs.TPMsgHandler { implements TransportProcs.TPMsgHandler {
public static final String INTENT_KEY_NAME = "name"; public static final String INTENT_KEY_ROWID = "rowid";
public static final String INTENT_KEY_CHAT = "chat"; public static final String INTENT_KEY_CHAT = "chat";
private static final int DLG_OKONLY = DlgDelegate.DIALOG_LAST + 1; private static final int DLG_OKONLY = DlgDelegate.DIALOG_LAST + 1;
@ -84,7 +84,7 @@ public class BoardActivity extends XWActivity
private Handler m_handler = null; private Handler m_handler = null;
private TimerRunnable[] m_timers; private TimerRunnable[] m_timers;
private Runnable m_screenTimer; private Runnable m_screenTimer;
private String m_name; private long m_rowid;
private Toolbar m_toolbar; private Toolbar m_toolbar;
private ArrayList<String> m_pendingChats = new ArrayList<String>(); private ArrayList<String> m_pendingChats = new ArrayList<String>();
@ -170,7 +170,7 @@ public class BoardActivity extends XWActivity
waitCloseGame( false ); waitCloseGame( false );
GameUtils.deleteGame( BoardActivity.this, GameUtils.deleteGame( BoardActivity.this,
m_name, false ); m_rowid, false );
// Intent intent = new Intent(); // Intent intent = new Intent();
// intent.putExtra( "delete", true ); // intent.putExtra( "delete", true );
// intent.putExtra( "path", m_path ); // intent.putExtra( "path", m_path );
@ -334,7 +334,7 @@ public class BoardActivity extends XWActivity
m_volKeysZoom = CommonPrefs.getVolKeysZoom( this ); m_volKeysZoom = CommonPrefs.getVolKeysZoom( this );
Intent intent = getIntent(); Intent intent = getIntent();
m_name = intent.getStringExtra( INTENT_KEY_NAME ); m_rowid = intent.getLongExtra( INTENT_KEY_ROWID, -1 );
m_haveInvited = intent.getBooleanExtra( GameUtils.INVITED, false ); m_haveInvited = intent.getBooleanExtra( GameUtils.INVITED, false );
setBackgroundColor(); setBackgroundColor();
@ -1034,7 +1034,7 @@ public class BoardActivity extends XWActivity
post( new Runnable() { post( new Runnable() {
public void run() { public void run() {
DBUtils.appendChatHistory( BoardActivity.this, DBUtils.appendChatHistory( BoardActivity.this,
m_name, msg, false ); m_rowid, msg, false );
startChatActivity(); startChatActivity();
} }
} ); } );
@ -1045,7 +1045,7 @@ public class BoardActivity extends XWActivity
{ {
if ( 0 == m_jniGamePtr ) { if ( 0 == m_jniGamePtr ) {
Assert.assertNull( m_gameLock ); Assert.assertNull( m_gameLock );
m_gameLock = new GameUtils.GameLock( m_name, true ).lock(); m_gameLock = new GameUtils.GameLock( m_rowid, true ).lock();
byte[] stream = GameUtils.savedGame( this, m_gameLock ); byte[] stream = GameUtils.savedGame( this, m_gameLock );
XwJNI.gi_from_stream( m_gi, stream ); XwJNI.gi_from_stream( m_gi, stream );
@ -1108,13 +1108,13 @@ public class BoardActivity extends XWActivity
m_jniThread.handle( JNICmd.CMD_START ); m_jniThread.handle( JNICmd.CMD_START );
if ( !CommonPrefs.getHideTitleBar( this ) ) { if ( !CommonPrefs.getHideTitleBar( this ) ) {
setTitle( GameUtils.gameName( this, m_name ) ); setTitle( GameUtils.gameName( this, m_rowid ) );
} }
m_toolbar = new Toolbar( this ); m_toolbar = new Toolbar( this );
populateToolbar(); populateToolbar();
int flags = DBUtils.getMsgFlags( m_name ); int flags = DBUtils.getMsgFlags( m_rowid );
if ( 0 != (GameSummary.MSG_FLAGS_CHAT & flags) ) { if ( 0 != (GameSummary.MSG_FLAGS_CHAT & flags) ) {
startChatActivity(); startChatActivity();
} }
@ -1122,7 +1122,7 @@ public class BoardActivity extends XWActivity
m_jniThread.handle( JNIThread.JNICmd.CMD_POST_OVER ); m_jniThread.handle( JNIThread.JNICmd.CMD_POST_OVER );
} }
if ( 0 != flags ) { if ( 0 != flags ) {
DBUtils.setMsgFlags( m_name, GameSummary.MSG_FLAGS_NONE ); DBUtils.setMsgFlags( m_rowid, GameSummary.MSG_FLAGS_NONE );
} }
trySendChats(); trySendChats();
@ -1285,7 +1285,7 @@ public class BoardActivity extends XWActivity
private void startChatActivity() private void startChatActivity()
{ {
Intent intent = new Intent( this, ChatActivity.class ); Intent intent = new Intent( this, ChatActivity.class );
intent.putExtra( BoardActivity.INTENT_KEY_NAME, m_name ); intent.putExtra( BoardActivity.INTENT_KEY_ROWID, m_rowid );
startActivityForResult( intent, CHAT_REQUEST ); startActivityForResult( intent, CHAT_REQUEST );
} }

View file

@ -35,7 +35,7 @@ import android.widget.LinearLayout;
public class ChatActivity extends XWActivity implements View.OnClickListener { public class ChatActivity extends XWActivity implements View.OnClickListener {
private String m_name; private long m_rowid;
@Override @Override
public void onCreate( Bundle savedInstanceState ) public void onCreate( Bundle savedInstanceState )
@ -44,9 +44,9 @@ public class ChatActivity extends XWActivity implements View.OnClickListener {
setContentView( R.layout.chat ); setContentView( R.layout.chat );
m_name = getIntent().getStringExtra( BoardActivity.INTENT_KEY_NAME ); m_rowid = getIntent().getLongExtra( BoardActivity.INTENT_KEY_ROWID, -1 );
DBUtils.HistoryPair[] pairs = DBUtils.getChatHistory( this, m_name ); DBUtils.HistoryPair[] pairs = DBUtils.getChatHistory( this, m_rowid );
if ( null != pairs ) { if ( null != pairs ) {
LinearLayout layout = (LinearLayout)findViewById( R.id.chat_history ); LinearLayout layout = (LinearLayout)findViewById( R.id.chat_history );
LayoutInflater factory = LayoutInflater.from( this ); LayoutInflater factory = LayoutInflater.from( this );
@ -65,7 +65,7 @@ public class ChatActivity extends XWActivity implements View.OnClickListener {
((Button)findViewById( R.id.send_button )).setOnClickListener( this ); ((Button)findViewById( R.id.send_button )).setOnClickListener( this );
String fmt = getString( R.string.chat_titlef ); String fmt = getString( R.string.chat_titlef );
setTitle( String.format( fmt, GameUtils.gameName( this, m_name ) ) ); setTitle( String.format( fmt, GameUtils.gameName( this, m_rowid ) ) );
} }
@Override @Override
@ -81,7 +81,7 @@ public class ChatActivity extends XWActivity implements View.OnClickListener {
{ {
boolean handled = R.id.chat_menu_clear == item.getItemId(); boolean handled = R.id.chat_menu_clear == item.getItemId();
if ( handled ) { if ( handled ) {
DBUtils.clearChatHistory( this, m_name ); DBUtils.clearChatHistory( this, m_rowid );
LinearLayout layout = LinearLayout layout =
(LinearLayout)findViewById( R.id.chat_history ); (LinearLayout)findViewById( R.id.chat_history );
layout.removeAllViews(); layout.removeAllViews();
@ -99,7 +99,7 @@ public class ChatActivity extends XWActivity implements View.OnClickListener {
if ( null == text || text.length() == 0 ) { if ( null == text || text.length() == 0 ) {
setResult( Activity.RESULT_CANCELED ); setResult( Activity.RESULT_CANCELED );
} else { } else {
DBUtils.appendChatHistory( this, m_name, text, true ); DBUtils.appendChatHistory( this, m_rowid, text, true );
Intent result = new Intent(); Intent result = new Intent();
result.putExtra( BoardActivity.INTENT_KEY_CHAT, text ); result.putExtra( BoardActivity.INTENT_KEY_CHAT, text );

View file

@ -39,9 +39,10 @@ import org.eehouse.android.xw4.jni.*;
public class DBUtils { public class DBUtils {
private static final String ROW_ID = "rowid"; private static final String ROW_ID = "rowid";
private static final String ROW_ID_FMT = "rowid=%d";
public static interface DBChangeListener { public static interface DBChangeListener {
public void pathSaved( String path ); public void gameSaved( long rowid );
} }
private static HashSet<DBChangeListener> s_listeners = private static HashSet<DBChangeListener> s_listeners =
new HashSet<DBChangeListener>(); new HashSet<DBChangeListener>();
@ -66,11 +67,11 @@ public class DBUtils {
boolean sourceLocal; boolean sourceLocal;
} }
public static GameSummary getSummary( Context context, String file, public static GameSummary getSummary( Context context, long rowid,
boolean wait ) boolean wait )
{ {
GameSummary result = null; GameSummary result = null;
GameUtils.GameLock lock = new GameUtils.GameLock( file, false ); GameUtils.GameLock lock = new GameUtils.GameLock( rowid, false );
if ( wait ) { if ( wait ) {
result = getSummary( context, lock.lock() ); result = getSummary( context, lock.lock() );
lock.unlock(); lock.unlock();
@ -101,7 +102,7 @@ public class DBUtils {
DBHelper.SCORES, DBHelper.HASMSGS, DBHelper.SCORES, DBHelper.HASMSGS,
DBHelper.LASTPLAY_TIME DBHelper.LASTPLAY_TIME
}; };
String selection = DBHelper.FILE_NAME + "=\"" + lock.getPath() + "\""; String selection = String.format( ROW_ID_FMT, lock.getRowid() );
Cursor cursor = db.query( DBHelper.TABLE_NAME_SUM, columns, Cursor cursor = db.query( DBHelper.TABLE_NAME_SUM, columns,
selection, null, null, null, null ); selection, null, null, null, null );
@ -203,13 +204,14 @@ public class DBUtils {
GameSummary summary ) GameSummary summary )
{ {
Assert.assertTrue( lock.canWrite() ); Assert.assertTrue( lock.canWrite() );
String path = lock.getPath(); long rowid = lock.getRowid();
String selection = String.format( ROW_ID_FMT, rowid );
initDB( context ); initDB( context );
synchronized( s_dbHelper ) { synchronized( s_dbHelper ) {
SQLiteDatabase db = s_dbHelper.getWritableDatabase(); SQLiteDatabase db = s_dbHelper.getWritableDatabase();
if ( null == summary ) { if ( null == summary ) {
String selection = DBHelper.FILE_NAME + "=\"" + path + "\"";
db.delete( DBHelper.TABLE_NAME_SUM, selection, null ); db.delete( DBHelper.TABLE_NAME_SUM, selection, null );
} else { } else {
ContentValues values = new ContentValues(); ContentValues values = new ContentValues();
@ -240,12 +242,11 @@ public class DBUtils {
} }
values.put( DBHelper.SERVERROLE, summary.serverRole.ordinal() ); values.put( DBHelper.SERVERROLE, summary.serverRole.ordinal() );
String selection = DBHelper.FILE_NAME + "=\"" + path + "\"";
long result = db.update( DBHelper.TABLE_NAME_SUM, long result = db.update( DBHelper.TABLE_NAME_SUM,
values, selection, null ); values, selection, null );
Assert.assertTrue( result >= 0 ); Assert.assertTrue( result >= 0 );
} }
notifyListeners( path ); notifyListeners( rowid );
db.close(); db.close();
} }
} // saveSummary } // saveSummary
@ -270,12 +271,12 @@ public class DBUtils {
return result; return result;
} }
public static void setMsgFlags( String path, int flags ) public static void setMsgFlags( long rowid, int flags )
{ {
synchronized( s_dbHelper ) { synchronized( s_dbHelper ) {
SQLiteDatabase db = s_dbHelper.getWritableDatabase(); SQLiteDatabase db = s_dbHelper.getWritableDatabase();
String selection = DBHelper.FILE_NAME + "=\"" + path + "\""; String selection = String.format( ROW_ID_FMT, rowid );
ContentValues values = new ContentValues(); ContentValues values = new ContentValues();
values.put( DBHelper.HASMSGS, flags ); values.put( DBHelper.HASMSGS, flags );
@ -284,21 +285,21 @@ public class DBUtils {
Assert.assertTrue( result == 1 ); Assert.assertTrue( result == 1 );
db.close(); db.close();
} }
notifyListeners( path ); notifyListeners( rowid );
} }
public static int getMsgFlags( String path ) public static int getMsgFlags( long rowid )
{ {
int flags = GameSummary.MSG_FLAGS_NONE; int flags = GameSummary.MSG_FLAGS_NONE;
synchronized( s_dbHelper ) { synchronized( s_dbHelper ) {
SQLiteDatabase db = s_dbHelper.getReadableDatabase(); SQLiteDatabase db = s_dbHelper.getReadableDatabase();
String selection = DBHelper.FILE_NAME + "=\"" + path + "\""; String selection = String.format( ROW_ID_FMT, rowid );
String[] columns = { DBHelper.HASMSGS }; String[] columns = { DBHelper.HASMSGS };
Cursor cursor = db.query( DBHelper.TABLE_NAME_SUM, columns, Cursor cursor = db.query( DBHelper.TABLE_NAME_SUM, columns,
selection, null, null, null, null ); selection, null, null, null, null );
if ( 1 == cursor.getCount() && cursor.moveToFirst() ) { if ( 1 == cursor.getCount() && cursor.moveToFirst() ) {
flags = cursor.getInt( cursor flags =
.getColumnIndex(DBHelper.HASMSGS)); cursor.getInt( cursor.getColumnIndex(DBHelper.HASMSGS));
} }
cursor.close(); cursor.close();
db.close(); db.close();
@ -306,47 +307,18 @@ public class DBUtils {
return flags; return flags;
} }
public static String getPathFor( Context context, String room, public static long getRowIDFor( Context context, String relayID )
int lang, int nPlayers )
{ {
String result = null; long result = -1;
initDB( context ); initDB( context );
synchronized( s_dbHelper ) { synchronized( s_dbHelper ) {
SQLiteDatabase db = s_dbHelper.getReadableDatabase(); SQLiteDatabase db = s_dbHelper.getReadableDatabase();
String[] columns = { DBHelper.FILE_NAME }; String[] columns = { ROW_ID };
String selection =
String.format( "%s = '%s' AND %s = %d AND %s = %d",
DBHelper.ROOMNAME, room,
DBHelper.DICTLANG, lang,
DBHelper.NUM_PLAYERS, nPlayers );
Cursor cursor = db.query( DBHelper.TABLE_NAME_SUM, columns,
selection, null, null, null, null );
if ( 1 == cursor.getCount() && cursor.moveToFirst() ) {
result = cursor.getString( cursor
.getColumnIndex(DBHelper.FILE_NAME));
}
cursor.close();
db.close();
}
Utils.logf( "getPathFor(%s)=>%s", room, result );
return result;
}
public static String getPathFor( Context context, String relayID )
{
String result = null;
initDB( context );
synchronized( s_dbHelper ) {
SQLiteDatabase db = s_dbHelper.getReadableDatabase();
String[] columns = { DBHelper.FILE_NAME };
String selection = DBHelper.RELAYID + "='" + relayID + "'"; String selection = DBHelper.RELAYID + "='" + relayID + "'";
Cursor cursor = db.query( DBHelper.TABLE_NAME_SUM, columns, Cursor cursor = db.query( DBHelper.TABLE_NAME_SUM, columns,
selection, null, null, null, null ); selection, null, null, null, null );
if ( 1 == cursor.getCount() && cursor.moveToFirst() ) { if ( 1 == cursor.getCount() && cursor.moveToFirst() ) {
result = cursor.getString( cursor result = cursor.getLong( cursor.getColumnIndex(ROW_ID) );
.getColumnIndex(DBHelper.FILE_NAME));
} }
cursor.close(); cursor.close();
db.close(); db.close();
@ -354,15 +326,14 @@ public class DBUtils {
return result; return result;
} }
public static String getPathForOpen( Context context, String room, public static long getRowIDForOpen( Context context, String room,
// String inviteID,
int lang, int nPlayers ) int lang, int nPlayers )
{ {
String result = null; long result = -1;
initDB( context ); initDB( context );
synchronized( s_dbHelper ) { synchronized( s_dbHelper ) {
SQLiteDatabase db = s_dbHelper.getReadableDatabase(); SQLiteDatabase db = s_dbHelper.getReadableDatabase();
String[] columns = { DBHelper.FILE_NAME }; String[] columns = { ROW_ID };
String selection = DBHelper.ROOMNAME + "='" + room + "' AND " String selection = DBHelper.ROOMNAME + "='" + room + "' AND "
// + DBHelper.INVITEID + "='" + inviteID + "' AND " // + DBHelper.INVITEID + "='" + inviteID + "' AND "
+ DBHelper.DICTLANG + "=" + lang + " AND " + DBHelper.DICTLANG + "=" + lang + " AND "
@ -370,9 +341,7 @@ public class DBUtils {
Cursor cursor = db.query( DBHelper.TABLE_NAME_SUM, columns, Cursor cursor = db.query( DBHelper.TABLE_NAME_SUM, columns,
selection, null, null, null, null ); selection, null, null, null, null );
if ( 1 == cursor.getCount() && cursor.moveToFirst() ) { if ( 1 == cursor.getCount() && cursor.moveToFirst() ) {
result = cursor.getString( cursor result = cursor.getLong( cursor.getColumnIndex(ROW_ID) );
.getColumnIndex(DBHelper.FILE_NAME));
} }
cursor.close(); cursor.close();
db.close(); db.close();
@ -494,16 +463,41 @@ public class DBUtils {
} }
} }
public static void saveGame( Context context, GameUtils.GameLock lock, public static GameUtils.GameLock saveNewGame( Context context, byte[] bytes )
byte[] bytes, boolean setCreate )
{ {
Assert.assertTrue( lock.canWrite() ); GameUtils.GameLock lock = null;
String path = lock.getPath();
initDB( context ); initDB( context );
synchronized( s_dbHelper ) { synchronized( s_dbHelper ) {
SQLiteDatabase db = s_dbHelper.getWritableDatabase(); SQLiteDatabase db = s_dbHelper.getWritableDatabase();
String selection = DBHelper.FILE_NAME + "=\"" + path + "\""; ContentValues values = new ContentValues();
values.put( DBHelper.SNAPSHOT, bytes );
long timestamp = new Date().getTime();
values.put( DBHelper.CREATE_TIME, timestamp );
values.put( DBHelper.LASTPLAY_TIME, timestamp );
long rowid = db.insert( DBHelper.TABLE_NAME_SUM, null, values );
lock = new GameUtils.GameLock( rowid, true ).lock();
notifyListeners( rowid );
}
return lock;
}
public static long saveGame( Context context, GameUtils.GameLock lock,
byte[] bytes, boolean setCreate )
{
Assert.assertTrue( lock.canWrite() );
long rowid = lock.getRowid();
initDB( context );
synchronized( s_dbHelper ) {
SQLiteDatabase db = s_dbHelper.getWritableDatabase();
String selection = String.format( ROW_ID_FMT, rowid );
ContentValues values = new ContentValues(); ContentValues values = new ContentValues();
values.put( DBHelper.SNAPSHOT, bytes ); values.put( DBHelper.SNAPSHOT, bytes );
@ -516,26 +510,31 @@ public class DBUtils {
int result = db.update( DBHelper.TABLE_NAME_SUM, int result = db.update( DBHelper.TABLE_NAME_SUM,
values, selection, null ); values, selection, null );
if ( 0 == result ) { if ( 0 == result ) {
values.put( DBHelper.FILE_NAME, path ); Assert.fail();
long row = db.insert( DBHelper.TABLE_NAME_SUM, null, values ); // values.put( DBHelper.FILE_NAME, path );
Assert.assertTrue( row >= 0 ); // rowid = db.insert( DBHelper.TABLE_NAME_SUM, null, values );
// Utils.logf( "insert=>%d", rowid );
// Assert.assertTrue( row >= 0 );
} }
db.close(); db.close();
} }
notifyListeners( path ); if ( -1 != rowid ) {
notifyListeners( rowid );
}
return rowid;
} }
public static byte[] loadGame( Context context, GameUtils.GameLock lock ) public static byte[] loadGame( Context context, GameUtils.GameLock lock )
{ {
String path = lock.getPath(); long rowid = lock.getRowid();
Assert.assertNotNull( path ); Assert.assertTrue( -1 != rowid );
byte[] result = null; byte[] result = null;
initDB( context ); initDB( context );
synchronized( s_dbHelper ) { synchronized( s_dbHelper ) {
SQLiteDatabase db = s_dbHelper.getReadableDatabase(); SQLiteDatabase db = s_dbHelper.getReadableDatabase();
String[] columns = { DBHelper.SNAPSHOT }; String[] columns = { DBHelper.SNAPSHOT };
String selection = DBHelper.FILE_NAME + "=\"" + path + "\""; String selection = String.format( ROW_ID_FMT, rowid );
Cursor cursor = db.query( DBHelper.TABLE_NAME_SUM, columns, Cursor cursor = db.query( DBHelper.TABLE_NAME_SUM, columns,
selection, null, null, null, null ); selection, null, null, null, null );
if ( 1 == cursor.getCount() && cursor.moveToFirst() ) { if ( 1 == cursor.getCount() && cursor.moveToFirst() ) {
@ -554,30 +553,33 @@ public class DBUtils {
initDB( context ); initDB( context );
synchronized( s_dbHelper ) { synchronized( s_dbHelper ) {
SQLiteDatabase db = s_dbHelper.getWritableDatabase(); SQLiteDatabase db = s_dbHelper.getWritableDatabase();
String selection = DBHelper.FILE_NAME + "=\"" + lock.getPath() + "\""; String selection = String.format( ROW_ID_FMT, lock.getRowid() );
db.delete( DBHelper.TABLE_NAME_SUM, selection, null ); db.delete( DBHelper.TABLE_NAME_SUM, selection, null );
db.close(); db.close();
} }
notifyListeners( lock.getPath() ); notifyListeners( lock.getRowid() );
} }
public static String[] gamesList( Context context ) public static long[] gamesList( Context context )
{ {
ArrayList<String> al = new ArrayList<String>(); long[] result = null;
initDB( context ); initDB( context );
synchronized( s_dbHelper ) { synchronized( s_dbHelper ) {
SQLiteDatabase db = s_dbHelper.getReadableDatabase(); SQLiteDatabase db = s_dbHelper.getReadableDatabase();
String[] columns = { DBHelper.FILE_NAME }; String[] columns = { ROW_ID };
String orderBy = DBHelper.CREATE_TIME + " DESC"; String orderBy = DBHelper.CREATE_TIME + " DESC";
Cursor cursor = db.query( DBHelper.TABLE_NAME_SUM, columns, Cursor cursor = db.query( DBHelper.TABLE_NAME_SUM, columns,
null, null, null, null, orderBy ); null, null, null, null, orderBy );
if ( 0 < cursor.getCount() ) { int count = cursor.getCount();
int index = cursor.getColumnIndex( DBHelper.FILE_NAME ); result = new long[count];
if ( 0 < count ) {
int index = cursor.getColumnIndex( ROW_ID );
cursor.moveToFirst(); cursor.moveToFirst();
for ( ; ; ) {
al.add( cursor.getString( index ) ); for ( int ii = 0; ; ++ii ) {
result[ii] = cursor.getLong( index );
if ( cursor.isLast() ) { if ( cursor.isLast() ) {
break; break;
} }
@ -588,14 +590,14 @@ public class DBUtils {
db.close(); db.close();
} }
return al.toArray( new String[al.size()] ); return result;
} }
public static HistoryPair[] getChatHistory( Context context, String path ) public static HistoryPair[] getChatHistory( Context context, long rowid )
{ {
HistoryPair[] result = null; HistoryPair[] result = null;
final String localPrefix = context.getString( R.string.chat_local_id ); final String localPrefix = context.getString( R.string.chat_local_id );
String history = getChatHistoryStr( context, path ); String history = getChatHistoryStr( context, rowid );
if ( null != history ) { if ( null != history ) {
String[] msgs = history.split( "\n" ); String[] msgs = history.split( "\n" );
result = new HistoryPair[msgs.length]; result = new HistoryPair[msgs.length];
@ -608,7 +610,7 @@ public class DBUtils {
return result; return result;
} }
private static String getChatHistoryStr( Context context, String path ) private static String getChatHistoryStr( Context context, long rowid )
{ {
String result = null; String result = null;
initDB( context ); initDB( context );
@ -616,7 +618,7 @@ public class DBUtils {
SQLiteDatabase db = s_dbHelper.getReadableDatabase(); SQLiteDatabase db = s_dbHelper.getReadableDatabase();
String[] columns = { DBHelper.CHAT_HISTORY }; String[] columns = { DBHelper.CHAT_HISTORY };
String selection = DBHelper.FILE_NAME + "=\"" + path + "\""; String selection = String.format( ROW_ID_FMT, rowid );
Cursor cursor = db.query( DBHelper.TABLE_NAME_SUM, columns, Cursor cursor = db.query( DBHelper.TABLE_NAME_SUM, columns,
selection, null, null, null, null ); selection, null, null, null, null );
if ( 1 == cursor.getCount() && cursor.moveToFirst() ) { if ( 1 == cursor.getCount() && cursor.moveToFirst() ) {
@ -630,24 +632,24 @@ public class DBUtils {
return result; return result;
} }
public static void appendChatHistory( Context context, String path, public static void appendChatHistory( Context context, long rowid,
String msg, boolean local ) String msg, boolean local )
{ {
Assert.assertNotNull( msg ); Assert.assertNotNull( msg );
int id = local ? R.string.chat_local_id : R.string.chat_other_id; int id = local ? R.string.chat_local_id : R.string.chat_other_id;
msg = context.getString( id ) + msg; msg = context.getString( id ) + msg;
String cur = getChatHistoryStr( context, path ); String cur = getChatHistoryStr( context, rowid );
if ( null != cur ) { if ( null != cur ) {
msg = cur + "\n" + msg; msg = cur + "\n" + msg;
} }
saveChatHistory( context, path, msg ); saveChatHistory( context, rowid, msg );
} // appendChatHistory } // appendChatHistory
public static void clearChatHistory( Context context, String path ) public static void clearChatHistory( Context context, long rowid )
{ {
saveChatHistory( context, path, null ); saveChatHistory( context, rowid, null );
} }
public static void setDBChangeListener( DBChangeListener listener ) public static void setDBChangeListener( DBChangeListener listener )
@ -668,14 +670,14 @@ public class DBUtils {
// Chat is independent of the GameLock mechanism because it's not // Chat is independent of the GameLock mechanism because it's not
// touching the SNAPSHOT column. // touching the SNAPSHOT column.
private static void saveChatHistory( Context context, String path, private static void saveChatHistory( Context context, long rowid,
String history ) String history )
{ {
initDB( context ); initDB( context );
synchronized( s_dbHelper ) { synchronized( s_dbHelper ) {
SQLiteDatabase db = s_dbHelper.getWritableDatabase(); SQLiteDatabase db = s_dbHelper.getWritableDatabase();
String selection = DBHelper.FILE_NAME + "=\"" + path + "\""; String selection = String.format( ROW_ID_FMT, rowid );
ContentValues values = new ContentValues(); ContentValues values = new ContentValues();
if ( null != history ) { if ( null != history ) {
values.put( DBHelper.CHAT_HISTORY, history ); values.put( DBHelper.CHAT_HISTORY, history );
@ -724,12 +726,12 @@ public class DBUtils {
} }
} }
private static void notifyListeners( String path ) private static void notifyListeners( long rowid )
{ {
synchronized( s_listeners ) { synchronized( s_listeners ) {
Iterator<DBChangeListener> iter = s_listeners.iterator(); Iterator<DBChangeListener> iter = s_listeners.iterator();
while ( iter.hasNext() ) { while ( iter.hasNext() ) {
iter.next().pathSaved( path ); iter.next().gameSaved( rowid );
} }
} }
} }

View file

@ -82,7 +82,7 @@ public class GameConfig extends XWActivity
private View m_connectSet; // really a LinearLayout private View m_connectSet; // really a LinearLayout
private Spinner m_roomChoose; private Spinner m_roomChoose;
// private Button m_configureButton; // private Button m_configureButton;
private String m_name; private long m_rowid;
private CurGameInfo m_gi; private CurGameInfo m_gi;
private CurGameInfo m_giOrig; private CurGameInfo m_giOrig;
private GameUtils.GameLock m_gameLock; private GameUtils.GameLock m_gameLock;
@ -371,7 +371,7 @@ public class GameConfig extends XWActivity
m_cp = CommonPrefs.get( this ); m_cp = CommonPrefs.get( this );
Intent intent = getIntent(); Intent intent = getIntent();
m_name = intent.getStringExtra( BoardActivity.INTENT_KEY_NAME ); m_rowid = intent.getLongExtra( BoardActivity.INTENT_KEY_ROWID, -1 );
setContentView(R.layout.game_config); setContentView(R.layout.game_config);
@ -400,7 +400,7 @@ public class GameConfig extends XWActivity
m_giOrig = new CurGameInfo( this ); m_giOrig = new CurGameInfo( this );
// Lock in case we're going to config. We *could* re-get the // Lock in case we're going to config. We *could* re-get the
// lock once the user decides to make changes. PENDING. // lock once the user decides to make changes. PENDING.
m_gameLock = new GameUtils.GameLock( m_name, true ).lock(); m_gameLock = new GameUtils.GameLock( m_rowid, true ).lock();
GameUtils.loadMakeGame( this, gamePtr, m_giOrig, m_gameLock ); GameUtils.loadMakeGame( this, gamePtr, m_giOrig, m_gameLock );
m_gameStarted = XwJNI.model_getNMoves( gamePtr ) > 0 m_gameStarted = XwJNI.model_getNMoves( gamePtr ) > 0
|| XwJNI.comms_isConnected( gamePtr ); || XwJNI.comms_isConnected( gamePtr );
@ -955,7 +955,7 @@ public class GameConfig extends XWActivity
if ( m_notNetworkedGame || m_car.ip_relay_invite.length() > 0 ) { if ( m_notNetworkedGame || m_car.ip_relay_invite.length() > 0 ) {
m_gameLock.unlock(); m_gameLock.unlock();
m_gameLock = null; m_gameLock = null;
GameUtils.launchGameAndFinish( this, m_name ); GameUtils.launchGameAndFinish( this, m_rowid );
} else { } else {
showOKOnlyDialog( R.string.no_empty_rooms ); showOKOnlyDialog( R.string.no_empty_rooms );
} }
@ -974,7 +974,7 @@ public class GameConfig extends XWActivity
String fmt = getString( m_notNetworkedGame ? String fmt = getString( m_notNetworkedGame ?
R.string.title_game_configf R.string.title_game_configf
: R.string.title_gamenet_configf ); : R.string.title_gamenet_configf );
setTitle( String.format( fmt, GameUtils.gameName( this, m_name ) ) ); setTitle( String.format( fmt, GameUtils.gameName( this, m_rowid ) ) );
} }
} }

View file

@ -42,23 +42,23 @@ import org.eehouse.android.xw4.jni.CurGameInfo.DeviceRole;
public class GameListAdapter extends XWListAdapter { public class GameListAdapter extends XWListAdapter {
private Context m_context; private Context m_context;
private LayoutInflater m_factory; private LayoutInflater m_factory;
private HashMap<String,View> m_viewsCache; private HashMap<Long,View> m_viewsCache;
private DateFormat m_df; private DateFormat m_df;
private LoadItemCB m_cb; private LoadItemCB m_cb;
// private int m_taskCounter = 0; // private int m_taskCounter = 0;
public interface LoadItemCB { public interface LoadItemCB {
public void itemLoaded( String path ); public void itemLoaded( long rowid );
} }
private class LoadItemTask extends AsyncTask<Void, Void, Void> { private class LoadItemTask extends AsyncTask<Void, Void, Void> {
private String m_path; private long m_rowid;
private Context m_context; private Context m_context;
// private int m_id; // private int m_id;
public LoadItemTask( Context context, String path/*, int id*/ ) public LoadItemTask( Context context, long rowid/*, int id*/ )
{ {
m_context = context; m_context = context;
m_path = path; m_rowid = rowid;
// m_id = id; // m_id = id;
} }
@ -68,9 +68,9 @@ public class GameListAdapter extends XWListAdapter {
// Utils.logf( "doInBackground(id=%d)", m_id ); // Utils.logf( "doInBackground(id=%d)", m_id );
View layout = m_factory.inflate( R.layout.game_list_item, null ); View layout = m_factory.inflate( R.layout.game_list_item, null );
boolean hideTitle = false;//CommonPrefs.getHideTitleBar(m_context); boolean hideTitle = false;//CommonPrefs.getHideTitleBar(m_context);
GameSummary summary = DBUtils.getSummary( m_context, m_path, false ); GameSummary summary = DBUtils.getSummary( m_context, m_rowid, false );
if ( null == summary ) { if ( null == summary ) {
m_path = null; m_rowid = -1;
} else { } else {
//Assert.assertNotNull( summary ); //Assert.assertNotNull( summary );
@ -78,7 +78,7 @@ public class GameListAdapter extends XWListAdapter {
if ( hideTitle ) { if ( hideTitle ) {
view.setVisibility( View.GONE ); view.setVisibility( View.GONE );
} else { } else {
String name = GameUtils.gameName( m_context, m_path ); String name = GameUtils.gameName( m_context, m_rowid );
String format = String format =
m_context.getString( R.string.str_game_namef ); m_context.getString( R.string.str_game_namef );
String lang = String lang =
@ -119,7 +119,7 @@ public class GameListAdapter extends XWListAdapter {
marker.setVisibility( View.VISIBLE ); marker.setVisibility( View.VISIBLE );
} }
synchronized( m_viewsCache ) { synchronized( m_viewsCache ) {
m_viewsCache.put( m_path, layout ); m_viewsCache.put( m_rowid, layout );
} }
} }
return null; return null;
@ -129,8 +129,8 @@ public class GameListAdapter extends XWListAdapter {
protected void onPostExecute( Void unused ) protected void onPostExecute( Void unused )
{ {
// Utils.logf( "onPostExecute(id=%d)", m_id ); // Utils.logf( "onPostExecute(id=%d)", m_id );
if ( null != m_path ) { if ( -1 != m_rowid ) {
m_cb.itemLoaded( m_path ); m_cb.itemLoaded( m_rowid );
} }
} }
} // class LoadItemTask } // class LoadItemTask
@ -148,7 +148,7 @@ public class GameListAdapter extends XWListAdapter {
sdk_int = Integer.decode( android.os.Build.VERSION.SDK ); sdk_int = Integer.decode( android.os.Build.VERSION.SDK );
} catch ( Exception ex ) {} } catch ( Exception ex ) {}
m_viewsCache = new HashMap<String,View>(); m_viewsCache = new HashMap<Long,View>();
} }
public int getCount() { public int getCount() {
@ -157,10 +157,10 @@ public class GameListAdapter extends XWListAdapter {
public Object getItem( int position ) public Object getItem( int position )
{ {
final String path = DBUtils.gamesList(m_context)[position]; final long rowid = DBUtils.gamesList(m_context)[position];
View layout; View layout;
synchronized( m_viewsCache ) { synchronized( m_viewsCache ) {
layout = m_viewsCache.get( path ); layout = m_viewsCache.get( rowid );
} }
if ( null == layout ) { if ( null == layout ) {
@ -172,11 +172,11 @@ public class GameListAdapter extends XWListAdapter {
if ( hideTitle ) { if ( hideTitle ) {
view.setVisibility( View.GONE ); view.setVisibility( View.GONE );
} else { } else {
String text = GameUtils.gameName( m_context, path ); String text = GameUtils.gameName( m_context, rowid );
view.setText( text ); view.setText( text );
} }
new LoadItemTask( m_context, path/*, ++m_taskCounter*/ ).execute(); new LoadItemTask( m_context, rowid/*, ++m_taskCounter*/ ).execute();
} }
// this doesn't work. Rather, it breaks highlighting because // this doesn't work. Rather, it breaks highlighting because
@ -197,10 +197,10 @@ public class GameListAdapter extends XWListAdapter {
return (View)getItem( position ); return (View)getItem( position );
} }
public void inval( String key ) public void inval( long rowid )
{ {
synchronized( m_viewsCache ) { synchronized( m_viewsCache ) {
m_viewsCache.remove( key ); m_viewsCache.remove( rowid );
} }
} }
} }

View file

@ -53,19 +53,19 @@ public class GameUtils {
// obtainable when other read locks are granted but not when a // obtainable when other read locks are granted but not when a
// write lock is. Write-locks are exclusive. // write lock is. Write-locks are exclusive.
public static class GameLock { public static class GameLock {
private String m_path; private long m_rowid;
private boolean m_isForWrite; private boolean m_isForWrite;
private int m_lockCount; private int m_lockCount;
// StackTraceElement[] m_lockTrace; // StackTraceElement[] m_lockTrace;
// This will leak empty ReentrantReadWriteLock instances for // This will leak empty ReentrantReadWriteLock instances for
// now. // now.
private static HashMap<String, GameLock> private static HashMap<Long, GameLock>
s_locks = new HashMap<String,GameLock>(); s_locks = new HashMap<Long,GameLock>();
public GameLock( String path, boolean isForWrite ) public GameLock( long rowid, boolean isForWrite )
{ {
m_path = path; m_rowid = rowid;
m_isForWrite = isForWrite; m_isForWrite = isForWrite;
m_lockCount = 0; m_lockCount = 0;
// Utils.logf( "GameLock.GameLock(%s,%s) done", m_path, // Utils.logf( "GameLock.GameLock(%s,%s) done", m_path,
@ -78,10 +78,10 @@ public class GameUtils {
{ {
boolean gotIt = false; boolean gotIt = false;
synchronized( s_locks ) { synchronized( s_locks ) {
GameLock owner = s_locks.get( m_path ); GameLock owner = s_locks.get( m_rowid );
if ( null == owner ) { // unowned if ( null == owner ) { // unowned
Assert.assertTrue( 0 == m_lockCount ); Assert.assertTrue( 0 == m_lockCount );
s_locks.put( m_path, this ); s_locks.put( m_rowid, this );
++m_lockCount; ++m_lockCount;
gotIt = true; gotIt = true;
@ -128,9 +128,9 @@ public class GameUtils {
{ {
// Utils.logf( "GameLock.unlock(%s)", m_path ); // Utils.logf( "GameLock.unlock(%s)", m_path );
synchronized( s_locks ) { synchronized( s_locks ) {
Assert.assertTrue( this == s_locks.get(m_path) ); Assert.assertTrue( this == s_locks.get(m_rowid) );
if ( 1 == m_lockCount ) { if ( 1 == m_lockCount ) {
s_locks.remove( m_path ); s_locks.remove( m_rowid );
} else { } else {
Assert.assertTrue( !m_isForWrite ); Assert.assertTrue( !m_isForWrite );
} }
@ -139,9 +139,9 @@ public class GameUtils {
// Utils.logf( "GameLock.unlock(%s) done", m_path ); // Utils.logf( "GameLock.unlock(%s) done", m_path );
} }
public String getPath() public long getRowid()
{ {
return m_path; return m_rowid;
} }
// used only for asserts // used only for asserts
@ -153,9 +153,9 @@ public class GameUtils {
private static Object s_syncObj = new Object(); private static Object s_syncObj = new Object();
public static byte[] savedGame( Context context, String path ) public static byte[] savedGame( Context context, long rowid )
{ {
GameLock lock = new GameLock( path, false ).lock(); GameLock lock = new GameLock( rowid, false ).lock();
byte[] result = savedGame( context, lock ); byte[] result = savedGame( context, lock );
lock.unlock(); lock.unlock();
return result; return result;
@ -170,8 +170,8 @@ public class GameUtils {
* Open an existing game, and use its gi and comms addr as the * Open an existing game, and use its gi and comms addr as the
* basis for a new one. * basis for a new one.
*/ */
public static void resetGame( Context context, GameLock lockSrc, public static GameLock resetGame( Context context, GameLock lockSrc,
GameLock lockDest ) GameLock lockDest )
{ {
int gamePtr = XwJNI.initJNI(); int gamePtr = XwJNI.initJNI();
CurGameInfo gi = new CurGameInfo( context ); CurGameInfo gi = new CurGameInfo( context );
@ -203,14 +203,20 @@ public class GameUtils {
XwJNI.comms_setAddr( gamePtr, addr ); XwJNI.comms_setAddr( gamePtr, addr );
} }
saveGame( context, gamePtr, gi, lockDest, true ); if ( null == lockDest ) {
summarizeAndClose( context, lockDest, gamePtr, gi ); long rowid = saveNewGame( context, gamePtr, gi );
lockDest = new GameLock( rowid, true ).lock();
} else {
saveGame( context, gamePtr, gi, lockDest, true );
}
summarizeAndClose( context, lockDest, gamePtr, gi );
return lockDest;
} // resetGame } // resetGame
public static void resetGame( Context context, String pathIn ) public static void resetGame( Context context, long rowidIn )
{ {
GameLock lock = new GameLock( pathIn, true ) GameLock lock = new GameLock( rowidIn, true ).lock();
.lock();
tellRelayDied( context, lock, true ); tellRelayDied( context, lock, true );
resetGame( context, lock, lock ); resetGame( context, lock, lock );
lock.unlock(); lock.unlock();
@ -258,22 +264,21 @@ public class GameUtils {
return summarizeAndClose( context, lock, gamePtr, gi ); return summarizeAndClose( context, lock, gamePtr, gi );
} }
public static String dupeGame( Context context, String pathIn ) public static long dupeGame( Context context, long rowidIn )
{ {
GameLock lockSrc = new GameLock( pathIn, false ).lock(); GameLock lockSrc = new GameLock( rowidIn, false ).lock();
String newName = newName( context ); GameLock lockDest = resetGame( context, lockSrc, null );
GameLock lockDest = long rowid = lockDest.getRowid();
new GameLock( newName, true ).lock();
resetGame( context, lockSrc, lockDest );
lockDest.unlock(); lockDest.unlock();
lockSrc.unlock(); lockSrc.unlock();
return newName; return rowid;
} }
public static void deleteGame( Context context, String path, boolean informNow ) public static void deleteGame( Context context, long rowid,
boolean informNow )
{ {
// does this need to be synchronized? // does this need to be synchronized?
GameLock lock = new GameLock( path, true ); GameLock lock = new GameLock( rowid, true );
if ( lock.tryLock() ) { if ( lock.tryLock() ) {
tellRelayDied( context, lock, informNow ); tellRelayDied( context, lock, informNow );
DBUtils.deleteGame( context, lock ); DBUtils.deleteGame( context, lock );
@ -309,56 +314,52 @@ public class GameUtils {
} }
} }
public static void saveGame( Context context, int gamePtr, public static long saveGame( Context context, int gamePtr,
CurGameInfo gi, GameLock lock, CurGameInfo gi, GameLock lock,
boolean setCreate ) boolean setCreate )
{ {
byte[] stream = XwJNI.game_saveToStream( gamePtr, gi ); byte[] stream = XwJNI.game_saveToStream( gamePtr, gi );
saveGame( context, stream, lock, setCreate ); return saveGame( context, stream, lock, setCreate );
} }
public static void saveGame( Context context, int gamePtr, public static long saveNewGame( Context context, int gamePtr,
CurGameInfo gi ) CurGameInfo gi )
{ {
String path = newName( context ); byte[] stream = XwJNI.game_saveToStream( gamePtr, gi );
GameLock lock = GameLock lock = DBUtils.saveNewGame( context, stream );
new GameLock( path, true ).lock(); long rowid = lock.getRowid();
saveGame( context, gamePtr, gi, lock, false );
lock.unlock(); lock.unlock();
return rowid;
} }
public static void saveGame( Context context, byte[] bytes, public static long saveGame( Context context, byte[] bytes,
GameLock lock, boolean setCreate ) GameLock lock, boolean setCreate )
{ {
DBUtils.saveGame( context, lock, bytes, setCreate ); return DBUtils.saveGame( context, lock, bytes, setCreate );
} }
public static GameLock saveGame( Context context, byte[] bytes, public static GameLock saveNewGame( Context context, byte[] bytes )
boolean setCreate )
{ {
String name = newName( context ); return DBUtils.saveNewGame( context, bytes );
GameLock lock =
new GameLock( name, true ).lock();
saveGame( context, bytes, lock, setCreate );
return lock;
} }
public static String saveNew( Context context, CurGameInfo gi ) public static long saveNew( Context context, CurGameInfo gi )
{ {
String path = null; long rowid = -1;
byte[] bytes = XwJNI.gi_to_stream( gi ); byte[] bytes = XwJNI.gi_to_stream( gi );
if ( null != bytes ) { if ( null != bytes ) {
GameLock lock = saveGame( context, bytes, true ); GameLock lock = DBUtils.saveNewGame( context, bytes );
path = lock.getPath(); rowid = lock.getRowid();
lock.unlock(); lock.unlock();
} }
return path; return rowid;
} }
public static String makeNewNetGame( Context context, String room, public static long makeNewNetGame( Context context, String room,
int[] lang, int nPlayersT, int[] lang, int nPlayersT,
int nPlayersH ) int nPlayersH )
{ {
long rowid = -1;
CommsAddrRec addr = new CommsAddrRec( context ); CommsAddrRec addr = new CommsAddrRec( context );
addr.ip_relay_invite = room; addr.ip_relay_invite = room;
@ -370,23 +371,23 @@ public class GameUtils {
// Will need to add a setNPlayers() method to gi to make this // Will need to add a setNPlayers() method to gi to make this
// work // work
Assert.assertTrue( gi.nPlayers == nPlayersT ); Assert.assertTrue( gi.nPlayers == nPlayersT );
String path = saveNew( context, gi ); rowid = saveNew( context, gi );
GameLock lock = new GameLock( path, true ).lock(); GameLock lock = new GameLock( rowid, true ).lock();
applyChanges( context, gi, addr, lock, false ); applyChanges( context, gi, addr, lock, false );
lock.unlock(); lock.unlock();
return path; return rowid;
} }
public static String makeNewNetGame( Context context, String room, public static long makeNewNetGame( Context context, String room,
int lang, int nPlayers ) int lang, int nPlayers )
{ {
int[] langarr = { lang }; int[] langarr = { lang };
return makeNewNetGame( context, room, langarr, nPlayers, 1 ); return makeNewNetGame( context, room, langarr, nPlayers, 1 );
} }
public static String makeNewNetGame( Context context, NetLaunchInfo info ) public static long makeNewNetGame( Context context, NetLaunchInfo info )
{ {
return makeNewNetGame( context, info.room, info.lang, return makeNewNetGame( context, info.room, info.lang,
info.nPlayers ); info.nPlayers );
@ -414,18 +415,18 @@ public class GameUtils {
} }
} }
public static boolean gameDictsHere( Context context, String path ) public static boolean gameDictsHere( Context context, long rowid )
{ {
return gameDictsHere( context, path, null, null ); return gameDictsHere( context, rowid, null, null );
} }
// Return true if all dicts present. Return list of those that // Return true if all dicts present. Return list of those that
// are not. // are not.
public static boolean gameDictsHere( Context context, String path, public static boolean gameDictsHere( Context context, long rowid,
String[][] missingNames, String[][] missingNames,
int[] missingLang ) int[] missingLang )
{ {
byte[] stream = savedGame( context, path ); byte[] stream = savedGame( context, rowid );
CurGameInfo gi = new CurGameInfo( context ); CurGameInfo gi = new CurGameInfo( context );
XwJNI.gi_from_stream( gi, stream ); XwJNI.gi_from_stream( gi, stream );
final String[] dictNames = gi.dictNames(); final String[] dictNames = gi.dictNames();
@ -451,28 +452,29 @@ public class GameUtils {
public static boolean gameDictsHere( Context context, int indx, public static boolean gameDictsHere( Context context, int indx,
String[][] name, int[] lang ) String[][] name, int[] lang )
{ {
String path = DBUtils.gamesList( context )[indx]; long rowid = DBUtils.gamesList( context )[indx];
return gameDictsHere( context, path, name, lang ); return gameDictsHere( context, rowid, name, lang );
} }
public static String newName( Context context ) public static String newName( Context context )
{ {
String name = null; return "untitled";
Integer num = 1; // String name = null;
int ii; // Integer num = 1;
String[] files = DBUtils.gamesList( context ); // int ii;
String fmt = context.getString( R.string.gamef ); // long[] rowids = DBUtils.gamesList( context );
// String fmt = context.getString( R.string.gamef );
while ( name == null ) { // while ( name == null ) {
name = String.format( fmt + XWConstants.GAME_EXTN, num ); // name = String.format( fmt + XWConstants.GAME_EXTN, num );
for ( ii = 0; ii < files.length; ++ii ) { // for ( ii = 0; ii < files.length; ++ii ) {
if ( files[ii].equals(name) ) { // if ( files[ii].equals(name) ) {
++num; // ++num;
name = null; // name = null;
} // }
} // }
} // }
return name; // return name;
} }
public static String[] dictList( Context context ) public static String[] dictList( Context context )
@ -733,52 +735,53 @@ public class GameUtils {
return file.endsWith( XWConstants.DICT_EXTN ); return file.endsWith( XWConstants.DICT_EXTN );
} }
public static String gameName( Context context, String path ) public static String gameName( Context context, long rowid )
{ {
return path.substring( 0, path.lastIndexOf( XWConstants.GAME_EXTN ) ); return String.format( "Row %d", rowid );
// return path.substring( 0, path.lastIndexOf( XWConstants.GAME_EXTN ) );
} }
public static void launchGame( Activity activity, String path, public static void launchGame( Activity activity, long rowid,
boolean invited ) boolean invited )
{ {
Intent intent = new Intent( activity, BoardActivity.class ); Intent intent = new Intent( activity, BoardActivity.class );
intent.setAction( Intent.ACTION_EDIT ); intent.setAction( Intent.ACTION_EDIT );
intent.putExtra( BoardActivity.INTENT_KEY_NAME, path ); intent.putExtra( BoardActivity.INTENT_KEY_ROWID, rowid );
if ( invited ) { if ( invited ) {
intent.putExtra( INVITED, true ); intent.putExtra( INVITED, true );
} }
activity.startActivity( intent ); activity.startActivity( intent );
} }
public static void launchGame( Activity activity, String path ) public static void launchGame( Activity activity, long rowid)
{ {
launchGame( activity, path, false ); launchGame( activity, rowid, false );
} }
public static void launchGameAndFinish( Activity activity, String path ) public static void launchGameAndFinish( Activity activity, long rowid )
{ {
launchGame( activity, path ); launchGame( activity, rowid );
activity.finish(); activity.finish();
} }
private static class FeedUtilsImpl extends UtilCtxtImpl { private static class FeedUtilsImpl extends UtilCtxtImpl {
private Context m_context; private Context m_context;
private String m_path; private long m_rowid;
public boolean m_gotMsg; public boolean m_gotMsg;
public boolean m_gotChat; public boolean m_gotChat;
public boolean m_gameOver; public boolean m_gameOver;
public FeedUtilsImpl( Context context, String path ) public FeedUtilsImpl( Context context, long rowid )
{ {
super( context ); super( context );
m_context = context; m_context = context;
m_path = path; m_rowid = rowid;
m_gotMsg = false; m_gotMsg = false;
m_gameOver = false; m_gameOver = false;
} }
public void showChat( String msg ) public void showChat( String msg )
{ {
DBUtils.appendChatHistory( m_context, m_path, msg, false ); DBUtils.appendChatHistory( m_context, m_rowid, msg, false );
m_gotChat = true; m_gotChat = true;
} }
public void turnChanged() public void turnChanged()
@ -796,12 +799,12 @@ public class GameUtils {
byte[][] msgs ) byte[][] msgs )
{ {
boolean draw = false; boolean draw = false;
String path = DBUtils.getPathFor( context, relayID ); long rowid = DBUtils.getRowIDFor( context, relayID );
if ( null != path ) { if ( -1 != rowid ) {
int gamePtr = XwJNI.initJNI(); int gamePtr = XwJNI.initJNI();
CurGameInfo gi = new CurGameInfo( context ); CurGameInfo gi = new CurGameInfo( context );
FeedUtilsImpl feedImpl = new FeedUtilsImpl( context, path ); FeedUtilsImpl feedImpl = new FeedUtilsImpl( context, rowid );
GameLock lock = new GameLock( path, true ); GameLock lock = new GameLock( rowid, true );
if ( lock.tryLock() ) { if ( lock.tryLock() ) {
loadMakeGame( context, gamePtr, gi, feedImpl, lock ); loadMakeGame( context, gamePtr, gi, feedImpl, lock );
@ -826,7 +829,7 @@ public class GameUtils {
} }
if ( GameSummary.MSG_FLAGS_NONE != flags ) { if ( GameSummary.MSG_FLAGS_NONE != flags ) {
draw = true; draw = true;
DBUtils.setMsgFlags( path, flags ); DBUtils.setMsgFlags( rowid, flags );
} }
lock.unlock(); lock.unlock();
} }
@ -838,10 +841,10 @@ public class GameUtils {
// This *must* involve a reset if the language is changing!!! // This *must* involve a reset if the language is changing!!!
// Which isn't possible right now, so make sure the old and new // Which isn't possible right now, so make sure the old and new
// dict have the same langauge code. // dict have the same langauge code.
public static void replaceDicts( Context context, String game, public static void replaceDicts( Context context, long rowid,
String oldDict, String newDict ) String oldDict, String newDict )
{ {
GameLock lock = new GameLock( game, true ).lock(); GameLock lock = new GameLock( rowid, true ).lock();
byte[] stream = savedGame( context, lock ); byte[] stream = savedGame( context, lock );
CurGameInfo gi = new CurGameInfo( context ); CurGameInfo gi = new CurGameInfo( context );
XwJNI.gi_from_stream( gi, stream ); XwJNI.gi_from_stream( gi, stream );
@ -911,11 +914,11 @@ public class GameUtils {
XwJNI.game_dispose( gamePtr ); XwJNI.game_dispose( gamePtr );
} // applyChanges } // applyChanges
public static void doConfig( Activity activity, String path, Class clazz ) public static void doConfig( Activity activity, long rowid, Class clazz )
{ {
Intent intent = new Intent( activity, clazz ); Intent intent = new Intent( activity, clazz );
intent.setAction( Intent.ACTION_EDIT ); intent.setAction( Intent.ACTION_EDIT );
intent.putExtra( BoardActivity.INTENT_KEY_NAME, path ); intent.putExtra( BoardActivity.INTENT_KEY_ROWID, rowid );
activity.startActivity( intent ); activity.startActivity( intent );
} }

View file

@ -64,7 +64,7 @@ public class GamesList extends XWListActivity
private String m_missingDict; private String m_missingDict;
private Handler m_handler; private Handler m_handler;
private String[] m_missingDictNames; private String[] m_missingDictNames;
private String m_missingDictPath; private long m_missingDictRowId;
private String[] m_sameLangDicts; private String[] m_sameLangDicts;
private int m_missingDictLang; private int m_missingDictLang;
@ -143,7 +143,7 @@ public class GamesList extends XWListActivity
dict = DictLangCache.stripCount( dict ); dict = DictLangCache.stripCount( dict );
GameUtils. GameUtils.
replaceDicts( GamesList.this, replaceDicts( GamesList.this,
m_missingDictPath, m_missingDictRowId,
m_missingDictNames[0], m_missingDictNames[0],
dict ); dict );
} }
@ -316,18 +316,18 @@ public class GamesList extends XWListActivity
} }
// DBUtils.DBChangeListener interface // DBUtils.DBChangeListener interface
public void pathSaved( final String path ) public void gameSaved( final long rowid )
{ {
m_handler.post( new Runnable() { m_handler.post( new Runnable() {
public void run() { public void run() {
m_adapter.inval( path ); m_adapter.inval( rowid );
onContentChanged(); onContentChanged();
} }
} ); } );
} }
// GameListAdapter.LoadItemCB interface // GameListAdapter.LoadItemCB interface
public void itemLoaded( String path ) public void itemLoaded( long rowid )
{ {
onContentChanged(); onContentChanged();
} }
@ -372,7 +372,7 @@ public class GamesList extends XWListActivity
break; break;
case R.id.gamel_menu_delete_all: case R.id.gamel_menu_delete_all:
final String[] games = DBUtils.gamesList( this ); final long[] games = DBUtils.gamesList( this );
if ( games.length > 0 ) { if ( games.length > 0 ) {
DialogInterface.OnClickListener lstnr = DialogInterface.OnClickListener lstnr =
new DialogInterface.OnClickListener() { new DialogInterface.OnClickListener() {
@ -427,12 +427,12 @@ public class GamesList extends XWListActivity
protected void onListItemClick( ListView l, View v, int position, long id ) protected void onListItemClick( ListView l, View v, int position, long id )
{ {
super.onListItemClick( l, v, position, id ); super.onListItemClick( l, v, position, id );
String path = DBUtils.gamesList( this )[position]; long rowid = DBUtils.gamesList( this )[position];
// We need a way to let the user get back to the basic-config // We need a way to let the user get back to the basic-config
// dialog in case it was dismissed. That way it to check for // dialog in case it was dismissed. That way it to check for
// an empty room name. // an empty room name.
GameSummary summary = DBUtils.getSummary( this, path, true ); GameSummary summary = DBUtils.getSummary( this, rowid, true );
if ( summary.conType == CommsAddrRec.CommsConnType.COMMS_CONN_RELAY if ( summary.conType == CommsAddrRec.CommsConnType.COMMS_CONN_RELAY
&& summary.roomName.length() == 0 ) { && summary.roomName.length() == 0 ) {
// If it's unconfigured and of the type RelayGameActivity // If it's unconfigured and of the type RelayGameActivity
@ -444,10 +444,10 @@ public class GamesList extends XWListActivity
} else { } else {
clazz = GameConfig.class; clazz = GameConfig.class;
} }
GameUtils.doConfig( this, path, clazz ); GameUtils.doConfig( this, rowid, clazz );
} else { } else {
if ( checkWarnNoDict( path ) ) { if ( checkWarnNoDict( rowid ) ) {
GameUtils.launchGame( this, path ); GameUtils.launchGame( this, rowid );
} }
} }
} }
@ -457,38 +457,37 @@ public class GamesList extends XWListActivity
boolean handled = true; boolean handled = true;
DialogInterface.OnClickListener lstnr; DialogInterface.OnClickListener lstnr;
final String path = DBUtils.gamesList( this )[position]; final long rowid = DBUtils.gamesList( this )[position];
if ( R.id.list_item_delete == menuID ) { if ( R.id.list_item_delete == menuID ) {
lstnr = new DialogInterface.OnClickListener() { lstnr = new DialogInterface.OnClickListener() {
public void onClick( DialogInterface dlg, int ii ) { public void onClick( DialogInterface dlg, int ii ) {
GameUtils.deleteGame( GamesList.this, path, true ); GameUtils.deleteGame( GamesList.this, rowid, true );
} }
}; };
showConfirmThen( R.string.confirm_delete, lstnr ); showConfirmThen( R.string.confirm_delete, lstnr );
} else { } else {
String invalPath = null; if ( checkWarnNoDict( rowid ) ) {
if ( checkWarnNoDict( path ) ) {
switch ( menuID ) { switch ( menuID ) {
case R.id.list_item_reset: case R.id.list_item_reset:
lstnr = new DialogInterface.OnClickListener() { lstnr = new DialogInterface.OnClickListener() {
public void onClick( DialogInterface dlg, int ii ) { public void onClick( DialogInterface dlg, int ii ) {
GameUtils.resetGame( GamesList.this, path ); GameUtils.resetGame( GamesList.this, rowid );
} }
}; };
showConfirmThen( R.string.confirm_reset, lstnr ); showConfirmThen( R.string.confirm_reset, lstnr );
break; break;
case R.id.list_item_config: case R.id.list_item_config:
GameUtils.doConfig( this, path, GameConfig.class ); GameUtils.doConfig( this, rowid, GameConfig.class );
break; break;
case R.id.list_item_new_from: case R.id.list_item_new_from:
Runnable proc = new Runnable() { Runnable proc = new Runnable() {
public void run() { public void run() {
String newName = long newid =
GameUtils.dupeGame( GamesList.this, path ); GameUtils.dupeGame( GamesList.this, rowid );
if ( null != m_adapter ) { if ( null != m_adapter ) {
m_adapter.inval( newName ); m_adapter.inval( newid );
} }
} }
}; };
@ -497,13 +496,13 @@ public class GamesList extends XWListActivity
break; break;
case R.id.list_item_copy: case R.id.list_item_copy:
GameSummary summary = DBUtils.getSummary( this, path, true ); GameSummary summary = DBUtils.getSummary( this, rowid, true );
if ( summary.inNetworkGame() ) { if ( summary.inNetworkGame() ) {
showOKOnlyDialog( R.string.no_copy_network ); showOKOnlyDialog( R.string.no_copy_network );
} else { } else {
byte[] stream = GameUtils.savedGame( this, path ); byte[] stream = GameUtils.savedGame( this, rowid );
GameUtils.GameLock lock = GameUtils.GameLock lock =
GameUtils.saveGame( this, stream, true ); GameUtils.saveNewGame( this, stream );
DBUtils.saveSummary( this, lock, summary ); DBUtils.saveSummary( this, lock, summary );
lock.unlock(); lock.unlock();
} }
@ -523,26 +522,22 @@ public class GamesList extends XWListActivity
break; break;
} }
} }
if ( null != invalPath ) {
m_adapter.inval( invalPath );
}
} }
return handled; return handled;
} // handleMenuItem } // handleMenuItem
private boolean checkWarnNoDict( String path ) private boolean checkWarnNoDict( long rowid )
{ {
String[][] missingNames = new String[1][]; String[][] missingNames = new String[1][];
int[] missingLang = new int[1]; int[] missingLang = new int[1];
boolean hasDicts = GameUtils.gameDictsHere( this, path, boolean hasDicts = GameUtils.gameDictsHere( this, rowid,
missingNames, missingNames,
missingLang ); missingLang );
if ( !hasDicts ) { if ( !hasDicts ) {
m_missingDictNames = missingNames[0]; m_missingDictNames = missingNames[0];
m_missingDictLang = missingLang[0]; m_missingDictLang = missingLang[0];
m_missingDictPath = path; m_missingDictRowId = rowid;
if ( 0 == DictLangCache.getLangCount( this, m_missingDictLang ) ) { if ( 0 == DictLangCache.getLangCount( this, m_missingDictLang ) ) {
showDialog( WARN_NODICT ); showDialog( WARN_NODICT );
} else { } else {
@ -556,8 +551,8 @@ public class GamesList extends XWListActivity
{ {
if ( null != relayIDs ) { if ( null != relayIDs ) {
for ( String relayID : relayIDs ) { for ( String relayID : relayIDs ) {
String path = DBUtils.getPathFor( this, relayID ); long rowid = DBUtils.getRowIDFor( this, relayID );
m_adapter.inval( path ); m_adapter.inval( rowid );
} }
onContentChanged(); onContentChanged();
} }
@ -569,9 +564,9 @@ public class GamesList extends XWListActivity
{ {
if ( null != relayIDs ) { if ( null != relayIDs ) {
for ( String relayID : relayIDs ) { for ( String relayID : relayIDs ) {
String path = DBUtils.getPathFor( this, relayID ); long rowid = DBUtils.getRowIDFor( this, relayID );
if ( null != path && GameUtils.gameDictsHere( this, path ) ) { if ( -1 != rowid && GameUtils.gameDictsHere( this, rowid ) ) {
GameUtils.launchGame( this, path ); GameUtils.launchGame( this, rowid );
break; break;
} }
} }
@ -594,21 +589,21 @@ public class GamesList extends XWListActivity
private void startNewNetGame( final NetLaunchInfo info ) private void startNewNetGame( final NetLaunchInfo info )
{ {
String path = DBUtils.getPathForOpen( this, info.room, info.lang, long rowid = DBUtils.getRowIDForOpen( this, info.room, info.lang,
info.nPlayers ); info.nPlayers );
if ( null == path ) { if ( -1 != rowid ) {
path = GameUtils.makeNewNetGame( this, info ); rowid = GameUtils.makeNewNetGame( this, info );
GameUtils.launchGame( this, path, true ); GameUtils.launchGame( this, rowid, true );
} else { } else {
DialogInterface.OnClickListener then = DialogInterface.OnClickListener then =
new DialogInterface.OnClickListener() { new DialogInterface.OnClickListener() {
public void onClick( DialogInterface dlg, public void onClick( DialogInterface dlg,
int ii ) { int ii ) {
String path = GameUtils. long rowid = GameUtils.
makeNewNetGame( GamesList.this, info ); makeNewNetGame( GamesList.this, info );
GameUtils.launchGame( GamesList.this, GameUtils.launchGame( GamesList.this,
path, true ); rowid, true );
} }
}; };
String fmt = getString( R.string.dup_game_queryf ); String fmt = getString( R.string.dup_game_queryf );

View file

@ -89,25 +89,25 @@ public class NewGameActivity extends XWActivity {
private void makeNewGame( boolean networked, boolean launch ) private void makeNewGame( boolean networked, boolean launch )
{ {
String room = null; String room = null;
String path; long rowid;
int[] lang = {0}; int[] lang = {0};
final int nPlayers = 2; // hard-coded for no-configure case final int nPlayers = 2; // hard-coded for no-configure case
if ( networked ) { if ( networked ) {
Random random = new Random(); Random random = new Random();
room = String.format( "%X", random.nextInt() ).substring( 0, 4 ); room = String.format( "%X", random.nextInt() ).substring( 0, 4 );
path = GameUtils.makeNewNetGame( this, room, lang, nPlayers, 1 ); rowid = GameUtils.makeNewNetGame( this, room, lang, nPlayers, 1 );
} else { } else {
path = GameUtils.saveNew( this, new CurGameInfo( this ) ); rowid = GameUtils.saveNew( this, new CurGameInfo( this ) );
} }
if ( launch ) { if ( launch ) {
GameUtils.launchGame( this, path, networked ); GameUtils.launchGame( this, rowid, networked );
if ( networked ) { if ( networked ) {
GameUtils.launchInviteActivity( this, room, lang[0], nPlayers ); GameUtils.launchInviteActivity( this, room, lang[0], nPlayers );
} }
} else { } else {
GameUtils.doConfig( this, path, GameConfig.class ); GameUtils.doConfig( this, rowid, GameConfig.class );
} }
finish(); finish();

View file

@ -39,7 +39,7 @@ import org.eehouse.android.xw4.jni.*;
public class RelayGameActivity extends XWActivity public class RelayGameActivity extends XWActivity
implements View.OnClickListener { implements View.OnClickListener {
private String m_name; private long m_rowid;
private CurGameInfo m_gi; private CurGameInfo m_gi;
private GameUtils.GameLock m_gameLock; private GameUtils.GameLock m_gameLock;
private CommsAddrRec m_car; private CommsAddrRec m_car;
@ -53,7 +53,7 @@ public class RelayGameActivity extends XWActivity
setContentView( R.layout.relay_game_config ); setContentView( R.layout.relay_game_config );
m_name = getIntent().getStringExtra( BoardActivity.INTENT_KEY_NAME ); m_rowid = getIntent().getLongExtra( BoardActivity.INTENT_KEY_ROWID, -1 );
m_playButton = (Button)findViewById( R.id.play_button ); m_playButton = (Button)findViewById( R.id.play_button );
m_playButton.setOnClickListener( this ); m_playButton.setOnClickListener( this );
@ -69,7 +69,7 @@ public class RelayGameActivity extends XWActivity
int gamePtr = XwJNI.initJNI(); int gamePtr = XwJNI.initJNI();
m_gi = new CurGameInfo( this ); m_gi = new CurGameInfo( this );
m_gameLock = new GameUtils.GameLock( m_name, true ).lock(); m_gameLock = new GameUtils.GameLock( m_rowid, true ).lock();
GameUtils.loadMakeGame( this, gamePtr, m_gi, m_gameLock ); GameUtils.loadMakeGame( this, gamePtr, m_gi, m_gameLock );
m_car = new CommsAddrRec( this ); m_car = new CommsAddrRec( this );
if ( XwJNI.game_hasComms( gamePtr ) ) { if ( XwJNI.game_hasComms( gamePtr ) ) {
@ -107,12 +107,12 @@ public class RelayGameActivity extends XWActivity
showOKOnlyDialog( R.string.no_empty_rooms ); showOKOnlyDialog( R.string.no_empty_rooms );
} else { } else {
if ( saveRoomAndName( room ) ) { if ( saveRoomAndName( room ) ) {
GameUtils.launchGameAndFinish( this, m_name ); GameUtils.launchGameAndFinish( this, m_rowid );
} }
} }
} else if ( view == m_configButton ) { } else if ( view == m_configButton ) {
if ( saveRoomAndName( room ) ) { if ( saveRoomAndName( room ) ) {
GameUtils.doConfig( this, m_name, GameConfig.class ); GameUtils.doConfig( this, m_rowid, GameConfig.class );
finish(); finish();
} }
} }