diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index c66d819..3c1ed71 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -42,11 +42,11 @@ + android:value="com.rubenvandeven.emotionhero.MirrorMenuActivity" /> - + + + + \ No newline at end of file diff --git a/app/src/main/java/com/rubenvandeven/emotionhero/Achievement.java b/app/src/main/java/com/rubenvandeven/emotionhero/Achievement.java new file mode 100644 index 0000000..4ff29c6 --- /dev/null +++ b/app/src/main/java/com/rubenvandeven/emotionhero/Achievement.java @@ -0,0 +1,28 @@ +package com.rubenvandeven.emotionhero; + +import android.graphics.Bitmap; + +/** + * Created by ruben on 10/09/16. + * + * Achievements made in a specific game (as provided by the API) + */ + +public class Achievement { + public String title; + /** + * Html string + */ + public String description; + public Bitmap icon; + + public Achievement(String title, String description, Bitmap icon){ + this.title = title; + this.description = description; + this.icon = icon; + } + + public int getId() { + return AchievementCollection.getInstance().getId(this); + } +} diff --git a/app/src/main/java/com/rubenvandeven/emotionhero/AchievementCollection.java b/app/src/main/java/com/rubenvandeven/emotionhero/AchievementCollection.java new file mode 100644 index 0000000..0754357 --- /dev/null +++ b/app/src/main/java/com/rubenvandeven/emotionhero/AchievementCollection.java @@ -0,0 +1,38 @@ +package com.rubenvandeven.emotionhero; + +import android.support.v4.content.res.TypedArrayUtils; + +import java.util.ArrayList; + +/** + * Created by ruben on 10/09/16. + */ +public class AchievementCollection { + private ArrayList achievements = new ArrayList(){{ + // fill the collection :-) + add(new Achievement("Microexpressor", null, null)); + add(new Achievement("\"In pursuit of happiness\"", null, null)); + add(new Achievement("CEO", null, null)); + add(new Achievement("Kuleshov", null, null)); + add(new Achievement("Soap opera", null, null)); + add(new Achievement("Stock photo model", null, null)); + }}; + + private static AchievementCollection ourInstance = new AchievementCollection(); + + public static AchievementCollection getInstance() { + return ourInstance; + } + + private AchievementCollection() { + } + + // ids start at one + public Achievement get(int id) { + return achievements.get(id-1); + } + + public int getId(Achievement a){ + return achievements.indexOf(a) + 1; + } +} diff --git a/app/src/main/java/com/rubenvandeven/emotionhero/ApiRestClient.java b/app/src/main/java/com/rubenvandeven/emotionhero/ApiRestClient.java index ef1c4cb..d0cb408 100644 --- a/app/src/main/java/com/rubenvandeven/emotionhero/ApiRestClient.java +++ b/app/src/main/java/com/rubenvandeven/emotionhero/ApiRestClient.java @@ -19,6 +19,7 @@ import org.json.JSONObject; import java.io.UnsupportedEncodingException; import java.text.DateFormat; import java.text.SimpleDateFormat; +import java.util.ArrayList; import java.util.Locale; import java.util.TimeZone; @@ -245,6 +246,15 @@ public class ApiRestClient { hit.remoteId = hits.getString(Long.toString(hit.id)); gameHelper.saveRemoteId(hit); } + JSONArray jAchievements = response.getJSONArray("achievements"); + if(jAchievements.length() > 0){ + ArrayList achievements = new ArrayList(jAchievements.length()); + for (int ai = 0; ai < jAchievements .length(); ai++) { + achievements.add(AchievementCollection.getInstance().get(jAchievements.getInt(ai))); + } + game.achievements = achievements; + gameHelper.saveAchievementsForGame(game); + } } catch (JSONException e) { Log.e("API","Invalid data: " + response.toString()); e.printStackTrace(); diff --git a/app/src/main/java/com/rubenvandeven/emotionhero/Game.java b/app/src/main/java/com/rubenvandeven/emotionhero/Game.java index 1e59208..60ec414 100644 --- a/app/src/main/java/com/rubenvandeven/emotionhero/Game.java +++ b/app/src/main/java/com/rubenvandeven/emotionhero/Game.java @@ -3,6 +3,7 @@ package com.rubenvandeven.emotionhero; import com.loopj.android.http.JsonHttpResponseHandler; import com.loopj.android.http.RequestParams; +import java.lang.reflect.Array; import java.util.ArrayList; import java.util.Date; import java.util.HashMap; @@ -22,6 +23,7 @@ public class Game { public Date time; public String remoteId; public Map hits = new HashMap<>(); + public ArrayList achievements = new ArrayList<>(); public Game(Long id, int lvl_id, float score, float bonus, Date time, String remoteId) { this(id, new Scenario(lvl_id, null), score, bonus, time, remoteId); diff --git a/app/src/main/java/com/rubenvandeven/emotionhero/GameOpenHelper.java b/app/src/main/java/com/rubenvandeven/emotionhero/GameOpenHelper.java index eaf680a..66163dc 100644 --- a/app/src/main/java/com/rubenvandeven/emotionhero/GameOpenHelper.java +++ b/app/src/main/java/com/rubenvandeven/emotionhero/GameOpenHelper.java @@ -20,7 +20,7 @@ import java.util.Date; * adb pull /sdcard/emotionhero.db */ public class GameOpenHelper extends SQLiteOpenHelper { - private static final int DATABASE_VERSION = 4; + 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 + " (" + @@ -155,6 +155,19 @@ public class GameOpenHelper extends SQLiteOpenHelper { "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 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) { @@ -166,6 +179,7 @@ public class GameOpenHelper extends SQLiteOpenHelper { public void onCreate(SQLiteDatabase db) { db.execSQL(GAME_TABLE_CREATE); db.execSQL(HIT_TABLE_CREATE); + db.execSQL(GAME_ACH_TABLE_CREATE); } @Override @@ -186,6 +200,10 @@ public class GameOpenHelper extends SQLiteOpenHelper { 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 void insertGame(Game game) { @@ -256,6 +274,7 @@ public class GameOpenHelper extends SQLiteOpenHelper { ); games[i] = game; this.getHitsForGame(game); // hits are appended to game object + game.achievements = getAchievementsOfGame(game); i++; c.moveToNext(); } @@ -281,6 +300,24 @@ public class GameOpenHelper extends SQLiteOpenHelper { 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 @@ -413,4 +450,27 @@ public class GameOpenHelper extends SQLiteOpenHelper { 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 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 null; + + ArrayList achievements = new ArrayList<>(count); + c.moveToFirst(); + while (!c.isAfterLast()) { + achievements.add(AchievementCollection.getInstance().get(c.getInt(0))); + c.moveToNext(); + } + return achievements; + } + } diff --git a/app/src/main/java/com/rubenvandeven/emotionhero/ReviewAchievementsActivity.java b/app/src/main/java/com/rubenvandeven/emotionhero/ReviewAchievementsActivity.java new file mode 100644 index 0000000..d558e7e --- /dev/null +++ b/app/src/main/java/com/rubenvandeven/emotionhero/ReviewAchievementsActivity.java @@ -0,0 +1,83 @@ +package com.rubenvandeven.emotionhero; + +import android.support.v7.app.AppCompatActivity; +import android.os.Bundle; +import android.support.v7.widget.Toolbar; +import android.util.Log; +import android.view.WindowManager; +import android.widget.ImageView; +import android.widget.LinearLayout; +import android.widget.TextView; + +public class ReviewAchievementsActivity extends AppCompatActivity { + + public final static String INTENT_EXTRA_GAME_ID = "com.rubenvandeven.emotionhero.GAME_ID"; + + Player player; + + Game game; + + LinearLayout achievementsLayout; + TextView toDiscoverText; + + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + getWindow().addFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN); + setContentView(R.layout.activity_review_achievements); + + Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar); + setSupportActionBar(toolbar); + getSupportActionBar().setDisplayHomeAsUpEnabled(true); + getSupportActionBar().setTitle("Achievements"); + + achievementsLayout = (LinearLayout) findViewById(R.id.achievementsLayout); + toDiscoverText = (TextView) findViewById(R.id.toDiscoverText); + + player = Player.getInstance(getApplicationContext()); + + // get game from Intent + long gameId = getIntent().getLongExtra(INTENT_EXTRA_GAME_ID, 0); + Log.d("Review", "gameid:" + gameId); + if(gameId != 0) { + game = player.getGameOpenHelper().getGameByid(gameId); + if(game == null) { + Log.e("Highscore", "CANNOT FIND GAME!! " + gameId); + throw new RuntimeException("Cannot find specified game"); + } else { + Log.i("Highscore", "FOUND GAME" + game.id + " " + game.score); + } + } else { + // no game specified??? SHould not be possible so finish + finish(); + } + + for(Achievement achievement: game.achievements) { + addAchievement(achievement); + } + + int toDiscover = game.scenario.achievements.size() - game.achievements.size(); + + if(toDiscover > 0) { + toDiscoverText.setText(String.format("There are %1$d other achievements for this level.", toDiscover)); + } else { + toDiscoverText.setText("Wow, you obtained all achievements in one run!!"); + } + } + + public void addAchievement(Achievement achievement) { + TextView titleText = new TextView(this); + TextView descriptionText = new TextView(this); +// ImageView imageView = new ImageView(this); + + titleText.setText(achievement.title); + titleText.setTextColor(getResources().getColor(R.color.textHighlight)); + titleText.setTextSize(R.dimen.highscore_textsize); + + descriptionText.setText(achievement.description); + descriptionText.setTextColor(getResources().getColor(R.color.textPrimary)); + + achievementsLayout.addView(titleText); + achievementsLayout.addView(descriptionText); + } +} diff --git a/app/src/main/java/com/rubenvandeven/emotionhero/ReviewActivity.java b/app/src/main/java/com/rubenvandeven/emotionhero/ReviewActivity.java index 865903c..9f02781 100644 --- a/app/src/main/java/com/rubenvandeven/emotionhero/ReviewActivity.java +++ b/app/src/main/java/com/rubenvandeven/emotionhero/ReviewActivity.java @@ -45,6 +45,11 @@ public class ReviewActivity extends AppCompatActivity { TextView overallScorePercText; TextView overallScoreText; + + TextView achievementTitle; + RelativeLayout achievementLayout; + TextView achievementArrow; + TextView achievementText; TextView improveArrow; TextView hintText; RelativeLayout retryLayout; @@ -81,6 +86,8 @@ public class ReviewActivity extends AppCompatActivity { position.getInt("position"); scoreProgressBar.setVisibility(View.GONE); + + checkAchievements(); } catch (JSONException e) { e.printStackTrace(); Toast.makeText(getApplicationContext(), "Something went wrong when loading results", Toast.LENGTH_LONG).show(); @@ -137,6 +144,11 @@ public class ReviewActivity extends AppCompatActivity { overallScorePercText= (TextView) findViewById(R.id.overallScorePercText); overallScoreText= (TextView) findViewById(R.id.overallScoreText); + achievementTitle = (TextView) findViewById(R.id.achievementTitle); + achievementLayout = (RelativeLayout) findViewById(R.id.achievementLayout); + achievementArrow = (TextView) findViewById(R.id.achievementArrow); + achievementText = (TextView) findViewById(R.id.achievementText); + improveArrow = (TextView) findViewById(R.id.improveArrow); hintText = (TextView) findViewById(R.id.hintText); retryLayout = (RelativeLayout) findViewById(R.id.retryLayout); @@ -149,10 +161,12 @@ public class ReviewActivity extends AppCompatActivity { scoreProgressBar = (ProgressBar) findViewById(R.id.scoreProgressBar); + checkAchievements(); Typeface font = Typeface.createFromAsset(getAssets(), "unifont-9.0.02.ttf"); lvlNameText.setTypeface(font); overallScorePercText.setTypeface(font); + achievementArrow.setTypeface(font); retryArrow.setTypeface(font); improveArrow.setTypeface(font); nextLvlArrow.setTypeface(font); @@ -201,6 +215,33 @@ public class ReviewActivity extends AppCompatActivity { retryText.setText(retryString); } + public void checkAchievements() { + if(game.achievements.size() > 0) { + achievementTitle.setVisibility(View.VISIBLE); + achievementLayout.setVisibility(View.VISIBLE); + + String achievementString = ""; + for(Achievement achievement: game.achievements) { + if(achievementString.length() > 0) { + achievementString += "\n"; + } + achievementString += String.format("%2$s", achievement.title); + } + achievementText.setText(achievementString); + achievementLayout.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + Intent intent = new Intent(getApplicationContext(), ReviewAchievementsActivity.class); + intent.putExtra(ReviewAchievementsActivity.INTENT_EXTRA_GAME_ID, game.id); + startActivity(intent); + } + }); + } else { + achievementTitle.setVisibility(View.GONE); + achievementLayout.setVisibility(View.GONE); + } + } + /** * Translate 1 => 1st, 2 => 2nd etc. * Thanks to http://stackoverflow.com/a/23182005 diff --git a/app/src/main/java/com/rubenvandeven/emotionhero/Scenario.java b/app/src/main/java/com/rubenvandeven/emotionhero/Scenario.java index bcee462..99c80b8 100644 --- a/app/src/main/java/com/rubenvandeven/emotionhero/Scenario.java +++ b/app/src/main/java/com/rubenvandeven/emotionhero/Scenario.java @@ -60,6 +60,11 @@ public class Scenario { */ float minimumAchievements= 0; + /** + * Achievements one get obtain in this level + */ + ArrayList achievements = new ArrayList<>(); + /** * If a game is beign played. */ @@ -357,6 +362,7 @@ public class Scenario { } public void createTargets() { + AchievementCollection achievementCollection = AchievementCollection.getInstance(); switch(id) { case LVL_ANGER: setTarget(Emotion.ANGER, 100, 1); @@ -366,6 +372,13 @@ public class Scenario { setTarget(Emotion.ANGER, 40, 5); setTarget(Emotion.ANGER, 70, 6); setTarget(Emotion.ANGER, 100, 7); + + setMinimumScoreFromPercentage(10); + minimumAchievements = 2; + + achievements.add(achievementCollection.get(1)); + achievements.add(achievementCollection.get(3)); + break; case LVL_JOY: setTarget(Emotion.JOY, 100, 1); @@ -385,23 +398,46 @@ public class Scenario { setTarget(Emotion.JOY, 100, 18); setTarget(Emotion.JOY, 100, 19); setTarget(Emotion.JOY, 100, 20); + + + setMinimumScoreFromPercentage(10); + minimumAchievements = 2; + + + achievements.add(achievementCollection.get(2)); + achievements.add(achievementCollection.get(4)); + break; case LVL_SURPRISE: setTarget(Emotion.SURPRISE, 20, 1); setTarget(Emotion.SURPRISE, 50, 2); setTarget(Emotion.SURPRISE, 80, 3); setTarget(Emotion.SURPRISE, 100, 4); + + setMinimumScoreFromPercentage(10); + minimumAchievements = 2; + + achievements.add(achievementCollection.get(5)); + achievements.add(achievementCollection.get(6)); + break; case LVL_SADDNESS: setTarget(Emotion.SADNESS, 20, 1); setTarget(Emotion.SADNESS, 50, 2); setTarget(Emotion.SADNESS, 80, 3); setTarget(Emotion.SADNESS, 100, 4); + + setMinimumScoreFromPercentage(10); + minimumAchievements = 2; break; } } + public void setMinimumScoreFromPercentage(float percentage) { + this.minimumScore = maxScore * (percentage / 100f); + } + public int getNextLevelId() { int nextIdx = SCENARIOS.indexOf(id) + 1; if(SCENARIOS.size() <= nextIdx) { diff --git a/app/src/main/res/layout/activity_review.xml b/app/src/main/res/layout/activity_review.xml index 2685440..f6bcfae 100644 --- a/app/src/main/res/layout/activity_review.xml +++ b/app/src/main/res/layout/activity_review.xml @@ -127,7 +127,53 @@ android:textAlignment="center" android:textColor="@color/textSecondary" /> + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +