From 38b41a60539039cee60785edf2d9775942f2898c Mon Sep 17 00:00:00 2001 From: Ruben Date: Tue, 6 Sep 2016 14:35:40 +0100 Subject: [PATCH] Syncing scores to https API and retreiving score position & hints --- .idea/misc.xml | 2 +- .../emotionhero/ApiRestClient.java | 41 +- .../emotionhero/GameOpenHelper.java | 5 +- .../emotionhero/GamingActivity.java | 88 +--- .../emotionhero/HighscoreActivity.java | 5 +- .../emotionhero/IntroActivity.java | 10 +- .../emotionhero/MenuActivity.java | 16 + .../emotionhero/ReviewActivity.java | 161 ++++++- .../rubenvandeven/emotionhero/Scenario.java | 5 + app/src/main/res/layout/activity_gaming.xml | 15 - app/src/main/res/layout/activity_review.xml | 438 ++++++++++-------- app/src/main/res/values/strings.xml | 1 + 12 files changed, 481 insertions(+), 306 deletions(-) diff --git a/.idea/misc.xml b/.idea/misc.xml index bd04605..1b77328 100644 --- a/.idea/misc.xml +++ b/.idea/misc.xml @@ -37,7 +37,7 @@ - + diff --git a/app/src/main/java/com/rubenvandeven/emotionhero/ApiRestClient.java b/app/src/main/java/com/rubenvandeven/emotionhero/ApiRestClient.java index 935fa0a..c02b953 100644 --- a/app/src/main/java/com/rubenvandeven/emotionhero/ApiRestClient.java +++ b/app/src/main/java/com/rubenvandeven/emotionhero/ApiRestClient.java @@ -34,10 +34,15 @@ import cz.msebera.android.httpclient.entity.StringEntity; */ public class ApiRestClient { - private static final String BASE_URL = "http://api.emotionhero.com"; // TODO: https! + private static final String BASE_URL = "https://api.emotionhero.com"; // TODO: https! - private static AsyncHttpClient client = new AsyncHttpClient(); -// private static SyncHttpClient syncClient = new SyncHttpClient(); + /** + * For some reason validation of SSL certificate needs to be disabled (using true). + * Otherwise async-http-client tries to validate other virtualhost (rubenvandeven.com) with api.emotionhero.com + * which obviously is not the same domain. For some reason the connection is handles properly + * by apache (so it detects the right VirtualHost...) ... odd :-( + */ + private static AsyncHttpClient client = new AsyncHttpClient(true, 80, 443); private String jwt; @@ -223,7 +228,7 @@ public class ApiRestClient { e.printStackTrace(); } - this.post("/me/games", postBody, new JsonHttpResponseHandler(){ + this.post("/games", postBody, new JsonHttpResponseHandler(){ @Override public void onSuccess(int statusCode, Header[] headers, JSONObject response) { @@ -251,7 +256,7 @@ public class ApiRestClient { @Override public void onFailure(int statusCode, Header[] headers, Throwable throwable, JSONObject response) { - onFailure(statusCode, headers, response.toString(), throwable); + onFailure(statusCode, headers, response == null ? null:response.toString(), throwable); } }); @@ -261,17 +266,25 @@ public class ApiRestClient { Log.e("API", "FAILURE ON REQUEST!"); Log.e("API", throwable.getMessage()); Log.e("API", "Status: "+statusCode); - Log.e("API", "Headers:"); - for(Header header: headers) { - Log.e("API", "\t" + header.getName() + ": " + header.getValue()); + if(headers == null){ + Log.e("API", "\tNULL"); + } else { + for(Header header: headers) { + Log.e("API", "\t" + header.getName() + ": " + header.getValue()); + } } Log.e("API", "Response:"); - int maxLogSize = 1000; - for(int i = 0; i <= responseString.length() / maxLogSize; i++) { - int start = i * maxLogSize; - int end = (i+1) * maxLogSize; - end = end > responseString.length() ? responseString.length() : end; - Log.e("API", responseString.substring(start, end)); + if(responseString == null) { + Log.e("API", "\tNULL!"); + } + else { + int maxLogSize = 1000; + for(int i = 0; i <= responseString.length() / maxLogSize; i++) { + int start = i * maxLogSize; + int end = (i+1) * maxLogSize; + end = end > responseString.length() ? responseString.length() : end; + Log.e("API", responseString.substring(start, end)); + } } } } diff --git a/app/src/main/java/com/rubenvandeven/emotionhero/GameOpenHelper.java b/app/src/main/java/com/rubenvandeven/emotionhero/GameOpenHelper.java index bc7b420..fcef55e 100644 --- a/app/src/main/java/com/rubenvandeven/emotionhero/GameOpenHelper.java +++ b/app/src/main/java/com/rubenvandeven/emotionhero/GameOpenHelper.java @@ -6,6 +6,7 @@ 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; @@ -376,7 +377,9 @@ public class GameOpenHelper extends SQLiteOpenHelper { } public int getLocalRankOfGame(Game game) { - String[] params = { Long.toString(game.scenario.id), Float.toString(game.score) }; + String[] params = { Long.toString(game.scenario.id), Double.toString(game.score) }; + 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 > ?", params); c.moveToFirst(); return c.getInt(0); diff --git a/app/src/main/java/com/rubenvandeven/emotionhero/GamingActivity.java b/app/src/main/java/com/rubenvandeven/emotionhero/GamingActivity.java index 9abbb3b..a52374f 100644 --- a/app/src/main/java/com/rubenvandeven/emotionhero/GamingActivity.java +++ b/app/src/main/java/com/rubenvandeven/emotionhero/GamingActivity.java @@ -56,9 +56,6 @@ public class GamingActivity extends AppCompatActivity implements Detector.ImageL boolean has_camera_permission = false; - Button restartButton; - Button nextLvlButton; - public SoundPool sound; public HashMap soundIds = new HashMap<>(); @@ -85,34 +82,6 @@ public class GamingActivity extends AppCompatActivity implements Detector.ImageL mContentView = (TextView) findViewById(R.id.fullscreen_content); RelativeLayout videoLayout = (RelativeLayout) findViewById(R.id.video_layout); - restartButton = (Button) findViewById(R.id.restartButton); - restartButton.setOnClickListener(new View.OnClickListener() { - @Override - public void onClick(View view) { - finish(); - startActivity(getIntent()); - } - }); - nextLvlButton = (Button) findViewById(R.id.nextLvlButton); - nextLvlButton.setOnClickListener(new View.OnClickListener() { - @Override - public void onClick(View view) { - finish(); - Intent intent = getIntent(); // trouble create new intent because of 'this' - intent.putExtra(INTENT_EXTRA_SCENARIO, currentScenario.getNextLevelId()); - startActivity(intent); - } - }); - - // Set up the user interaction to manually show or hide the system UI. - mContentView.setOnClickListener(new View.OnClickListener() { - @Override - public void onClick(View view) { -// toggle(); - } - }); - - //We create a custom SurfaceView that resizes itself to match the aspect ratio of the incoming camera frames cameraPreview = new SurfaceView(this) { @Override @@ -344,53 +313,35 @@ public class GamingActivity extends AppCompatActivity implements Detector.ImageL } public void finishLevel() { -// setText("LEVEL ENDED"); stopDetector(); -// restartButton.setVisibility(View.VISIBLE); -// if(!currentScenario.isFinalLevel()) { -// nextLvlButton.setVisibility(View.VISIBLE); -// } PlayerInfo playerInfo = player.getPlayerInfo(); - ScoreList scores = playerInfo.getScoresForLevel(currentScenario.id); - Score score = currentScenario.getScore(); - - if(score.score == currentScenario.getMaxScore()) { - // Maximum SCORE!! - // You nailed it! - } if(scores.isEmpty()) { - // First play! Nice :-) - } - else if(scores.isHighest(score)) { - // HIGHSCORE!!!!! - } else { - // Better luck next time - } - - // show the highscores (top 3?)... +// ScoreList scores = playerInfo.getScoresForLevel(currentScenario.id); +// Score score = currentScenario.getScore(); +// +// if(score.score == currentScenario.getMaxScore()) { +// // Maximum SCORE!! +// // You nailed it! +// } if(scores.isEmpty()) { +// // First play! Nice :-) +// } +// else if(scores.isHighest(score)) { +// // HIGHSCORE!!!!! +// } else { +// // Better luck next time +// } // check whether this is the highest reached level by the player // ... used by 'continue' button in main menu Scenario nextScenario = new Scenario(currentScenario.getNextLevelId(), this); - if(nextScenario.isHigherThen(playerInfo.reachedLevelId)) { + if(currentScenario.minimumScore < currentScenario.game.score && nextScenario.isHigherThen(playerInfo.reachedLevelId)) { + // allow player to continue to next level :-) playerInfo.reachedLevelId = nextScenario.id; } - scores.add(score); +// scores.add(score); player.savePlayerInfo(playerInfo); -// String highscoreText = "TOPSCORES\n"; -// -// ScoreList topscores = scores.getTopN(3); // TODO: only highscores for current lEVEL!!!!!!! -// int i = 0; -// for(Score topscore: topscores) { -// i++; -// highscoreText += String.format("%1$d. %2$.2f\n", i, topscore.score); //make line by line elements -// } -// -// TextView highscoreView = (TextView) findViewById(R.id.highscores); -// highscoreView.setText(highscoreText); -// highscoreView.setVisibility(View.VISIBLE); finish(); GameOpenHelper gameHelper = new GameOpenHelper(getApplicationContext()); @@ -401,10 +352,5 @@ public class GamingActivity extends AppCompatActivity implements Detector.ImageL intent.putExtra(ReviewActivity.INTENT_EXTRA_GAME_ID, currentScenario.game.id); intent.putExtra(ReviewActivity.INTENT_EXTRA_FROM_GAME, true); startActivity(intent); - -// Intent intent = new Intent(this, HighscoreActivity.class); -// intent.putExtra(HighscoreActivity.INTENT_EXTRA_SCORE_ID, score.id.toString()); -// intent.putExtra(HighscoreActivity.INTENT_EXTRA_GAME_ID, currentScenario.game.id.toString()); -// startActivity(intent); } } diff --git a/app/src/main/java/com/rubenvandeven/emotionhero/HighscoreActivity.java b/app/src/main/java/com/rubenvandeven/emotionhero/HighscoreActivity.java index 93500b8..b2c5b58 100644 --- a/app/src/main/java/com/rubenvandeven/emotionhero/HighscoreActivity.java +++ b/app/src/main/java/com/rubenvandeven/emotionhero/HighscoreActivity.java @@ -1,5 +1,6 @@ package com.rubenvandeven.emotionhero; +import android.app.ProgressDialog; import android.content.Intent; import android.graphics.Typeface; import android.support.design.widget.FloatingActionButton; @@ -216,7 +217,7 @@ public class HighscoreActivity extends AppCompatActivity { for(Game game: games) { final long itemGameId = game.id; i++; - String highscoreText = String.format("%1$d. %2$.3f", i, game.score); //make line by line elements + String highscoreText = String.format("%1$d. %2$.4f", i, game.score); //make line by line elements TextView scoreItem = new TextView(getContext()); scoreItem.setText(highscoreText); scoreItem.setTextColor(ContextCompat.getColor(getContext(), R.color.highscore)); @@ -272,6 +273,8 @@ public class HighscoreActivity extends AppCompatActivity { startLvlButton.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { + ProgressDialog dialog = ProgressDialog.show(getContext(), "", + getContext().getResources().getString(R.string.load_game_activity), true); Intent intent = new Intent(getContext(), GamingActivity.class); intent.putExtra(GamingActivity.INTENT_EXTRA_SCENARIO, scenario.id); getActivity().finish(); diff --git a/app/src/main/java/com/rubenvandeven/emotionhero/IntroActivity.java b/app/src/main/java/com/rubenvandeven/emotionhero/IntroActivity.java index 749cd9f..605a342 100644 --- a/app/src/main/java/com/rubenvandeven/emotionhero/IntroActivity.java +++ b/app/src/main/java/com/rubenvandeven/emotionhero/IntroActivity.java @@ -35,12 +35,10 @@ public class IntroActivity extends AppCompatActivity { player = Player.getInstance(getApplicationContext()); - int extraLogoDelay; - if(player.isNew()) { - extraLogoDelay = 1500; - } else { - extraLogoDelay = 0; - } + int extraLogoDelay = 0; +// if(player.isNew()) { +// extraLogoDelay = 1500; +// } View introView = findViewById(R.id.activity_intro); diff --git a/app/src/main/java/com/rubenvandeven/emotionhero/MenuActivity.java b/app/src/main/java/com/rubenvandeven/emotionhero/MenuActivity.java index ab7c65d..d17df2c 100644 --- a/app/src/main/java/com/rubenvandeven/emotionhero/MenuActivity.java +++ b/app/src/main/java/com/rubenvandeven/emotionhero/MenuActivity.java @@ -2,9 +2,11 @@ package com.rubenvandeven.emotionhero; import android.animation.AnimatorSet; import android.animation.ObjectAnimator; +import android.app.ProgressDialog; import android.content.Intent; import android.support.v7.app.AppCompatActivity; import android.os.Bundle; +import android.view.Menu; import android.view.View; import android.view.WindowManager; import android.view.animation.AlphaAnimation; @@ -17,6 +19,8 @@ public class MenuActivity extends AppCompatActivity { Player player; + ProgressDialog loadGameDialog; + @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); @@ -81,14 +85,19 @@ public class MenuActivity extends AppCompatActivity { startButton.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { + loadGameDialog = ProgressDialog.show(MenuActivity.this, "", + MenuActivity.this.getResources().getString(R.string.load_game_activity), true); Intent intent = new Intent(MenuActivity.this, GamingActivity.class); startActivity(intent); + } }); continueButton.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { + loadGameDialog= ProgressDialog.show(MenuActivity.this, "", + MenuActivity.this.getResources().getString(R.string.load_game_activity), true); Intent intent = new Intent(MenuActivity.this, GamingActivity.class); intent.putExtra(GamingActivity.INTENT_EXTRA_SCENARIO, player.getPlayerInfo().reachedLevelId); startActivity(intent); @@ -115,4 +124,11 @@ public class MenuActivity extends AppCompatActivity { } + + @Override + protected void onResume() { + super.onResume(); + if(loadGameDialog != null) + loadGameDialog.dismiss(); + } } diff --git a/app/src/main/java/com/rubenvandeven/emotionhero/ReviewActivity.java b/app/src/main/java/com/rubenvandeven/emotionhero/ReviewActivity.java index df939a1..7f1941d 100644 --- a/app/src/main/java/com/rubenvandeven/emotionhero/ReviewActivity.java +++ b/app/src/main/java/com/rubenvandeven/emotionhero/ReviewActivity.java @@ -1,17 +1,29 @@ package com.rubenvandeven.emotionhero; +import android.app.ProgressDialog; import android.content.Intent; import android.graphics.Typeface; +import android.os.Handler; import android.support.v7.app.AppCompatActivity; import android.os.Bundle; import android.support.v7.widget.Toolbar; import android.util.Log; import android.view.MenuItem; +import android.view.View; import android.view.WindowManager; +import android.widget.ProgressBar; +import android.widget.RelativeLayout; import android.widget.TextView; +import android.widget.Toast; +import com.loopj.android.http.JsonHttpResponseHandler; + +import org.json.JSONException; +import org.json.JSONObject; import org.ocpsoft.prettytime.PrettyTime; +import cz.msebera.android.httpclient.Header; + public class ReviewActivity extends AppCompatActivity { @@ -27,6 +39,65 @@ public class ReviewActivity extends AppCompatActivity { */ protected boolean fromGame; + TextView lvlNameText; + TextView dateText; + TextView scoreText; + TextView overallScorePercText; + TextView overallScoreText; + + TextView improveArrow; + TextView hintText; + RelativeLayout retryLayout; + TextView retryArrow; + TextView retryText; + + RelativeLayout nextLvlLayout; + TextView nextLvlArrow; + TextView nextLvlText; + + ProgressBar scoreProgressBar; + + protected Runnable loadRemoteInfo = new Runnable() { + @Override + public void run() { + // retry until remoteId is set. + if(game.remoteId == null) { + final Handler handler = new Handler(); + handler.postDelayed(loadRemoteInfo,500); + return; + } else { + player.api.get("/games/"+game.remoteId, null, new JsonHttpResponseHandler(){ + @Override + public void onSuccess(int statusCode, Header[] headers, JSONObject response) { + try { + JSONObject position = response.getJSONObject("position"); +// overallScorePercText.setText(String.format("%1$.0f%%", position.getDouble("percentage"))); + overallScoreText.setText(String.format("You beat %1$.0f%%", position.getDouble("percentage"))); + overallScorePercText.setText(Integer.toString(position.getInt("position"))); + if(response.has("hint")) + { + hintText.setText(response.getString("hint")); + } + position.getInt("position"); + + scoreProgressBar.setVisibility(View.GONE); + } catch (JSONException e) { + e.printStackTrace(); + Toast.makeText(getApplicationContext(), "Something went wrong when loading results", Toast.LENGTH_LONG).show(); + } + } + @Override + public void onFailure(int statusCode, Header[] headers, String response, Throwable throwable) { + throwable.printStackTrace(); + Log.e("API", response == null ? "NULL" : response); + Toast.makeText(getApplicationContext(), "Something went wrong when loading results", Toast.LENGTH_LONG).show(); + scoreProgressBar.setVisibility(View.GONE); + } + }); + } + } + }; + @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); @@ -60,13 +131,23 @@ public class ReviewActivity extends AppCompatActivity { finish(); } - TextView lvlNameText = (TextView) findViewById(R.id.lvlNameText); - TextView dateText = (TextView) findViewById(R.id.dateText); - TextView scoreText= (TextView) findViewById(R.id.scoreText); - TextView overallScorePercText= (TextView) findViewById(R.id.overallScorePercText); - TextView improveArrow = (TextView) findViewById(R.id.improveArrow); - TextView retryArrow = (TextView) findViewById(R.id.retryArrow); + lvlNameText = (TextView) findViewById(R.id.lvlNameText); + dateText = (TextView) findViewById(R.id.dateText); + scoreText= (TextView) findViewById(R.id.scoreText); + overallScorePercText= (TextView) findViewById(R.id.overallScorePercText); + overallScoreText= (TextView) findViewById(R.id.overallScoreText); + improveArrow = (TextView) findViewById(R.id.improveArrow); + hintText = (TextView) findViewById(R.id.hintText); + retryLayout = (RelativeLayout) findViewById(R.id.retryLayout); + retryArrow = (TextView) findViewById(R.id.retryArrow); + retryText = (TextView) findViewById(R.id.retryText); + + nextLvlLayout = (RelativeLayout) findViewById(R.id.nextLvlLayout); + nextLvlArrow = (TextView) findViewById(R.id.nextLvlArrow); + nextLvlText = (TextView) findViewById(R.id.nextLvlText); + + scoreProgressBar = (ProgressBar) findViewById(R.id.scoreProgressBar); Typeface font = Typeface.createFromAsset(getAssets(), "unifont-9.0.02.ttf"); @@ -74,14 +155,78 @@ public class ReviewActivity extends AppCompatActivity { overallScorePercText.setTypeface(font); retryArrow.setTypeface(font); improveArrow.setTypeface(font); + nextLvlArrow.setTypeface(font); lvlNameText.setText("\""+game.scenario.toString()+"\""); PrettyTime p = new PrettyTime(); dateText.setText(p.format(game.time)); - scoreText.setText(String.format("%1$.3f", game.score)); - overallScorePercText.setText(String.format("%1$.0f%%", 30f)); + scoreText.setText(String.format("%1$.4f", game.score)); +// overallScorePercText.setText(String.format("%1$.0f%%", 30f)); + + loadRemoteInfo.run(); + + retryLayout.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + Intent intent = new Intent(getApplicationContext(), GamingActivity.class); + intent.putExtra(GamingActivity.INTENT_EXTRA_SCENARIO, game.scenario.id); + ProgressDialog dialog = ProgressDialog.show(ReviewActivity.this, "", + getApplicationContext().getResources().getString(R.string.load_game_activity), true); + finish(); + startActivity(intent); + } + }); + + if(player.getPlayerInfo().hasAccessToLevel(game.scenario.getNextLevelId())) { + nextLvlLayout.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + Intent intent = new Intent(getApplicationContext(), GamingActivity.class); + intent.putExtra(GamingActivity.INTENT_EXTRA_SCENARIO, game.scenario.getNextLevelId()); + ProgressDialog dialog = ProgressDialog.show(ReviewActivity.this, "", + getApplicationContext().getResources().getString(R.string.load_game_activity), true); + finish(); + startActivity(intent); + } + }); + } else { + nextLvlText.setVisibility(View.GONE); + nextLvlLayout.setVisibility(View.GONE); + } + int rank = player.getGameOpenHelper().getLocalRankOfGame(game); + String personalScoreJudgement = rank < 7 ? "nice work!" : "you can do better."; + String retryString = "Your " + rank + intToPosition(rank) + " score, " + personalScoreJudgement + " Now, retry and improve your performance."; + retryText.setText(retryString); + } + + /** + * Translate 1 => 1st, 2 => 2nd etc. + * Thanks to http://stackoverflow.com/a/23182005 + * @param number + * @return + */ + public static String intToPosition(int number) { + String value = String.valueOf(number); + if(value.length() > 1) { + // Check for special case: 11 - 13 are all "th". + // So if the second to last digit is 1, it is "th". + char secondToLastDigit = value.charAt(value.length()-2); + if(secondToLastDigit == '1') + return "th"; + } + char lastDigit = value.charAt(value.length()-1); + switch(lastDigit) { + case '1': + return "st"; + case '2': + return "nd"; + case '3': + return "rd"; + default: + return "th"; + } } @Override diff --git a/app/src/main/java/com/rubenvandeven/emotionhero/Scenario.java b/app/src/main/java/com/rubenvandeven/emotionhero/Scenario.java index 285ae70..3ec0e8f 100644 --- a/app/src/main/java/com/rubenvandeven/emotionhero/Scenario.java +++ b/app/src/main/java/com/rubenvandeven/emotionhero/Scenario.java @@ -40,6 +40,11 @@ public class Scenario { float duration = 0; + /** + * Minimum score to be able to pass to the next level. + */ + float minimumScore = 0; + /** * If a game is beign played. */ diff --git a/app/src/main/res/layout/activity_gaming.xml b/app/src/main/res/layout/activity_gaming.xml index d181eab..62cea64 100644 --- a/app/src/main/res/layout/activity_gaming.xml +++ b/app/src/main/res/layout/activity_gaming.xml @@ -49,21 +49,6 @@ android:visibility="gone" /> -