Game achievements

This commit is contained in:
Ruben 2016-09-10 15:51:34 +01:00
parent fedb7563d9
commit 02cf5d6065
11 changed files with 425 additions and 5 deletions

View file

@ -42,11 +42,11 @@
<activity
android:name=".HighscoreActivity"
android:label="@string/title_activity_highscore"
android:parentActivityName=".MenuActivity"
android:parentActivityName=".MirrorMenuActivity"
android:theme="@style/AppTheme.NoActionBar">
<meta-data
android:name="android.support.PARENT_ACTIVITY"
android:value="com.rubenvandeven.emotionhero.MenuActivity" />
android:value="com.rubenvandeven.emotionhero.MirrorMenuActivity" />
</activity>
<activity
android:name=".CreditsActivity"
@ -54,7 +54,13 @@
<activity
android:name=".ReviewActivity"
android:theme="@style/AppTheme.NoActionBar" />
<activity android:name=".MirrorMenuActivity"></activity>
<activity android:name=".MirrorMenuActivity" />
<activity android:name=".ReviewAchievementsActivity"
android:theme="@style/AppTheme.NoActionBar">
<meta-data
android:name="android.support.PARENT_ACTIVITY"
android:value="com.rubenvandeven.emotionhero.ReviewActivity" />
</activity>
</application>
</manifest>

View file

@ -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);
}
}

View file

@ -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<Achievement> achievements = new ArrayList<Achievement>(){{
// 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;
}
}

View file

@ -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<Achievement> achievements = new ArrayList<Achievement>(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();

View file

@ -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<Integer, Hit> hits = new HashMap<>();
public ArrayList<Achievement> 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);

View file

@ -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<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 null;
ArrayList<Achievement> achievements = new ArrayList<>(count);
c.moveToFirst();
while (!c.isAfterLast()) {
achievements.add(AchievementCollection.getInstance().get(c.getInt(0)));
c.moveToNext();
}
return achievements;
}
}

View file

@ -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);
}
}

View file

@ -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

View file

@ -60,6 +60,11 @@ public class Scenario {
*/
float minimumAchievements= 0;
/**
* Achievements one get obtain in this level
*/
ArrayList<Achievement> 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) {

View file

@ -127,7 +127,53 @@
android:textAlignment="center"
android:textColor="@color/textSecondary" />
<TextView
android:text="ACHIEVEMENTS"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="@+id/achievementTitle"
android:fontFamily="sans-serif"
android:textColor="@color/textPrimary"
android:layout_below="@+id/overallScoreText"
android:layout_alignLeft="@+id/overallScoreText"
android:layout_alignStart="@+id/overallScoreText"
android:layout_marginTop="16dp"
android:layout_marginBottom="5dp"
tools:visibility="visible"
android:visibility="gone" />
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="@color/colorPrimaryDark"
android:padding="@dimen/fab_margin"
android:layout_below="@+id/achievementTitle"
android:layout_alignParentLeft="true"
android:layout_alignParentStart="true"
android:id="@+id/achievementLayout"
tools:visibility="visible"
android:visibility="gone">
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:id="@+id/achievementText"
android:layout_toLeftOf="@+id/achievementArrow"
android:layout_centerInParent="true"
android:textColor="@color/textHighlight"
tools:text="No achievements." />
<TextView
android:text=">"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentRight="true"
android:layout_alignParentEnd="true"
android:id="@+id/achievementArrow"
android:textColor="@color/textHighlight"
android:textSize="36sp"
android:layout_centerInParent="true" />
</RelativeLayout>
<TextView
android:text="IMPROVE"
@ -136,7 +182,7 @@
android:id="@+id/improveTitle"
android:fontFamily="sans-serif"
android:textColor="@color/textPrimary"
android:layout_below="@+id/overallScoreText"
android:layout_below="@+id/achievementLayout"
android:layout_alignLeft="@+id/overallScoreText"
android:layout_alignStart="@+id/overallScoreText"
android:layout_marginTop="16dp"

View file

@ -0,0 +1,70 @@
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/activity_review_achievements"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context="com.rubenvandeven.emotionhero.ReviewAchievementsActivity">
<android.support.design.widget.AppBarLayout
android:id="@+id/appbar"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:paddingTop="@dimen/appbar_padding_top"
android:theme="@style/AppTheme.AppBarOverlay"
android:layout_marginBottom="10dp"
>
<android.support.v7.widget.Toolbar
android:id="@+id/toolbar"
android:layout_width="match_parent"
android:layout_height="?attr/actionBarSize"
android:background="?attr/colorPrimary"
app:layout_scrollFlags="scroll|enterAlways"
app:popupTheme="@style/AppTheme.PopupOverlay"
app:titleTextColor="@color/textHighlight">
</android.support.v7.widget.Toolbar>
</android.support.design.widget.AppBarLayout>
<ScrollView
android:id="@+id/achievementScrollView"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_below="@+id/appbar"
android:layout_above="@+id/toDiscoverText"
android:layout_alignParentLeft="true"
android:layout_alignParentStart="true">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical"
android:id="@+id/achievementsLayout" >
</LinearLayout>
</ScrollView>
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:id="@+id/toDiscoverText"
android:text="more achievements to discover."
android:layout_alignParentBottom="true"
android:layout_alignParentLeft="true"
android:layout_alignParentStart="true"
android:background="@color/colorPrimaryDark"
android:padding="@dimen/fab_margin"
android:textAlignment="center"
android:fontFamily="sans-serif"
android:textSize="18sp"
android:textColor="@color/textHighlight">
</TextView>
</RelativeLayout>