package com.rubenvandeven.emotionhero; import android.content.ContentValues; import android.content.Context; import android.database.Cursor; import android.database.sqlite.SQLiteDatabase; import android.database.sqlite.SQLiteOpenHelper; import android.graphics.PointF; import android.util.Log; import java.util.ArrayList; import java.util.Date; /** * Created by ruben on 02/09/16. * * To test data: * adb -d shell "run-as com.rubenvandeven.emotionhero ls /data/data/com.rubenvandeven.emotionhero/databases/" * adb -d shell "run-as com.rubenvandeven.emotionhero cp /data/data/com.rubenvandeven.emotionhero/databases/emotionhero.db /sdcard/emotionhero.db" * adb pull /sdcard/emotionhero.db */ public class GameOpenHelper extends SQLiteOpenHelper { private static final int DATABASE_VERSION = 4; private static final String GAME_TABLE_NAME = "games"; private static final String GAME_TABLE_CREATE = "CREATE TABLE " + GAME_TABLE_NAME + " (" + "id INTEGER NOT NULL," + "lvl_id INTEGER NOT NULL," + "score VARCHAR(255) NOT NULL," + "bonus VARCHAR(255) NOT NULL," + "time INTEGER NOT NULL," + "remoteId VARCHAR(255) DEFAULT NULL, " + "PRIMARY KEY(id));"; private static final String[] GAME_PROJECTION = { "id", "lvl_id", "score", "bonus", "time", "remoteId" }; private static final String HIT_TABLE_NAME = "hits"; public static final String HIT_TABLE_CREATE = "CREATE TABLE hits (" + "id INTEGER NOT NULL," + "game_id INTEGER NOT NULL," + "target_index INTEGER NOT_NULL," + "score VARCHAR(20)," + "bonus VARCHAR(20)," + "remoteId VARCHAR(20)," + "glasses VARCHAR(20)," + "ethnicity VARCHAR(20)," + "age VARCHAR(20)," + "gender VARCHAR(1)," + "anger VARCHAR(20)," + "contempt VARCHAR(20)," + "disgust VARCHAR(20)," + "fear VARCHAR(20)," + "joy VARCHAR(20)," + "sadness VARCHAR(20)," + "surprise VARCHAR(20)," + "roll VARCHAR(20)," + "pitch VARCHAR(20)," + "yaw VARCHAR(20)," + "inter_ocular_distance VARCHAR(20)," + "mouth_open VARCHAR(20)," + "lip_press VARCHAR(20)," + "brow_raise VARCHAR(20)," + "nose_wrinkler VARCHAR(20)," + "lip_depressor VARCHAR(20)," + "brow_furrow VARCHAR(20)," + "attention VARCHAR(20)," + "smile VARCHAR(20)," + "inner_brow_raiser VARCHAR(20)," + "chin_raiser VARCHAR(20)," + "smirk VARCHAR(20)," + "lip_suck VARCHAR(20)," + "upper_lip_raiser VARCHAR(20)," + "lip_pucker VARCHAR(20)," + "eye_closure VARCHAR(20)," + "engagement VARCHAR(20)," + "valence VARCHAR(20)," + "point_0x VARCHAR(20)," + "point_0y VARCHAR(20)," + "point_1x VARCHAR(20)," + "point_1y VARCHAR(20)," + "point_2x VARCHAR(20)," + "point_2y VARCHAR(20)," + "point_3x VARCHAR(20)," + "point_3y VARCHAR(20)," + "point_4x VARCHAR(20)," + "point_4y VARCHAR(20)," + "point_5x VARCHAR(20)," + "point_5y VARCHAR(20)," + "point_6x VARCHAR(20)," + "point_6y VARCHAR(20)," + "point_7x VARCHAR(20)," + "point_7y VARCHAR(20)," + "point_8x VARCHAR(20)," + "point_8y VARCHAR(20)," + "point_9x VARCHAR(20)," + "point_9y VARCHAR(20)," + "point_10x VARCHAR(20)," + "point_10y VARCHAR(20)," + "point_11x VARCHAR(20)," + "point_11y VARCHAR(20)," + "point_12x VARCHAR(20)," + "point_12y VARCHAR(20)," + "point_13x VARCHAR(20)," + "point_13y VARCHAR(20)," + "point_14x VARCHAR(20)," + "point_14y VARCHAR(20)," + "point_15x VARCHAR(20)," + "point_15y VARCHAR(20)," + "point_16x VARCHAR(20)," + "point_16y VARCHAR(20)," + "point_17x VARCHAR(20)," + "point_17y VARCHAR(20)," + "point_18x VARCHAR(20)," + "point_18y VARCHAR(20)," + "point_19x VARCHAR(20)," + "point_19y VARCHAR(20)," + "point_20x VARCHAR(20)," + "point_20y VARCHAR(20)," + "point_21x VARCHAR(20)," + "point_21y VARCHAR(20)," + "point_22x VARCHAR(20)," + "point_22y VARCHAR(20)," + "point_23x VARCHAR(20)," + "point_23y VARCHAR(20)," + "point_24x VARCHAR(20)," + "point_24y VARCHAR(20)," + "point_25x VARCHAR(20)," + "point_25y VARCHAR(20)," + "point_26x VARCHAR(20)," + "point_26y VARCHAR(20)," + "point_27x VARCHAR(20)," + "point_27y VARCHAR(20)," + "point_28x VARCHAR(20)," + "point_28y VARCHAR(20)," + "point_29x VARCHAR(20)," + "point_29y VARCHAR(20)," + "point_30x VARCHAR(20)," + "point_30y VARCHAR(20)," + "point_31x VARCHAR(20)," + "point_31y VARCHAR(20)," + "point_32x VARCHAR(20)," + "point_32y VARCHAR(20)," + "point_33x VARCHAR(20)," + "point_33y VARCHAR(20)," + "image BLOB," + "PRIMARY KEY (id));" ; private static final String[] HIT_PROJECTION = { "id","game_id", "target_index","score","bonus","remoteId","glasses","ethnicity","age","gender","anger","contempt","disgust","fear","joy","sadness","surprise","roll","pitch","yaw","inter_ocular_distance","mouth_open","lip_press","brow_raise","nose_wrinkler","lip_depressor","brow_furrow","attention","smile","inner_brow_raiser","chin_raiser","smirk","lip_suck","upper_lip_raiser","lip_pucker","eye_closure","engagement","valence","point_0x","point_0y","point_1x","point_1y","point_2x","point_2y","point_3x","point_3y","point_4x","point_4y","point_5x","point_5y","point_6x","point_6y","point_7x","point_7y","point_8x","point_8y","point_9x","point_9y","point_10x","point_10y","point_11x","point_11y","point_12x","point_12y","point_13x","point_13y","point_14x","point_14y","point_15x","point_15y","point_16x","point_16y","point_17x","point_17y","point_18x","point_18y","point_19x","point_19y","point_20x","point_20y","point_21x","point_21y","point_22x","point_22y","point_23x","point_23y","point_24x","point_24y","point_25x","point_25y","point_26x","point_26y","point_27x","point_27y","point_28x","point_28y","point_29x","point_29y","point_30x","point_30y","point_31x","point_31y","point_32x","point_32y","point_33x","point_33y", "image" }; private Context context; GameOpenHelper(Context context) { super(context, "emotionhero.db", null, DATABASE_VERSION); this.context = context; } @Override public void onCreate(SQLiteDatabase db) { db.execSQL(GAME_TABLE_CREATE); db.execSQL(HIT_TABLE_CREATE); } @Override public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) { // until now there is only 1 database version.. so no alter table statements if(oldVersion == 1 && newVersion == 2) { // run alter statements db.execSQL("DROP TABLE hits"); db.execSQL("DROP TABLE games"); db.execSQL(GAME_TABLE_CREATE); db.execSQL(HIT_TABLE_CREATE); } if(oldVersion == 2 && newVersion == 3) { db.execSQL("ALTER TABLE hits ADD image BLOB;"); } if(oldVersion == 3 && newVersion == 4) { db.execSQL("ALTER TABLE hits ADD bonus VARCHAR(20);"); db.execSQL("ALTER TABLE games ADD bonus VARCHAR(255);"); } } public void insertGame(Game game) { // Gets the data repository in write mode SQLiteDatabase db = getWritableDatabase(); // Create a new map of values, where column names are the keys ContentValues values = new ContentValues(); values.put("lvl_id", game.scenario.id); values.put("score", game.score); values.put("bonus", game.bonus); values.put("time", game.time.getTime()); if(game.remoteId == null) { values.putNull("remoteId"); } else { values.put("remoteId", game.remoteId); } // Insert the new row, returning the primary key value of the new row long newRowId = db.insert(GAME_TABLE_NAME, null, values); game.id = newRowId; for(Hit hit: game.hits.values()) { insertHit(hit); } } public Game[] getGamesForLevel(int lvl_id) { Scenario scenario = new Scenario(lvl_id, null); return getGamesForScenario(scenario); } public Game[] getGamesForScenario(Scenario s) { SQLiteDatabase db = getReadableDatabase(); String selection = "lvl_id = ?"; String[] selectionArgs = { Integer.toString(s.id) }; String sortOrder = "score+bonus DESC"; Cursor c = db.query( GAME_TABLE_NAME, // The table to query GAME_PROJECTION, // The columns to return selection, // The columns for the WHERE clause selectionArgs, // The values for the WHERE clause null, // don't group the rows null, // don't filter by row groups sortOrder, // The sort order null // no limit! ); return cursorToGames(c, s); } public Game[] cursorToGames(Cursor c, Scenario s) { Game[] games = new Game[c.getCount()]; int i = 0; c.moveToFirst(); while (!c.isAfterLast()) { Scenario scenario = s == null ? new Scenario(c.getInt(c.getColumnIndex("lvl_id")), null) : s; Game game = new Game( c.getLong(c.getColumnIndex("id")), scenario, c.getFloat(c.getColumnIndex("score")), c.getFloat(c.getColumnIndex("bonus")), new Date(c.getLong(c.getColumnIndex("time"))), c.getString(c.getColumnIndex("remoteId")) ); games[i] = game; this.getHitsForGame(game); // hits are appended to game object i++; c.moveToNext(); } return games; } public void saveRemoteId(Game game) { SQLiteDatabase db = getWritableDatabase(); // New value for one column ContentValues values = new ContentValues(); values.put("remoteId", game.remoteId); // Which row to update, based on the title String selection = "id = ?"; String[] selectionArgs = { Long.toString(game.id) }; int count = db.update( GAME_TABLE_NAME, values, selection, selectionArgs); } public void insertHit(Hit hit) { // Gets the data repository in write mode SQLiteDatabase db = getWritableDatabase(); // Create a new map of values, where column names are the keys ContentValues values = new ContentValues(); values.put("game_id", hit.game.id); values.put("target_index", hit.target.index); values.put("score", hit.score); values.put("bonus", hit.bonus); values.put("glasses", hit.glasses); values.put("ethnicity", hit.ethnicity); values.put("age", hit.age); values.put("gender", hit.gender); for(Emotion emotion: Emotion.values()) { values.put(emotion.name().toLowerCase(), hit.emotions.get(emotion)); } for(Expression exp: Expression.values()) { values.put(exp.getDbName(), hit.expressions.get(exp)); } int i=0; for(PointF point: hit.points) { values.put("point_"+i+"x", point.x); values.put("point_"+i+"y", point.y); i++; } if(hit.remoteId == null) { values.putNull("remoteId"); } else { values.put("remoteId", hit.remoteId); } byte[] frameBytes = hit.getFrameAsByteArray(); if(frameBytes != null) { values.put("image", frameBytes); } // Insert the new row, returning the primary key value of the new row long newRowId = db.insert(HIT_TABLE_NAME, null, values); hit.id = newRowId; } public ArrayList getHitsForGame(Game game) { SQLiteDatabase db = getReadableDatabase(); String selection = "game_id = ?"; String[] selectionArgs = { Long.toString(game.id) }; String sortOrder = "target_index ASC"; Cursor c = db.query( HIT_TABLE_NAME, // The table to query HIT_PROJECTION, // The columns to return selection, // The columns for the WHERE clause selectionArgs, // The values for the WHERE clause null, // don't group the rows null, // don't filter by row groups sortOrder, // The sort order null // no limit! ); return cursorToHits(game, c); } public ArrayList cursorToHits(Game game, Cursor c) { ArrayList hits = new ArrayList(c.getCount()); c.moveToFirst(); while (!c.isAfterLast()) { hits.add(new Hit(game, c)); c.moveToNext(); } return hits; } public void saveRemoteId(Hit hit) { SQLiteDatabase db = getWritableDatabase(); // New value for one column ContentValues values = new ContentValues(); values.put("remoteId", hit.remoteId); // reset image after sync to avoid to much data used on phone // values.putNull("image"); // Which row to update, based on the title String selection = "id = ?"; String[] selectionArgs = { Long.toString(hit.id) }; int count = db.update( HIT_TABLE_NAME, values, selection, selectionArgs); } public Game getGameByid(long id) { SQLiteDatabase db = getReadableDatabase(); String selection = "id = ?"; String[] selectionArgs = { Long.toString(id) }; Cursor c = db.query( GAME_TABLE_NAME, // The table to query GAME_PROJECTION, // The columns to return selection, // The columns for the WHERE clause selectionArgs, // The values for the WHERE clause null, // don't group the rows null, // don't filter by row groups null, // The sort order null // no limit! ); Game[] games = cursorToGames(c, null); return games[0]; } public int getLocalRankOfGame(Game game) { String[] params = { Long.toString(game.scenario.id), Double.toString(game.score + game.bonus) }; Log.e("GAME",params[0].toString()); Log.e("GAME",params[1].toString()); Cursor c = getReadableDatabase().rawQuery("SELECT COUNT(id)+1 FROM games WHERE lvl_id = ? AND score+bonus > ?", params); c.moveToFirst(); return c.getInt(0); } }