package com.vorsk.crossfitr.models;
import android.content.ContentValues;
import android.content.Context;
import android.database.Cursor;
/**
* DAO for "Achievement" table.
*
* Create a new instance and use the methods to interact with the database.
* Data is returned as instances of AchievementRow where each column
* is a publicly accessible property.
*
* @author Vivek and Sam
* @since 1.0
*/
public class AchievementModel extends SQLiteDAO
{
//// Constants
// Table-specific columns
public static final String COL_NAME = "name";
public static final String COL_DESC = "description";
public static final String COL_ACH_TYPE = "achievement_type_id";
public static final String COL_THRESH = "progress_thresh";
public static final String COL_PROG = "progress";
public static final String COL_COUNT = "count";
/***** Constructors *****/
/**
* Init SQLiteDAO with table "Achievement"
*
* @param ctx In the example they passed "this" from the calling class..
* I'm not really sure what this is yet.
*/
public AchievementModel(Context ctx)
{
super("achievement", ctx);
}
/***** Private *****/
/**
* Utility method to grab all the rows from a cursor
*
* @param cr result of a query
* @return Array of entries
*/
private AchievementRow[] fetchAchievementRows(Cursor cr)
{
if (cr == null) {
return null;
}
AchievementRow[] result = new AchievementRow[cr.getCount()];
if (result.length == 0) {
cr.close();
return result;
}
boolean valid = cr.moveToFirst();
int ii = 0;
// Grab the cursor's column indices
// An error here indicates the COL constants aren't synced with the DB
int ind_id = cr.getColumnIndexOrThrow(COL_ID);
int ind_name = cr.getColumnIndexOrThrow(COL_NAME);
int ind_desc = cr.getColumnIndexOrThrow(COL_DESC);
int ind_atid = cr.getColumnIndexOrThrow(COL_ACH_TYPE);
int ind_thres = cr.getColumnIndexOrThrow(COL_THRESH);
int ind_prog = cr.getColumnIndexOrThrow(COL_PROG);
int ind_cnt = cr.getColumnIndexOrThrow(COL_COUNT);
int ind_dm = cr.getColumnIndexOrThrow(COL_MDATE);
int ind_dc = cr.getColumnIndexOrThrow(COL_CDATE);
// Iterate over every row (move the cursor down the set)
while (valid) {
result[ii] = new AchievementRow();
fetchBaseData(cr, result[ii], ind_id, ind_dm, ind_dc);
result[ii].name = cr.getString(ind_name);
result[ii].description = cr.getString(ind_desc);
result[ii].achievement_type_id = cr.getLong(ind_atid);
result[ii].progress_thresh = cr.getInt(ind_thres);
result[ii].progress = cr.getInt(ind_prog);
result[ii].count = cr.getInt(ind_cnt);
valid = cr.moveToNext();
ii ++;
}
cr.close();
return result;
}
/***** Public *****/
/**
* Inserts a new entry into the workout table
*
* @param row Add this entry to the DB
* @return ID of newly added entry, -1 on failure
*/
public long insert(AchievementRow row)
{
return super.insert(row.toContentValues());
}
/**
* Inserts a new entry into the achievement table, defaults record to 0
*
* @param name
* @param description
* @param achievement_type Type of the achievement.. TODO
* @param threshold Limit of the progress before awarded
* @param progress Progress towards getting this
* @param count number of times this was earned
* @return ID of newly added entry, -1 on failure
*/
public long insert(String name, String description, long achievement_type,
int threshold, int progress, int count)
{
ContentValues cv = new ContentValues();
cv.put(COL_NAME, name);
cv.put(COL_DESC, description);
cv.put(COL_ACH_TYPE, achievement_type);
cv.put(COL_THRESH, threshold);
cv.put(COL_PROG, progress);
cv.put(COL_COUNT, count);
return super.insert(cv);
}
/**
* Attempts to update a previously entered achievement. If the update fails,
* or the achievement has not yet passed the threshold it returns null. If it
* has passed the threshold it will return the description for a display toast.
*
* @param achievementType
* Type of achievement to update
* @return AchievementRow containing achievement if threshold
* is passed, null if not, or failed.
*/
public String getProgress(int achievementType) {
AchievementRow[] achievement;
// Check if the all workout achievements need to be updated.
if(achievementType == AchievementModel.TYPE_HERO || achievementType == AchievementModel.TYPE_GIRL){
AchievementRow[] all = this.getAllByType(AchievementModel.TYPE_ALL);
AchievementRow[] other = this.getAllByType(achievementType);
achievement = new AchievementRow[all.length + other.length];
System.arraycopy(all, 0, achievement, 0, all.length);
System.arraycopy(other, 0, achievement, all.length, other.length);
}
else{
achievement = this.getAllByType(achievementType);
}
ContentValues cv;
String totalAchievement = null;
for(int i = 0; i < achievement.length; i++)
{
cv = new ContentValues();
cv.put(COL_NAME, achievement[i].name);
// Increment progress of achievement
int newProgress = achievement[i].progress;
newProgress += 1;
cv.put(COL_PROG, newProgress);
// If the progress has passed the threshold, update the count
// and return the name of the achievement
if(newProgress >= (achievement[i].progress_thresh) &&
achievement[i].count == 0){
cv.put(COL_COUNT, 1);
super.update(cv, "name='" + achievement[i].name + "'");
if(totalAchievement == null){
totalAchievement = "Achievement Earned: " + achievement[i].name;
}
else{
totalAchievement += "\nAchievement Earned: " + achievement[i].name;
}
}
else{
super.update(cv, "name='" + achievement[i].name + "'");
}
}
return totalAchievement;
}
/**
* Gets the total number of achievements earned
*
* @return Total achievements
*/
public int getTotal()
{
String[] count = new String[1];
count[0] = "count";
String[] one = new String[1];
one[0] = "1";
return selectCount(count, one);
}
/**
* Fetch all achievements of a specific type (girl, hero, custom, all)
*
* @param type The achievement type; use constants (TYPE_GIRL, etc)
* @return array of achievements, null on failure
*/
public AchievementRow[] getAllByType(int type)
{
String[] col = { COL_ACH_TYPE };
String[] val = { String.valueOf(type) };
Cursor cr = select(col, val);
return fetchAchievementRows(cr);
}
/**
* Fetch all achievements
*
* @return List of each profile attribute and value
*/
public AchievementRow[] getAll() {
Cursor cr = select(new String[] {}, new String[] {});
return fetchAchievementRows(cr);
}
/**
* Fetch a specific achievement by name
*
* @param name
* Achievement name to retrieve
* @return Associated entry or NULL on failure
*/
public AchievementRow getByName(String name) {
Cursor cr = select(new String[] { COL_NAME }, new String[] { name});
// Name should be unique
/*
* if (cr.getCount() > 1) { // TODO: Throw exception? }
*/
AchievementRow[] rows = fetchAchievementRows(cr);
return (rows.length == 0) ? null : rows[0];
}
/**
* Fetch an entry via the ID
*
* @param id
* @return Associated entry or NULL on failure
*/
public AchievementRow getByID(long id)
{
Cursor cr = selectByID(id);
if (cr.getCount() > 1) {
return null; // TODO: Throw exception
}
AchievementRow[] rows = fetchAchievementRows(cr);
return (rows.length == 0) ? null : rows[0];
}
}