Skip to content
This repository has been archived by the owner on Jul 25, 2022. It is now read-only.

Commit

Permalink
Merge remote-tracking branch 'origin/master' into feature/cleanup-about
Browse files Browse the repository at this point in the history
  • Loading branch information
dhebbeker committed Mar 28, 2018
2 parents 38bb01b + 6f2ff2c commit 8a351b9
Show file tree
Hide file tree
Showing 13 changed files with 277 additions and 5 deletions.
31 changes: 30 additions & 1 deletion CONTRIBUTING.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,37 @@ This document shall give you some guidelines in order to help you to contribute

# Coding Rules
Before committing to this repository, please:

* Use automatic code formatting with the [project specific format](.idea/codeStyleSettings.xml).
* Make sure your code does not introduce warnings or errors.
* Test your contribution on the target device.
* We use [SemVer](http://semver.org/) for versioning. For the versions available, see the [tags on this repository](https://github.com/dhebbeker/memorex-android/tags).
* Project build configuration is setup for [Android Studio](https://developer.android.com/studio/index.html)
* Project build configuration is setup for [Android Studio](https://developer.android.com/studio/index.html)

# Versioning
Versions in this project shall be specified according to the [Semantic Versioning](https://semver.org/) 2 specification (SemVer2). Additional rules specify details of the usage.

Tags which point to defined versions shall use the version name prefixed with a `v` as this is [common practice](https://github.com/semver/semver/issues/235#issuecomment-346477428) on GitHub.

## Development releases
A development release is defined as a release, which is only on a branch, which is not the normal release branch. A development release aims to be included within the normal release branch after development is completed.
The normal release branch is `master`.
The following rule does specify how to name versions in development releases using Backus–Naur form:

<version> ::= <X>"."<Y>"."<Z>"-0.develop+"<dev-id>
<X> ::= <X'> | <X'>+1
<X'> ::= mayjor version of the normal release this development is based on
<Y> ::= <Y'> | <Y'>+1
<Y'> ::= minor version of the normal release this development is based on
<Z> ::= <Z'> | <Z'>+1
<Z'> ::= patch version of the normal release this development is based on
<dev-id> ::= <branch>"."<commits>"."<object>
<branch> ::= branch name
<commits> ::= number of additional commits on top of the normal release this development is based on
<object> ::= abbreviated object name of the most recent commit

The major, minor or patch number are incremented according to SemVer2. Exactly one of major, minor or patch number must be incremented.
The branch name must satisfy the requirements for pre-release version identifiers of SemVer2. Slashes (`/`) in branch names must be replaced with hyphens (`-`).
The abbreviated object name of the most recent commit may be a tag, a revision number or a hash.

The following is a valid example of a version *tag*: `v6.6.5-0.develop+feature-update-notification.1.gf934dc7`
5 changes: 5 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,7 @@
**Download latest release of Memorex App:** Got to [latest release][] page and download the *`app-release-vX-Y-Z.apk` asset*.

[latest release]: https://github.com/dhebbeker/memorex-android/releases/latest "latest release on GitHub"

# Memorex

Memorex is a simple game for short time diversion. The challenge is to memorize a sequence of symbols. The sequence is displayed by the game and the player has to repeat it directly afterwards. On success the game increments the sequence by another symbol and repeats. There are four different symbols with a color and tone each.
Expand Down Expand Up @@ -47,6 +51,7 @@ Please refer to the [releases page][1] to download the Android application packa
This app certainly has potential to grow. In case you played it, you may already have some features in mind to enhance the game.

Contributors are welcome! Please read our [Code of Conduct][6]. These are some of the possibilities to contribute to the project:

* Create an issue on the [issue page][3] in order to ask questions related to the project or app, report a problem, or request a new feature.
* Create or edit pages in the [project wiki][4] in order to document the app or the project itself.
* Please feel free to contribute source code! These [guidelines][5] may help you doing so.
Expand Down
1 change: 1 addition & 0 deletions app/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -60,4 +60,5 @@ dependencies {
testImplementation 'junit:junit:4.12'
androidTestImplementation 'com.android.support.test:runner:1.0.1'
androidTestImplementation 'com.android.support.test.espresso:espresso-core:3.0.1'
compile "com.google.code.gson:gson:2.8.2"
}
11 changes: 11 additions & 0 deletions app/src/main/AndroidManifest.xml
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,17 @@
android:name="android.support.PARENT_ACTIVITY"
android:value="info.hebbeker.david.memorex.MainActivity" />
</activity>
<activity
android:name=".DisplayHighScore"
android:label="High scores"
android:parentActivityName=".MainActivity"
tools:ignore="UnusedAttribute">

<!-- The meta-data tag is required if you support API level 15 and lower -->
<meta-data
android:name="android.support.PARENT_ACTIVITY"
android:value=".MainActivity" />
</activity>
</application>

</manifest>
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
package info.hebbeker.david.memorex;

import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
import android.text.Html;
import android.widget.TextView;

import java.io.Serializable;

public class DisplayHighScore extends AppCompatActivity
{

@Override
protected void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_display_high_score);
final Serializable currentHighScore = getIntent().getSerializableExtra(MainActivity.HIGH_SCORE_DATA);
final String aboutText = getResources().getString(R.string.high_score_display, currentHighScore.toString());
final TextView textView = findViewById(R.id.textViewHighScore);
textView.setText(Html.fromHtml(aboutText));
}
}
8 changes: 6 additions & 2 deletions app/src/main/java/info/hebbeker/david/memorex/Game.java
Original file line number Diff line number Diff line change
Expand Up @@ -68,12 +68,16 @@ private void nextLevel()
gameBoardInterface.queueDisplaySymbolSequence(symbolSequence);
}

void putPlayerInput(final Symbol symbol)
void putPlayerInput(final Symbol symbol, final HighScoreContainer highScoreContainer)
{
// if input symbol is not correct, notify user and reset board game
if (symbol != currentSymbol.next())
{
gameBoardInterface.notifyUser("Game Over (" + symbolSequence.size() + ")");
// end current game
final int completedLevel = symbolSequence.size() - 1;
final Score score = new Score(completedLevel);
highScoreContainer.setNewHighScore(score);
gameBoardInterface.notifyUser("Game Over (" + completedLevel + ")");
gameBoardInterface.clearBoard();
}
// if sequence is complete, notify user and start next level
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
package info.hebbeker.david.memorex;

import android.content.SharedPreferences;

import com.google.gson.Gson;
import com.google.gson.JsonSyntaxException;

import java.io.IOException;

class HighScoreContainer
{
final private SharedPreferences sharedPref;
final private String highScorePreferenceKey = "HighScoreStorage";
final private Gson gson = new Gson();
private Score currentHighScore;

HighScoreContainer(final SharedPreferences sharedPref)
{
this.sharedPref = sharedPref;
loadHighScore();
}

private void loadHighScore()
{
try
{
String highScoreSerializedObject = this.sharedPref.getString(highScorePreferenceKey, "");
currentHighScore = gson.fromJson(highScoreSerializedObject, Score.class);
if (currentHighScore == null) // this may be overcautious
{
throw new IOException("Getting stored high score failed!");
}
}
catch (JsonSyntaxException|IOException e)
{
e.printStackTrace();
currentHighScore = new Score(0);
saveHighScore();
}
}

boolean setNewHighScore(final Score newScore)
{
final boolean isNewHighScore = newScore.isGreaterThan(currentHighScore);
if (isNewHighScore)
{
currentHighScore = newScore;
saveHighScore();
}
return isNewHighScore;
}

private void saveHighScore()
{
SharedPreferences.Editor editor = sharedPref.edit();
String highScoreSerializedObject = gson.toJson(currentHighScore);
editor.putString(highScorePreferenceKey, highScoreSerializedObject);
editor.apply();
}

public Score getCurrentHighScore()
{
return currentHighScore;
}
}
15 changes: 13 additions & 2 deletions app/src/main/java/info/hebbeker/david/memorex/MainActivity.java
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
package info.hebbeker.david.memorex;

import android.content.Context;
import android.content.Intent;
import android.os.Bundle;
import android.preference.PreferenceManager;
Expand All @@ -16,10 +17,12 @@

public class MainActivity extends AppCompatActivity implements GameBoardInterface, View.OnClickListener
{
static final String HIGH_SCORE_DATA = MainActivity.class.getPackage().getName() + "HIGH_SCORE_DATA";
private final SymbolButton[] symbols = new SymbolButton[4];
private final Game game = new Game(this, symbols);
private View startGameButton;
private View startGameButton = null;
private Toast notification = null;
private HighScoreContainer highScoreContainer = null;

@Override
protected void onCreate(final Bundle savedInstanceState)
Expand All @@ -28,6 +31,7 @@ protected void onCreate(final Bundle savedInstanceState)
setContentView(R.layout.activity_main);

startGameButton = findViewById(R.id.startButton);
highScoreContainer = new HighScoreContainer(getSharedPreferences("info.hebbeker.david.memorex.PREFERENCE_SCORE_FILE_KEY", Context.MODE_PRIVATE));

symbols[0] = findViewById(R.id.button1);
symbols[1] = findViewById(R.id.button2);
Expand Down Expand Up @@ -55,7 +59,7 @@ public void signalSymbol2Game(View view)
{
SymbolButton pressedButton = (SymbolButton) view;
pressedButton.signalSymbol(); // signal symbol to user
game.putPlayerInput(pressedButton); // signal symbol to game
game.putPlayerInput(pressedButton, highScoreContainer); // signal symbol to game
}

public void startGame(@SuppressWarnings("unused") final View view)
Expand Down Expand Up @@ -154,6 +158,13 @@ public void run()
}).start();
}

public void showHighScore(@SuppressWarnings("unused") final MenuItem menuItem)
{
Intent intent = new Intent(this, DisplayHighScore.class);
intent.putExtra(HIGH_SCORE_DATA, highScoreContainer.getCurrentHighScore());
startActivity(intent);
}

public void showAbout(@SuppressWarnings("unused") final MenuItem menuItem)
{
Intent intent = new Intent(this, DisplayAboutActivity.class);
Expand Down
37 changes: 37 additions & 0 deletions app/src/main/java/info/hebbeker/david/memorex/Score.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
package info.hebbeker.david.memorex;

import java.io.Serializable;

/**
* Does contain information about a score.
* \todo Add the following attributes: username, speed, date, points
*/
class Score implements Serializable
{
/**
* Completed level.
* <p>
* If the player fails at level 2, the completed level is 1. If he fails at level 1, the
* completed level is 0.
*/
private final int level;

Score(final int level)
{
this.level = level;
}

/**
* @return true if this score is greater than other score
*/
boolean isGreaterThan(final Score otherScore)
{
return this.level > otherScore.level;
}

@Override
public String toString()
{
return "Level=" + level;
}
}
23 changes: 23 additions & 0 deletions app/src/main/res/layout/activity_display_high_score.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
<?xml version="1.0" encoding="utf-8"?>
<android.support.constraint.ConstraintLayout 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:layout_width="match_parent"
android:layout_height="match_parent"
tools:context="info.hebbeker.david.memorex.DisplayHighScore">

<TextView
android:id="@+id/textViewHighScore"
android:layout_width="0dp"
android:layout_height="0dp"
android:layout_marginBottom="8dp"
android:layout_marginLeft="11dp"
android:layout_marginRight="11dp"
android:layout_marginTop="8dp"
android:autoLink="web|email|map"
android:text="@string/high_score_display"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toTopOf="parent" />
</android.support.constraint.ConstraintLayout>
9 changes: 9 additions & 0 deletions app/src/main/res/menu/main_menu.xml
Original file line number Diff line number Diff line change
@@ -1,11 +1,20 @@
<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:android="http://schemas.android.com/apk/res/android">

<item
android:icon="@android:drawable/ic_menu_myplaces"
android:onClick="showHighScore"
android:title="@string/show_high_score"
android:titleCondensed="high score" />
<item
android:icon="@android:drawable/ic_menu_info_details"
android:onClick="showAbout"
android:title="@string/about_this_app"
android:titleCondensed="About" />

<!-- “Settings” should be below all other items (except Help & Feedback)
https://material.io/guidelines/patterns/settings.html#settings-placement
-->
<item
android:icon="@android:drawable/ic_menu_preferences"
android:onClick="showSettings"
Expand Down
2 changes: 2 additions & 0 deletions app/src/main/res/values/strings.xml
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,8 @@
<string name="title_activity_settings">Settings</string>
<string name="preference_speed_list" translatable="false">speed_list</string>
<string name="preference_switch_sound" translatable="false">switch_preference_sound</string>
<string name="show_high_score">Show high score</string>
<string name="high_score_display">Current high score is: %1$s</string>
<string-array name="pref_speed_titles">
<item>Slow</item>
<item>Medium</item>
Expand Down
52 changes: 52 additions & 0 deletions generate-version-tag-name.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
#!/bin/bash
# This script shall print a string to stdout that can directly be used as a tag name for versioning.

echo "INFO: Call this script like this: $0 4 3 2 alpha"

# read arguments
majorOffset=$1
minorOffset=$2
patchOffset=$3
masterPostfix=$4

gitInfo=`git describe --tags --always --match "v[[:digit:]]*"`
rawBranchName=`git symbolic-ref --short HEAD`
branchName="${rawBranchName/\//-}"

# truncate leading `v`
oldVersionString=${gitInfo:1}

# separate version information
IFS=- # delimit on _
set -f # disable the glob part
oldVersionInfo=(${oldVersionString}) # invoke the split+glob operator
IFS=

commits=${oldVersionInfo[1]}
object=${oldVersionInfo[2]}

# separate version numbers
IFS=. # delimit on _
set -f # disable the glob part
oldVersionNumbers=(${oldVersionInfo[0]}) # invoke the split+glob operator
IFS=

major=$((${oldVersionNumbers[0]}+$majorOffset))
minor=$((${oldVersionNumbers[1]}+$minorOffset))
patch=$((${oldVersionNumbers[2]}+$patchOffset))

if [ "$branchName" == "master" ]; then
if [ "$masterPostfix" == "" ]; then
postfix=""
else
postfix="-$masterPostfix"
fi
else
postfix="-0.develop+$branchName.$commits.$object"
fi

version="$major.$minor.$patch$postfix"

# Tags which point to defined versions shall use the version name prefixed with a `v` as this is [common practice](https://github.com/semver/semver/issues/235#issuecomment-346477428) on GitHub.
tag="v$version"
echo ${tag}

0 comments on commit 8a351b9

Please sign in to comment.