diff --git a/ExaltedDice/src/com/TwentyCode/android/ExaltedDice/Database.java b/ExaltedDice/src/com/TwentyCode/android/ExaltedDice/Database.java index 61f5a04..16fb388 100644 --- a/ExaltedDice/src/com/TwentyCode/android/ExaltedDice/Database.java +++ b/ExaltedDice/src/com/TwentyCode/android/ExaltedDice/Database.java @@ -33,6 +33,46 @@ import android.util.Log; * @author ricky barrette */ public class Database { + + /** + * database version. If this is increased, the database will be upgraded the next time it connects + */ + private final int DATABASE_VERSION = 1; + + /** + * database file name + */ + private final String DATABASE_NAME = "history.db"; + + /** + * database table for games + */ + private final String GAME_NAME_TABLE = "games"; + /** + * Database table of history + */ + private final String GAME_HISTORY_TABLE = "history"; + + /* + * Database keys + */ + private static final String KEY = "key"; + private static final String KEY_VALUE = "value"; + + /* + * database value keys + */ + public final static String KEY_NAME = "name"; + public final static String KEY_D_TYPE = "d_type"; + public final static String KEY_NUMBER = "number"; + public final static String KEY_LOG = "log"; + public final static String KEY_ROLL_ID = "roll_id"; + + private static final String TAG = "Database"; + private Context mContext; + private SQLiteDatabase mDb; + public boolean isUpgrading = false; + private DatabaseListener mListener; /** * A helper class to manage database creation and version management. @@ -40,7 +80,6 @@ public class Database { */ private class OpenHelper extends SQLiteOpenHelper { - /** * Creates a new OpenHelper * @param context @@ -50,7 +89,7 @@ public class Database { super(context, DATABASE_NAME, null, DATABASE_VERSION); } - /** + /** * Creates the initial database structure * @param db * @author ricky barrette @@ -58,16 +97,19 @@ public class Database { private void createDatabase(SQLiteDatabase db){ db.execSQL("CREATE TABLE " + GAME_NAME_TABLE + "(id INTEGER PRIMARY KEY, " + - KEY_NAME+" TEXT)"); + KEY_NAME+" TEXT, " + + KEY_ROLL_ID + " INTEGER)"); + db.execSQL("CREATE TABLE " + GAME_HISTORY_TABLE + "(id INTEGER PRIMARY KEY, " + KEY_NAME+" TEXT, " + + KEY_ROLL_ID + " TEXT, "+ KEY+" TEXT, " + - KEY_VALUE+" TEXT)"); + KEY_VALUE+" INTEGER)"); } /** - * called when the database is created for the first time. this will create our Ringer database + * called when the database is created for the first time. this will create our game database * (non-Javadoc) * @see android.database.sqlite.SQLiteOpenHelper#onCreate(android.database.sqlite.SQLiteDatabase) * @author ricky barrette @@ -111,7 +153,7 @@ public class Database { case 2: //upgrade from 2 to 3 case 3: - //upgrade from 4 to 4 + //upgrade from 3 to 4 } handler.sendEmptyMessage(0); Database.this.isUpgrading = false; @@ -119,63 +161,7 @@ public class Database { }).start(); } } - private static final String TAG = "Database"; - /** - * Parses a string boolean from the database - * @param bool - * @return true or false - * @author ricky barrette - */ - public static boolean parseBoolean(String bool){ - try { - return bool == null ? false : Integer.parseInt(bool) == 1 ? true : false; - } catch (NumberFormatException e) { - return false; - } - } - private Context mContext; - private SQLiteDatabase mDb; - - public boolean isUpgrading = false; - private DatabaseListener mListener; - - /** - * database version. If this is increased, the database will be upgraded the next time it connects - */ - private final int DATABASE_VERSION = 1; - - /** - * database file name - */ - private final String DATABASE_NAME = "history.db"; - - /** - * database table for games - */ - private final String GAME_NAME_TABLE = "game_name"; - /** - * Database table of history - */ - private final String GAME_HISTORY_TABLE = "game_history"; - - /* - * Database keys - */ - private static final String KEY = "key"; - private static final String KEY_VALUE = "value"; - /* - * database value keys - */ - public final static String KEY_NAME = "name"; - public final static String KEY_D_TYPE = "d_type"; - public final static String KEY_NUMBER = "number"; - - - public final static String KEY_LOG = "log"; - - public final static String KEY_ROLL_ID = "log_number"; - /** * Creates a new Database * @param context @@ -286,19 +272,19 @@ public class Database { } }; - //ringer deleting thread + //game deleting thread new Thread( new Runnable(){ @Override public void run(){ Looper.prepare(); /* - * get the game name from the id, and then delete all its information from the game histroy table + * get the game name from the id, and then delete all its information from the game history table */ - Database.this.mDb.delete(GAME_HISTORY_TABLE, KEY_NAME +" = "+ DatabaseUtils.sqlEscapeString(Database.this.getGameName(id)), null); + Database.this.mDb.delete(GAME_HISTORY_TABLE, KEY_NAME +" = "+ DatabaseUtils.sqlEscapeString(getGameName(id)), null); /* - * finally delete the ringer from the ringer table + * finally delete the game from the game table */ Database.this.mDb.delete(GAME_NAME_TABLE, "id = "+ id, null); updateRowIds(id +1); @@ -322,7 +308,7 @@ public class Database { */ public List getAllGameTitles() { List list = new ArrayList(); - Cursor cursor = this.mDb.query(GAME_NAME_TABLE, new String[] { KEY_NAME }, null, null, null, null, null); + Cursor cursor = getAllGames();; if (cursor.moveToFirst()) { do { list.add(cursor.getString(0)); @@ -345,14 +331,15 @@ public class Database { } /** - * gets a games's histrory info from the supplied ringer name + * gets roll log from the games's history info from the supplied game name and roll id * @param gameName + * @param rollId * @return * @author ricky barrette */ - public ContentValues getGameHistoryInfo(String gameName){ + public ContentValues getGameHistoryInfo(String gameName, int rollId){ ContentValues values = new ContentValues(); - Cursor info = this.mDb.query(GAME_HISTORY_TABLE, new String[]{ KEY, KEY_VALUE }, KEY_NAME +" = "+ DatabaseUtils.sqlEscapeString(gameName), null, null, null, null); + Cursor info = this.mDb.query(GAME_HISTORY_TABLE, new String[]{ KEY, KEY_VALUE }, KEY_NAME +" = "+ DatabaseUtils.sqlEscapeString(gameName) +" AND "+ KEY_ROLL_ID+" = "+rollId, null, null, null, null); if (info.moveToFirst()) { do { values.put(info.getString(0), info.getString(1)); @@ -371,15 +358,32 @@ public class Database { * @author ricky barrette */ public String getGameName(long id) { - String name = null; Cursor cursor = this.mDb.query(GAME_NAME_TABLE, new String[]{ KEY_NAME }, "id = "+id, null, null, null, null);; if (cursor.moveToFirst()) { - name = cursor.getString(0); + return cursor.getString(0); } if (cursor != null && !cursor.isClosed()) { cursor.close(); } - return name; + return null; + } + + /** + * Retrieves the number of rolls for this game + * @param id + * @return roll count + * @author ricky barrette + */ + public int getGameRollCount(long id) { + int rolls = -1; + Cursor cursor = this.mDb.query(GAME_NAME_TABLE, new String[]{ KEY_ROLL_ID }, "id = "+id, null, null, null, null);; + if (cursor.moveToFirst()) { + rolls = Integer.parseInt(cursor.getString(0)); + } + if (cursor != null && !cursor.isClosed()) { + cursor.close(); + } + return rolls; } /** @@ -387,38 +391,27 @@ public class Database { * @param game values * @param gameHistory values * @author ricky barrette + * @return */ - public void insertGame(String gameName, ContentValues gameHistory){ + public long insertGame(String gameName){ ContentValues game = new ContentValues(); game.put(Database.KEY_NAME, checkName(gameName)); - mDb.insert(GAME_NAME_TABLE, null, game); - - if(gameHistory != null) - //insert the information values - for(Entry item : gameHistory.valueSet()){ - ContentValues values = new ContentValues(); - values.put(KEY_NAME, gameName); - values.put(KEY, item.getKey()); - /* - * Try get the value. - * If there is a class cast exception, try casting to the next object type. - * - * The following types are tried: - * String - * Integer - * Boolean - */ - try { - values.put(KEY_VALUE, (String) item.getValue()); - } catch (ClassCastException e) { - try { - values.put(KEY_VALUE, (Boolean) item.getValue() ? 1 : 0); - } catch (ClassCastException e1) { - values.put(KEY_VALUE, (Integer) item.getValue()); - } - } - mDb.insert(GAME_HISTORY_TABLE, null, values); - } + game.put(Database.KEY_ROLL_ID, 0); + return mDb.insert(GAME_NAME_TABLE, null, game); + } + + /** + * Parses a string boolean from the database + * @param bool + * @return true or false + * @author ricky barrette + */ + public static boolean parseBoolean(String bool){ + try { + return bool == null ? false : Integer.parseInt(bool) == 1 ? true : false; + } catch (NumberFormatException e) { + return false; + } } /** @@ -458,23 +451,23 @@ public class Database { * @param gameHistory values * @author ricky barrette */ - public void updateGame(long id, String gameName, ContentValues gameHistory) throws NullPointerException{ + public void updateGame(long id, String gameName, ContentValues gameHistory, int rollId) throws NullPointerException{ ContentValues game= new ContentValues(); + //store the current roll + game.put(KEY_ROLL_ID, rollId); + if(gameName == null || gameHistory == null) throw new NullPointerException("game content was null"); - String ringer_name = getGameName(id); - if(!ringer_name.equals(gameName)) - game.put(Database.KEY_NAME, checkName(gameName)); - /* * update the information values in the info table */ for(Entry item : gameHistory.valueSet()){ ContentValues values = new ContentValues(); - values.put(KEY_NAME, game.getAsString(KEY_NAME)); + values.put(KEY_ROLL_ID, rollId); + values.put(KEY_NAME, gameName); values.put(KEY, item.getKey()); try { values.put(KEY_VALUE, (String) item.getValue()); @@ -486,44 +479,18 @@ public class Database { } } /* - * try to update, if update fails insert + * we dont care about updating the history, just insert new information */ - if(!(mDb.update(GAME_HISTORY_TABLE, values, KEY_NAME + "="+ DatabaseUtils.sqlEscapeString(ringer_name) +" AND " + KEY +"='"+ item.getKey()+"'", null) > 0)) +// if(!(mDb.update(GAME_HISTORY_TABLE, values, KEY_NAME + "="+ DatabaseUtils.sqlEscapeString(gameName) +" AND " + KEY +"='"+ item.getKey()+"'", null) > 0)) mDb.insert(GAME_HISTORY_TABLE, null, values); } /* - * update the ringer table + * update the game table */ mDb.update(GAME_NAME_TABLE, game, "id" + "= "+ id, null); } - /** - * Updates all the roll ids after a row is deleted - * @param gameName - * @param id of the roll to start with - * @author ricky barrette - */ - private void updateRollIds(String gameName, int rollId) { - long currentRow; - ContentValues values = new ContentValues(); - Cursor cursor = this.mDb.query(GAME_HISTORY_TABLE, new String[] { KEY_ROLL_ID },KEY_NAME+" = "+ gameName, null, null, null, null); - if (cursor.moveToFirst()) { - do { - currentRow = cursor.getLong(0); - if(currentRow == rollId){ - rollId++; - values.clear(); - values.put(KEY_ROLL_ID, currentRow -1); - mDb.update(GAME_NAME_TABLE, values, KEY_ROLL_ID + "= "+ currentRow, null); - } - } while (cursor.moveToNext()); - } - if (cursor != null && !cursor.isClosed()) { - cursor.close(); - } - } - /** * Updates the row ids after a row is deleted * @param id of the row to start with diff --git a/ExaltedDice/src/com/TwentyCode/android/ExaltedDice/ExaltedDice.java b/ExaltedDice/src/com/TwentyCode/android/ExaltedDice/ExaltedDice.java index 57faa41..8b003c0 100755 --- a/ExaltedDice/src/com/TwentyCode/android/ExaltedDice/ExaltedDice.java +++ b/ExaltedDice/src/com/TwentyCode/android/ExaltedDice/ExaltedDice.java @@ -1,10 +1,10 @@ package com.TwentyCode.android.ExaltedDice; -import java.util.ArrayList; import java.util.Random; import android.app.Activity; import android.app.AlertDialog; +import android.content.ContentValues; import android.content.Context; import android.content.DialogInterface; import android.content.Intent; @@ -27,23 +27,24 @@ import android.widget.Toast; import com.TwentyCodes.android.exception.ExceptionHandler; -public class ExaltedDice extends Activity implements OnClickListener, OnItemClickListener, OnValueChangeListener, DatabaseListener { +public class ExaltedDice extends Activity implements OnClickListener, OnItemClickListener, OnValueChangeListener { - private ListView listview; - private ArrayList rollHistory = new ArrayList(); - private ArrayList rolled = new ArrayList(); + private ListView mListView; private int intSuccesses; private int mRolls = 1; private int mD = 2; private NumberPicker mNumberPicker; - private int mCurrentDie; private NumberPicker mDPicker; private Database mDb; private String mGameName; + private long mGameId; + private RollHistoryDatabaseAdapter mListAdapter; + private boolean isNewGame; private static final int MENU_QUIT = Menu.FIRST; private static final int MENU_CLEAR = Menu.FIRST + 1; private static final String TAG = "ExaltedDice"; public static final String KEY_GAME_NAME = "game_name"; + public static final String KEY_GAME_ID = "game_id"; private static final String[] DICE_VALUES = { "D2", "D3", "D4", "D6", "D8", "D10", "D12", "D20", "D100" }; /** @@ -52,9 +53,8 @@ public class ExaltedDice extends Activity implements OnClickListener, OnItemClic * @author ricky barrette */ private void clearHistory() { - rollHistory.clear(); - rolled.clear(); - listview.setAdapter(new ArrayAdapter(this, R.layout.list_row, rollHistory)); + //TODO clear history + refresh(); } /** @@ -97,11 +97,16 @@ public class ExaltedDice extends Activity implements OnClickListener, OnItemClic if(i != null) if(i.hasExtra(KEY_GAME_NAME)){ mGameName = i.getStringExtra(KEY_GAME_NAME); + mGameId = i.getLongExtra(KEY_GAME_ID, -1); this.setTitle(mGameName); + + Log.v(TAG, "game name ="+mGameName); + Log.v(TAG, "game id ="+mGameId); + } - listview = (ListView) findViewById(R.id.list); - listview.setOnItemClickListener(this); + mListView = (ListView) findViewById(R.id.list); + mListView.setOnItemClickListener(this); mDPicker = (NumberPicker) findViewById(R.id.d_Picker); mDPicker.setMinValue(0); @@ -121,10 +126,7 @@ public class ExaltedDice extends Activity implements OnClickListener, OnItemClic /* * display hello message */ - listview.setAdapter(new ArrayAdapter(this, R.layout.list_row, getResources().getStringArray(R.array.hello_msg))); - - System.gc(); - + mListView.setAdapter(new ArrayAdapter(this, R.layout.list_row, getResources().getStringArray(R.array.hello_msg))); } /** @@ -148,34 +150,17 @@ public class ExaltedDice extends Activity implements OnClickListener, OnItemClic return true; } - @Override - public void onDatabaseUpgrade() { - // TODO Auto-generated method stub - - } - - @Override - public void onDatabaseUpgradeComplete() { - // TODO Auto-generated method stub - - } - - @Override - public void onDeletionComplete() { - // TODO Auto-generated method stub - - } - /** * rolls same amount of dice as previous roll * @author ricky barrette */ @Override public void onItemClick(AdapterView arg0, View v, int position, long arg3) { - if(rolled.size() != 0){ - mNumberPicker.setValue(rolled.get(position)); - rollDice(); - } +// if(rolled.size() != 0){ +// mNumberPicker.setValue(rolled.get(position)); +// rollDice(); +// } + //TODO roll again } @@ -207,13 +192,6 @@ public class ExaltedDice extends Activity implements OnClickListener, OnItemClic mDb.close(); super.onPause(); } - - @Override - public void onRestoreComplete() { - // TODO Auto-generated method stub - - } - /** * resorts application state after rotation * @author ricky barrette @@ -231,11 +209,29 @@ public class ExaltedDice extends Activity implements OnClickListener, OnItemClic */ @Override protected void onResume() { - mDb = new Database(this, this); + this.setTitle(mDb.getGameName(mGameId)); + + if(mDb.getGameRollCount(mGameId) > 0){ + isNewGame = false; + refresh(); + } else + isNewGame = true; super.onResume(); } /** + * (non-Javadoc) + * @see android.app.Activity#onStart() + */ + @Override + protected void onStart() { + mDb = new Database(this); + mListAdapter = new RollHistoryDatabaseAdapter(mGameId, mDb, this); + mListView.setAdapter(mListAdapter); + super.onStart(); + } + + /** * saves application state before rotation * @author ricky barrette */ @@ -251,7 +247,6 @@ public class ExaltedDice extends Activity implements OnClickListener, OnItemClic switch(picker.getId()){ case R.id.d_Picker: mD = Integer.parseInt(DICE_VALUES[newVal].substring(1)); - mCurrentDie = newVal; break; case R.id.number_Picker: mRolls = newVal; @@ -281,6 +276,12 @@ public class ExaltedDice extends Activity implements OnClickListener, OnItemClic }); builder.show(); } + + public void refresh(){ + if(!isNewGame) + mListView.setAdapter(mListAdapter); + mListAdapter.notifyDataSetChanged(); + } /** * returns a custom string containing dice rolls and number of successes @@ -292,7 +293,6 @@ public class ExaltedDice extends Activity implements OnClickListener, OnItemClic public String results(int times) { Log.i(TAG, "results()"); StringBuffer resultsString = new StringBuffer(); - resultsString.append("Rolled "+ times +" "+DICE_VALUES[mCurrentDie]); /** * roll the dice @@ -316,7 +316,7 @@ public class ExaltedDice extends Activity implements OnClickListener, OnItemClic } /** - * Performs a dice roll + * Performs a dice roll and logs it's information in the database * * @author ricky barrette */ @@ -324,10 +324,16 @@ public class ExaltedDice extends Activity implements OnClickListener, OnItemClic // vibrate for 50 milliseconds vibrate(50); - rolled.add(0, mRolls); - rollHistory.add(0, results(mRolls)); - - listview.setAdapter(new ArrayAdapter(this, R.layout.list_row, rollHistory)); + int rollId = mDb.getGameRollCount(mGameId) +1; + + ContentValues roll = new ContentValues(); + roll.put(Database.KEY_D_TYPE, DICE_VALUES[mDPicker.getValue()]); + roll.put(Database.KEY_NUMBER, mNumberPicker.getValue()); + roll.put(Database.KEY_LOG, results(mRolls)); + + mDb.updateGame(mGameId, mGameName, roll, rollId); + + refresh(); } /** diff --git a/ExaltedDice/src/com/TwentyCode/android/ExaltedDice/GameListActivity.java b/ExaltedDice/src/com/TwentyCode/android/ExaltedDice/GameListActivity.java index e5c0225..b669f97 100644 --- a/ExaltedDice/src/com/TwentyCode/android/ExaltedDice/GameListActivity.java +++ b/ExaltedDice/src/com/TwentyCode/android/ExaltedDice/GameListActivity.java @@ -99,7 +99,7 @@ public class GameListActivity extends Activity implements OnClickListener, Datab @Override public void onItemClick(AdapterView parent, View view, int position, long id) { - startActivity(new Intent(this, ExaltedDice.class).putExtra(ExaltedDice.KEY_GAME_NAME, mDb.getGameName(id +1))); + startActivity(new Intent(this, ExaltedDice.class).putExtra(ExaltedDice.KEY_GAME_NAME, mDb.getGameName(id +1)).putExtra(ExaltedDice.KEY_GAME_ID, id+1)); } /** diff --git a/ExaltedDice/src/com/TwentyCode/android/ExaltedDice/NewGameDialog.java b/ExaltedDice/src/com/TwentyCode/android/ExaltedDice/NewGameDialog.java index f1594f2..735d475 100644 --- a/ExaltedDice/src/com/TwentyCode/android/ExaltedDice/NewGameDialog.java +++ b/ExaltedDice/src/com/TwentyCode/android/ExaltedDice/NewGameDialog.java @@ -38,8 +38,12 @@ public class NewGameDialog extends Dialog implements android.view.View.OnClickLi findViewById(R.id.new_game_button).setEnabled(false); String name = mGameName.getText().toString(); - mDb.insertGame(name, null); - mContext.startActivity(new Intent(mContext, ExaltedDice.class).putExtra(ExaltedDice.KEY_GAME_NAME, name)); + + Intent i = new Intent(mContext, ExaltedDice.class) + .putExtra(ExaltedDice.KEY_GAME_NAME, name) + .putExtra(ExaltedDice.KEY_GAME_ID, mDb.insertGame(name)); + + mContext.startActivity(i); this.dismiss(); } diff --git a/ExaltedDice/src/com/TwentyCode/android/ExaltedDice/RollHistoryDatabaseAdapter.java b/ExaltedDice/src/com/TwentyCode/android/ExaltedDice/RollHistoryDatabaseAdapter.java new file mode 100644 index 0000000..13f5e45 --- /dev/null +++ b/ExaltedDice/src/com/TwentyCode/android/ExaltedDice/RollHistoryDatabaseAdapter.java @@ -0,0 +1,103 @@ +/** + * RollHistoryDatabaseAdapter.java + * @date Feb 5, 2012 + * @author ricky barrette + * @author Twenty Codes, LLC + */ +package com.TwentyCode.android.ExaltedDice; + +import android.content.ContentValues; +import android.content.Context; +import android.util.Log; +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; +import android.widget.BaseAdapter; +import android.widget.TextView; + +/** + * This adapter will be used to display the roll history from a specific game from the database + * @author ricky barrette + */ +public class RollHistoryDatabaseAdapter extends BaseAdapter { + + private static final String TAG = "RollHistoryDatabaseAdapter"; + private long mGameId; + private Database mDb; + private String mGameName; + private LayoutInflater mInflater; + + /** + * Creates a new RollHistoryDatabaseAdapter + * @author ricky barrette + */ + public RollHistoryDatabaseAdapter(long gameId, Database db, Context context) { + mGameId = gameId; + mGameName = db.getGameName(gameId); + mDb = db; + mInflater = LayoutInflater.from(context); + } + + /** + * (non-Javadoc) + * @see android.widget.Adapter#getCount() + */ + @Override + public int getCount() { + Log.v(TAG, "getCount() "+mDb.getGameRollCount(mGameId)); + return mDb.getGameRollCount(mGameId); + } + + /** + * (non-Javadoc) + * @see android.widget.Adapter#getItem(int) + */ + @Override + public ContentValues getItem(int position) { + return mDb.getGameHistoryInfo(mGameName, position+1); + } + + /** + * (non-Javadoc) + * @see android.widget.Adapter#getItemId(int) + */ + @Override + public long getItemId(int position) { + return position; + } + + /** + * (non-Javadoc) + * @see android.widget.Adapter#getView(int, android.view.View, android.view.ViewGroup) + */ + @Override + public View getView(int position, View convertView, ViewGroup parent) { + ViewHolder holder; + + if (convertView == null) { + convertView = mInflater.inflate(R.layout.list_row, null); + + holder = new ViewHolder(); + holder.text = (TextView) convertView.findViewById(R.id.text1); + + convertView.setTag(holder); + } else { + holder = (ViewHolder) convertView.getTag(); + } + + ContentValues roll = getItem(position); + + StringBuffer s = new StringBuffer(); + s.append("Rolled: "+roll.getAsInteger(Database.KEY_NUMBER)); + s.append(" "+(String)roll.getAsString(Database.KEY_D_TYPE)); + s.append("\n"+roll.getAsString(Database.KEY_LOG)); + + holder.text.setText(s.toString()); + return convertView; + } + + private class ViewHolder { + TextView text; + } + +} \ No newline at end of file