Commit 87df5cc8 authored by Florian Wolfgang Marth's avatar Florian Wolfgang Marth
Browse files

Add README.md, decrease fault tolerance

parent 700b6893
# SproutsBachelorProject
# Sprouts Bachelor Project
Git Project for my bachelor thesis about Sprouts. For any questions please refer to the readme file.
\ No newline at end of file
## The Application
The application is split in six parts. Each of those parts correspond to an android activity and is a package within the project.
### GameActivity
In the game activity, the whole game logic and game models are stored. This corresponding activity is called when you start a local or online multiplayer game.
### LandingPageActivity
In the landing page activity, there is basically no logic. The only thing the landing page activity provides is a platform where you can call other activities. In total, from there you can call the GameActivity, the MultiplayerActivity, the QuestionMarkActivity, the SettingsActivity and the ShareActivity, although the last mentioned is currently not activated. It basically acts as a navigator activity.
### MultiplayerActivity
In the multiplayer activity, you can see the logic that is necessary to start a multiplayer game. There is e.g. the logic of how a gamekey is generated and how access to the db is realized.
### QuestionMarkActivity
In the question mark activity, there is no logic. The only purpose of this activity is to give the user an overview of what the game of sprouts is all about.
### SettingsActivity
In the settings activity, you can change the width of lines, the number of nodes and the radius size of nodes.
### ShareActivity
In the share activity (currently disabled) you would have the possibility to share the application with other people.
### Resources
In the resource folder, all of the layout files are specified alongside string values and pictures that are used within the game.
## Tests
Some logic is also covered by standard JUnit tests. All of the tests can be found in the uibk.sprouts.gameActivity.Validators (test) folder. As the name indicates, only the game logic is covered by JUnit Tests.
## Install the Application
The game can be installed simply by opening the provided zip with Android Studio and build the project from there. There are no additional settings that need to be done. Android Studio also provides the possibility to show the application in an emulated mobile device.
## Further References
As this game has been developed as part of a bachelor thesis, there is a pdf describing most of the algorithms alongside design decisions. You can find the file [here](https://1drv.ms/b/s!Ati0LH3etGbBg9wm8BZs2wtTagEc1w?e=osH9Ig). If you can not open the link, feel free to send an E-Mail to the contact information provided below and I send the required information.
## Contact
This project has been developed as part of a bachelor thesis at the University of Innsbruck.
Florian Marth
E-Mail: marth.florian@gmail.com
Developed in 2021
\ No newline at end of file
......@@ -10,10 +10,10 @@ android {
defaultConfig {
applicationId "uibk.sprouts"
minSdkVersion 21
minSdkVersion 26
targetSdkVersion 30
versionCode 1
versionName "1.0"
versionCode 2
versionName '1.1'
testOptions {
unitTests.returnDefaultValues = true
......
......@@ -4,16 +4,13 @@ import static uibk.sprouts.gameActivity.Auxiliary.Auxiliary.getAllConnectionNode
import static uibk.sprouts.gameActivity.Auxiliary.Auxiliary.getFirstRegion;
import android.os.Build;
import android.util.Pair;
import androidx.annotation.RequiresApi;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import uibk.sprouts.gameActivity.Auxiliary.Auxiliary;
......@@ -24,7 +21,6 @@ import uibk.sprouts.gameActivity.Model.Line;
import uibk.sprouts.gameActivity.Model.Node;
import uibk.sprouts.gameActivity.Model.Region;
import uibk.sprouts.gameActivity.Validators.NodeInRegionValidation;
import uibk.sprouts.gameActivity.Validators.NodeRangeValidation;
import uibk.sprouts.gameActivity.Validators.PossibleCyclesCalculator;
public class CalculateRegionsHandler {
......@@ -199,17 +195,6 @@ public class CalculateRegionsHandler {
return regionSubSet;
}
private static List<Set<Node>> getInsideAndOutsideNodesPerIndex(GameState gameState,
int regionIndex,
int connectionIndex) {
List<Line> regionLines =
gameState.getGamestateRegions().get(regionIndex).getConnectionLines();
List<Line> connectionLines =
gameState.getGamestateConnections().get(connectionIndex).getConnectionLines();
return getInsideAndOutsideNodesPerLines(regionLines, connectionLines);
}
private static List<Set<Node>> getInsideAndOutsideNodesPerLines(List<Line> regionLines,
List<Line> connectionLines) {
List<Set<Node>> listlistNodes = new ArrayList<>();
......@@ -235,9 +220,9 @@ public class CalculateRegionsHandler {
return listlistNodes;
}
private static boolean calculateIfPercentageOfNodesAreInsideOrOutside(List<Line> regionLines,
List<Line> connectionLines, double percentage) {
int limit = (int) (Math.floor((connectionLines.size() + 1) * percentage / 100) + 1);
private static boolean calculateIfFourtyPercentageOfNodesAreInsideOrOutside(List<Line> regionLines,
List<Line> connectionLines) {
int limit = (int) (Math.floor((connectionLines.size() + 1) * (double) 40 / 100) + 1);
Set<Node> insideNodes = new HashSet<>();
Set<Node> outsideNodes = new HashSet<>();
......@@ -287,8 +272,8 @@ public class CalculateRegionsHandler {
continue;
}
if (!calculateIfPercentageOfNodesAreInsideOrOutside(outerRegion.getConnectionLines(),
connection.getConnectionLines(), 15)) {
if (!calculateIfFourtyPercentageOfNodesAreInsideOrOutside(outerRegion.getConnectionLines(),
connection.getConnectionLines())) {
return false;
}
}
......@@ -422,173 +407,6 @@ public class CalculateRegionsHandler {
}
return null;
}
//region Auxiliary functions for debugging
private static boolean allNodesOfConnectionWithinRegion(Connection connection,
List<Line> regionConnectionLines,
GameState gameState) {
for (Line line : connection.getConnectionLines()) {
if ((line.getStartNode().getxCoord() != connection.getStartNode().getxCoord() || line.getStartNode().getyCoord() != connection.getStartNode().getyCoord()) &&
(line.getStartNode().getxCoord() != connection.getEndNode().getxCoord() || line.getStartNode().getyCoord() != connection.getEndNode().getyCoord())) {
if (!NodeInRegionValidation.validate(line.getStartNode(), regionConnectionLines,
true) && NodeRangeValidation.validateNodeNearbyByNode(line.getStartNode(), gameState) == null) {
return false;
}
}
if ((line.getEndNode().getxCoord() != connection.getStartNode().getxCoord() || line.getEndNode().getyCoord() != connection.getStartNode().getyCoord()) &&
(line.getEndNode().getxCoord() != connection.getEndNode().getxCoord() || line.getEndNode().getyCoord() != connection.getEndNode().getyCoord())) {
if (!NodeInRegionValidation.validate(line.getEndNode(), regionConnectionLines,
true) && NodeRangeValidation.validateNodeNearbyByNode(line.getEndNode(), gameState) == null) {
return false;
}
}
}
return true;
}
private static Map<Pair<Region, Connection>, List<List<Line>>> listLinesForDebugging(Set<Pair<Region,
Connection>> myDebugMap) {
Map<Pair<Region, Connection>, List<List<Line>>> returnMap = new HashMap<>();
for (Pair<Region, Connection> entry : myDebugMap) {
List<Line> connectionLines = new ArrayList<>(entry.first.getConnectionLines());
List<Line> regionLinesToConsider = new ArrayList<>();
for (Line line : connectionLines) {
for (Line regionLine : entry.first.getConnectionLines()) {
if ( line.getStartNode().getxCoord() >= regionLine.getStartNode().getxCoord() ||
line.getStartNode().getxCoord() >= regionLine.getEndNode().getxCoord() ||
line.getEndNode().getxCoord() >= regionLine.getStartNode().getxCoord() ||
line.getEndNode().getxCoord() >= regionLine.getEndNode().getxCoord()) {
if ( (regionLine.getStartNode().getyCoord() < line.getStartNode().getyCoord() &&
regionLine.getStartNode().getyCoord() > line.getEndNode().getyCoord()) ||
(regionLine.getStartNode().getyCoord() < line.getEndNode().getyCoord() &&
regionLine.getStartNode().getyCoord() > line.getStartNode().getyCoord()) ||
(regionLine.getEndNode().getyCoord() < line.getStartNode().getyCoord() &&
regionLine.getEndNode().getyCoord() > line.getEndNode().getyCoord()) ||
(regionLine.getEndNode().getyCoord() < line.getEndNode().getyCoord() &&
regionLine.getEndNode().getyCoord() > line.getStartNode().getyCoord()) ||
(line.getStartNode().getyCoord() < regionLine.getStartNode().getyCoord() &&
line.getStartNode().getyCoord() > regionLine.getEndNode().getyCoord()) ||
(line.getStartNode().getyCoord() < regionLine.getEndNode().getyCoord() &&
line.getStartNode().getyCoord() > regionLine.getStartNode().getyCoord()) ||
(line.getEndNode().getyCoord() < regionLine.getStartNode().getyCoord() &&
line.getEndNode().getyCoord() > regionLine.getEndNode().getyCoord()) ||
(line.getEndNode().getyCoord() < regionLine.getEndNode().getyCoord() &&
line.getEndNode().getyCoord() > regionLine.getStartNode().getyCoord())
) {
regionLinesToConsider.add(line);
}
}
}
}
List<List<Line>> linelineList = new ArrayList<>();
linelineList.add(connectionLines);
linelineList.add(regionLinesToConsider);
returnMap.put(entry, linelineList);
}
return returnMap;
}
private static Set<Line> getRelatedLinesForNodesInQuestion(GameState gameState, int regionIndex,
int connectionIndex,
boolean insideNodesInQuestion) {
List<Line> connectionLines =
gameState.getGamestateRegions().get(regionIndex).getConnectionLines();
Set<Node> nodesInQuestion;
if(insideNodesInQuestion) {
nodesInQuestion =
getInsideAndOutsideNodesPerIndex(gameState, regionIndex, connectionIndex).get(0);
} else {
nodesInQuestion =
getInsideAndOutsideNodesPerIndex(gameState, regionIndex, connectionIndex).get(1);
}
Set<Line> lines = new HashSet<>();
for (Node node : nodesInQuestion) {
for (Line line : connectionLines) {
if (line.getStartNode().getxCoord() <= node.getxCoord() || line.getEndNode().getxCoord() <= node.getxCoord()) {
if ( line.getStartNode().getyCoord() <= node.getyCoord() && line.getEndNode().getyCoord() >= node.getyCoord() ||
line.getStartNode().getyCoord() >= node.getyCoord() && line.getEndNode().getyCoord() <= node.getyCoord()) {
lines.add(line);
}
}
}
}
return lines;
}
private static Set<Pair<Region, Connection>> listConnectionsThatArePartlyContainedInRegion(GameState gameState) {
Set<Pair<Region, Connection>> regionConnectionMap = new HashSet<>();
for (Region region : gameState.getGamestateRegions()) {
for (Connection connection : gameState.getGamestateConnections()) {
int flag = 2;
for (Line line : connection.getConnectionLines()) {
if (!NodeInRegionValidation.validate(line.getStartNode(),
region.getConnectionLines(),
true)) {
if (flag == 1) {
regionConnectionMap.add(new Pair<>(region, connection));
break;
}
flag = 0;
} else {
if (flag == 0){
regionConnectionMap.add(new Pair<>(region, connection));
break;
}
flag = 1;
}
if (!NodeInRegionValidation.validate(line.getEndNode(),
region.getConnectionLines(),
true)) {
if (flag == 1) {
regionConnectionMap.add(new Pair<>(region, connection));
break;
}
flag = 0;
} else {
if (flag == 0){
regionConnectionMap.add(new Pair<>(region, connection));
break;
}
flag = 1;
}
}
}
}
Set<Pair<Region, Connection>> pairsToKeep = new HashSet<>();
for (Pair<Region, Connection> pair : regionConnectionMap) {
boolean keepFlag = true;
for (Node node : getInsideAndOutsideNodesPerIndex(gameState,
gameState.getGamestateRegions().indexOf(pair.first),
gameState.getGamestateConnections().indexOf(pair.second)).get(0)) {
if ((node.getxCoord() == pair.second.getStartNode().getxCoord() &&
node.getyCoord() == pair.second.getStartNode().getyCoord()) ||
(node.getxCoord() == pair.second.getEndNode().getxCoord() &&
node.getyCoord() == pair.second.getEndNode().getyCoord())) {
keepFlag = false;
break;
}
}
if (keepFlag) {
pairsToKeep.add(pair);
}
}
return pairsToKeep;
}
//endregion
}
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment