Updated Exalted Dice to insert new rolls into the database, and created a list view adapter that displays roll history from the database.

Change-Id: I0e288d0e89ee0041f70eb363049f5808a94c282b
This commit is contained in:
2012-02-05 13:35:28 -05:00
parent 21fd9a73a0
commit 397baca5a7
5 changed files with 272 additions and 192 deletions

View File

@@ -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<String> getAllGameTitles() {
List<String> list = new ArrayList<String>();
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<String, Object> 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<String, Object> 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

View File

@@ -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<String> rollHistory = new ArrayList<String>();
private ArrayList<Integer> rolled = new ArrayList<Integer>();
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<String>(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<String>(this, R.layout.list_row, getResources().getStringArray(R.array.hello_msg)));
System.gc();
mListView.setAdapter(new ArrayAdapter<String>(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<String>(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();
}
/**

View File

@@ -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));
}
/**

View File

@@ -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();
}

View File

@@ -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;
}
}