emotionhero/app/src/main/java/com/rubenvandeven/emotionhero/GameOpenHelper.java

505 lines
20 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 = 5;
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"
};
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);
}
}
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());
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, 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);
}
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
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;
}
}