package com.vorsk.crossfitr.models; import android.content.ContentValues; import android.content.Context; import android.database.Cursor; /** * DAO for "workout" table. * * Create a new instance and use the methods to interact with the database. * Data is returned as instances of WorkoutRow where each column is a * publicly accessible property. * * @author Vivek * @since 1.0 */ public class WorkoutModel extends SQLiteDAO { //// Constants // Table-specific columns public static final String COL_WK_TYPE = "workout_type_id"; public static final String COL_RECORD = "record"; public static final String COL_REC_TYPE = "record_type_id"; private Context context; /***** Constructors *****/ /** * Init SQLiteDAO with table "workout" * * @param ctx In the example they passed "this" from the calling class.. * I'm not really sure what this is yet. */ public WorkoutModel(Context ctx) { super("workout", ctx); context = ctx; } /***** Private *****/ /** * Utility method to grab all the rows from a cursor * * @param cr result of a query * @return Array of entries */ private WorkoutRow[] fetchWorkoutRows(Cursor cr) { if (cr == null) { return null; } WorkoutRow[] result = new WorkoutRow[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_wtid = cr.getColumnIndexOrThrow(COL_WK_TYPE); int ind_rec = cr.getColumnIndexOrThrow(COL_RECORD); int ind_rtid = cr.getColumnIndexOrThrow(COL_REC_TYPE); 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 WorkoutRow(); 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].workout_type_id = cr.getLong(ind_wtid); result[ii].record = cr.getInt(ind_rec); result[ii].record_type_id = cr.getLong(ind_rtid); valid = cr.moveToNext(); ii++; } cr.close(); return result; } /***** Public *****/ /** * Inserts a new entry into the workout table * TODO: does not work, violates unknown constraint * @param row * Add this entry to the DB * @return ID of newly added entry, -1 on failure */ public long insert(WorkoutRow row) { // TODO: Fix this? Seemed to be funky return super.insert(row.toContentValues()); } /** * Inserts a new entry into the workout table, defaults record to 0 * * @param name * @param desc * @param type Type of the workout (this.TYPE_GIRL, etc) * @param rec_type Type of scoring used (this.SCORE_TIME, etc) * @return ID of newly added entry, -1 on failure */ public long insert(String name, String desc, int type, int rec_type) { // Default COL_RECORD to NOT_SCORED return insert(name, desc, type, rec_type, NOT_SCORED); } /** * Inserts a new entry into the workout table * * @param name * @param desc * @param type Type of the workout (this.TYPE_GIRL, etc) * @param rec_type Type of scoring used (this.SCORE_TIME, etc) * @param record Best score received on this workout or this.NOT_SCORED * @return ID of newly added entry, -1 on failure */ public long insert(String name, String desc, int type, int rec_type, int record) { Integer wtype = (type == TYPE_NONE) ? null : type; Integer rtype = (rec_type == SCORE_NONE) ? null : rec_type; Integer rec = (record == NOT_SCORED) ? null : record; ContentValues cv = new ContentValues(); cv.put(COL_NAME, name); cv.put(COL_DESC, desc); cv.put(COL_WK_TYPE, wtype); cv.put(COL_REC_TYPE, rtype); cv.put(COL_RECORD, rec); return super.insert(cv); } /** * Call this to edit the properties of a workout entry * * @param row The new data to replace * @return Number of rows affected */ public long edit(WorkoutRow row) { return super.update(row.toContentValues(), COL_ID + " = " + row._id); } /** * Remove a workout definition. History for it will be removed * * @param id Workout definition ID to remove * @return Number of removed workouts */ public long delete(long id) { WorkoutSessionModel model = new WorkoutSessionModel(context); model.deleteWorkoutHistory(id); return super.delete(COL_ID + " = " + id); } /** * Recalculates the best record from existing sessions * * @param id Workout ID to recalculate * @param type Type of the Workout ID * @return Number of rows updated; -1 or 0 on failure */ public int calculateRecord(long id, long type) { String cond; if (type == SCORE_TIME) { cond = "MIN"; } else if (type == SCORE_WEIGHT || type == SCORE_REPS) { cond = "MAX"; } else { return -1; } WorkoutSessionModel model = new WorkoutSessionModel(context); ContentValues cv = new ContentValues(); cv.put(COL_RECORD, model.getWorkoutAggScore(id, cond)); return update(cv, COL_ID + "=" + id); } /** * Fetch an entry via the ID * * @param id * @return Associated entry or NULL on failure */ public WorkoutRow getByID(long id) { Cursor cr = selectByID(id); if (cr == null || cr.getCount() > 1) { return null; // TODO: Throw exception } WorkoutRow[] rows = fetchWorkoutRows(cr); return (rows.length == 0) ? null : rows[0]; } /** * Finds a workout matching a given name * * @param name the name to search for * @return the row id containing that workout, -1 on failure; */ public long getIDFromName(String name) { return super.selectIDByName(DB_TABLE, name); } /** * Fetch all workouts of a specific type (girl, hero, custom, wod) * * @param type The workout type; use constants (TYPE_GIRL, etc) * @return array of workouts, null on failure */ public WorkoutRow[] getAllByType(int type) { String[] col = { COL_WK_TYPE }; String[] val = { String.valueOf(type) }; Cursor cr = select(col, val); return fetchWorkoutRows(cr); } /** * Gets a workout_type's ID by its name * * @param name * @return ID of the workout type, -1 on failure */ public long getTypeID(String name) { return selectIDByName("workout_type", name); } /** * Gets a workout_type's name by its ID * * @param id * @return name of the workout type, NULL on failure */ public String getTypeName(long id) { return selectNameByID("workout_type", id); } }