545 lines
22 KiB
Java
545 lines
22 KiB
Java
package com.rubenvandeven.emotionhero;
|
|
|
|
import android.content.ContentValues;
|
|
import android.content.Context;
|
|
import android.content.Intent;
|
|
import android.database.Cursor;
|
|
import android.database.sqlite.SQLiteDatabase;
|
|
import android.database.sqlite.SQLiteOpenHelper;
|
|
import android.graphics.Bitmap;
|
|
import android.graphics.BitmapFactory;
|
|
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 = 6;
|
|
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," +
|
|
"lost_face_time VARCHAR(255) NOT NULL," +
|
|
"remoteId VARCHAR(255) DEFAULT NULL, " +
|
|
"PRIMARY KEY(id));";
|
|
private static final String[] GAME_PROJECTION = {
|
|
"id",
|
|
"lvl_id",
|
|
"score",
|
|
"bonus",
|
|
"time",
|
|
"lost_face_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"
|
|
};
|
|
|
|
private static final String GAME_ACH_TABLE_NAME = "game_achievements";
|
|
private static final String GAME_ACH_TABLE_CREATE =
|
|
"CREATE TABLE " + GAME_ACH_TABLE_NAME + " (" +
|
|
"id INTEGER NOT NULL," +
|
|
"game_id INTEGER NOT NULL," +
|
|
"achievement_id INTEGER NOT NULL," +
|
|
"PRIMARY KEY(id));";
|
|
private static final String[] GAME_ACH_PROJECTION = {
|
|
"id",
|
|
"game_id",
|
|
"achievement_id",
|
|
};
|
|
|
|
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);
|
|
db.execSQL(GAME_ACH_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);");
|
|
}
|
|
if(oldVersion == 4 && newVersion == 5) {
|
|
db.execSQL(GAME_ACH_TABLE_CREATE);
|
|
}
|
|
if(oldVersion == 5 && newVersion == 6) {
|
|
db.execSQL("ALTER TABLE games ADD lost_face_time VARCHAR(255);");
|
|
}
|
|
|
|
}
|
|
|
|
public Bitmap getImageForHit(Hit hit) {
|
|
String[] params = { Long.toString(hit.id) };
|
|
Cursor c = getReadableDatabase().rawQuery("SELECT image FROM hits h WHERE h.id = ?", params);
|
|
c.moveToFirst();
|
|
byte[] imageBytes= c.getBlob(0);
|
|
if(imageBytes == null)
|
|
{
|
|
return null;
|
|
}
|
|
return BitmapFactory.decodeByteArray(imageBytes, 0, imageBytes.length);
|
|
}
|
|
|
|
public void clearImageForHit(Hit hit) {
|
|
String[] params = { Long.toString(hit.id) };
|
|
getWritableDatabase().rawQuery("UPDATE hits SET image = NULL WHERE id = ?", params);
|
|
}
|
|
|
|
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());
|
|
values.put("lost_face_time", game.lostFaceTime);
|
|
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);
|
|
}
|
|
|
|
saveAchievementsForGame(game);
|
|
}
|
|
|
|
public Game[] getGamesForLevel(int lvl_id) {
|
|
Scenario scenario = new Scenario(lvl_id, null);
|
|
return getGamesForScenario(scenario, null);
|
|
}
|
|
|
|
public Game[] getGamesForScenario(Scenario s, Integer limit) {
|
|
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
|
|
limit == null ? null : Integer.toString(limit) // no limit!
|
|
);
|
|
return cursorToGames(c, s);
|
|
}
|
|
|
|
/**
|
|
* Get the game that was played before this game
|
|
* @param game
|
|
* @return Game
|
|
*/
|
|
public Game getPreviousGame(Game game) {
|
|
SQLiteDatabase db = getReadableDatabase();
|
|
|
|
String selection = "lvl_id = ? AND time < ?";
|
|
String[] selectionArgs = { Integer.toString(game.scenario.id), Long.toString(game.time.getTime()) };
|
|
|
|
String sortOrder = "time 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
|
|
"1" // only last item
|
|
);
|
|
|
|
if(c.getCount() < 1)
|
|
return null;
|
|
|
|
Game[] games = cursorToGames(c, game.scenario);
|
|
return games[0];
|
|
}
|
|
|
|
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"))
|
|
);
|
|
game.lostFaceTime = c.getFloat(c.getColumnIndex("lost_face_time"));
|
|
games[i] = game;
|
|
this.getHitsForGame(game); // hits are appended to game object
|
|
game.achievements = getAchievementsOfGame(game);
|
|
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 saveAchievementsForGame(Game game) {
|
|
SQLiteDatabase db = getWritableDatabase();
|
|
|
|
if(game.achievements.size() < 1) {
|
|
return;
|
|
}
|
|
|
|
// New value for one column
|
|
for(Achievement achievement: game.achievements) {
|
|
ContentValues values = new ContentValues();
|
|
values.put("game_id", game.id);
|
|
values.put("achievement_id", achievement.getId());
|
|
|
|
db.insert(GAME_ACH_TABLE_NAME, null, values);
|
|
}
|
|
|
|
}
|
|
|
|
|
|
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 Game getHighscoreGameForScenario(Scenario scenario) {
|
|
Game[] games = getGamesForScenario(scenario, 1);
|
|
if(games == null || games.length == 0) {
|
|
return null;
|
|
}
|
|
return games[0];
|
|
}
|
|
|
|
public ArrayList<Hit> 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<Hit> cursorToHits(Game game, Cursor c) {
|
|
ArrayList<Hit> hits = new ArrayList<Hit>(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);
|
|
}
|
|
|
|
public int countAchievementsForLevel(int lvl_id) {
|
|
String[] params = { Long.toString(lvl_id) };
|
|
Cursor c = getReadableDatabase().rawQuery("SELECT COUNT(DISTINCT achievement_id) FROM games g INNER JOIN game_achievements ga ON ga.game_id = g.id WHERE g.lvl_id = ?", params);
|
|
c.moveToFirst();
|
|
return c.getInt(0);
|
|
}
|
|
|
|
public ArrayList<Achievement> getAchievementsOfGame(Game game) {
|
|
String[] params = { Long.toString(game.id) };
|
|
Cursor c = getReadableDatabase().rawQuery("SELECT achievement_id FROM games g INNER JOIN game_achievements ga ON ga.game_id = g.id WHERE g.id = ?", params);
|
|
int count = c.getCount();
|
|
if(count < 1)
|
|
return new ArrayList<Achievement>();
|
|
|
|
ArrayList<Achievement> achievements = new ArrayList<>(count);
|
|
c.moveToFirst();
|
|
while (!c.isAfterLast()) {
|
|
achievements.add(AchievementCollection.getInstance().get(c.getInt(0)));
|
|
c.moveToNext();
|
|
}
|
|
return achievements;
|
|
}
|
|
|
|
}
|