Skip to content

Commit

Permalink
Merge pull request #19 from georgeprice/feature/#18-new-java-server
Browse files Browse the repository at this point in the history
Feature/#18 new java server
  • Loading branch information
OhmGeek authored Oct 20, 2019
2 parents d73b7f9 + aeb9511 commit 2e105ce
Show file tree
Hide file tree
Showing 9 changed files with 315 additions and 0 deletions.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -108,6 +108,7 @@ captures/
.idea/dictionaries
.idea/libraries
.idea/caches
.idea/

# Keystore files
# Uncomment the following lines if you do not want to check your keystore files in.
Expand Down
70 changes: 70 additions & 0 deletions server/pom.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>

<groupId>com.colonelpanic.n64all</groupId>
<artifactId>server</artifactId>
<version>1.0-SNAPSHOT</version>

<properties>
<java.version>1.8</java.version>
<junit-jupiter.version>5.5.2</junit-jupiter.version>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<slf4jVersion>1.6.1</slf4jVersion>
</properties>

<dependencies>
<!-- https://mvnrepository.com/artifact/com.google.inject/guice -->
<dependency>
<groupId>com.google.inject</groupId>
<artifactId>guice</artifactId>
<version>4.2.2</version>
</dependency>
<!-- https://mvnrepository.com/artifact/com.google.guava/guava -->
<dependency>
<groupId>com.google.guava</groupId>
<artifactId>guava</artifactId>
<version>28.0-jre</version>
</dependency>
<dependency>
<groupId>org.junit.jupiter</groupId>
<artifactId>junit-jupiter-engine</artifactId>
<version>5.5.0</version>
<scope>test</scope>
</dependency>
<!-- https://mvnrepository.com/artifact/org.mockito/mockito-core -->
<dependency>
<groupId>org.mockito</groupId>
<artifactId>mockito-core</artifactId>
<version>2.10.0</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-api</artifactId>
<version>${slf4jVersion}</version>
</dependency>
</dependencies>
<build>
<plugins>
<!-- Need at least 2.22.0 to support JUnit 5 -->
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<version>3.0.0-M3</version>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.8.1</version>
<configuration>
<source>1.8</source>
<target>1.8</target>
</configuration>
</plugin>

</plugins>
</build>
</project>
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
package com.colonelpanic.n64all.server.model;

public enum ControllerProperty {
ANALOG_X(0, -80, 80),
ANALOG_Y(0, -80, 80),
A_BTN(0, 0, 1),
B_BTN(0, 0, 1),
Z_BTN(0, 0, 1),
C_UP_ARROW(0, 0, 1),
C_LEFT_ARROW(0, 0, 1),
C_RIGHT_ARROW(0, 0, 1),
C_DOWN_ARROW(0, 0, 1),
L_TRIGGER(0, 0, 1),
R_TRIGGER(0, 0, 1),
START(0, 0, 1);

private final int defaultValue;
private final int minValue;
private final int maxValue;

/**
* The definition of the schema for each player controller property. This defines
* defaults, as well as the allowed values.
*
* @param defaultValue the default value that this property is set to
* @param min the minimum value (inclusive) the property can be
* @param max the maximum value (inclusive) the property can be
*/
ControllerProperty(int defaultValue, int min, int max) {
this.defaultValue = defaultValue;
this.minValue = min;
this.maxValue = max;
}

public int getDefaultValue() {
return defaultValue;
}

public int getMinValue() {
return minValue;
}

public int getMaxValue() {
return maxValue;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
package com.colonelpanic.n64all.server.model;

import com.colonelpanic.n64all.server.service.PlayerController;
import com.google.common.collect.Maps;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.Map;

public class ControllerState implements PlayerController {
private static final Logger logger = LoggerFactory.getLogger(ControllerState.class);
private Map<ControllerProperty, Integer> properties;

public ControllerState() {
this.properties = Maps.newConcurrentMap();

for (ControllerProperty prop : ControllerProperty.values()) {
setState(prop, prop.getDefaultValue());
}
}

public void setState(ControllerProperty property, int value) {
if (isValidPropertyValue(property, value)) {
properties.put(property, value);
}
}

public int getState(ControllerProperty property) {
return properties.get(property);
}

private boolean isValidPropertyValue(ControllerProperty prop, int value) {
return prop.getMinValue() <= value && prop.getMaxValue() >= value;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
package com.colonelpanic.n64all.server.service;

import com.colonelpanic.n64all.server.model.ControllerProperty;
import com.colonelpanic.n64all.server.model.ControllerState;
import com.google.common.collect.Maps;
import com.google.inject.Singleton;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.Map;

@Singleton
public class ControllerService {
private static final Logger logger = LoggerFactory.getLogger(ControllerService.class);
private Map<Integer, PlayerController> players;

public ControllerService() {
players = Maps.newConcurrentMap();
}

public void addPlayer(int playerId) {

if(players.containsKey(playerId))
return;

// TODO use a Guice supplied Factory to get the appropriate state.
players.put(playerId, new ControllerState());
}
public void updatePlayerState(int playerId, ControllerProperty propToUpdate, int valueToSet) {
if(this.players.get(playerId) == null) {
logger.error("Player with id: {} not found.", playerId);
throw new PlayerNotFoundException();
}
this.players.get(playerId).setState(propToUpdate, valueToSet);
}

public int getPlayerState(int playerId, ControllerProperty property) {
if(this.players.get(playerId) == null) {
logger.error("Player with id: {} not found.", playerId);
throw new PlayerNotFoundException();
}
return this.players.get(playerId).getState(property);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
package com.colonelpanic.n64all.server.service;

import com.colonelpanic.n64all.server.model.ControllerProperty;

public interface PlayerController {
void setState(ControllerProperty property, int value);

int getState(ControllerProperty property);

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
package com.colonelpanic.n64all.server.service;

public class PlayerNotFoundException extends RuntimeException {
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
package com.colonelpanic.n64all.server.model;

import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;

import java.util.Random;

import static org.junit.jupiter.api.Assertions.*;

class ControllerStateTest {
private static final int NUMBER_OF_TRIALS = 15;
private ControllerState sut;

@BeforeEach
void setUp() {
sut = new ControllerState();
}

@AfterEach
void tearDown() {
}

@Test
public void shouldSetStateCorrectlyForValidValue() {
Random randGen = new Random();

for (int i = 0; i < NUMBER_OF_TRIALS; i++) {
ControllerProperty p = givenRandomControllerProperty(randGen);
int expectedValue = randGen.nextInt(p.getMaxValue() - p.getMinValue()) + p.getMinValue();

sut.setState(p, expectedValue);
assertEquals(expectedValue, sut.getState(p));
}
}

@Test
public void shouldNotSetStateForInvalidValue() {
int invalidValue = 1000;

for(ControllerProperty prop : ControllerProperty.values()) {
sut.setState(prop, invalidValue);
assertEquals(prop.getDefaultValue(), sut.getState(prop));
}
}

private ControllerProperty givenRandomControllerProperty(Random randGen) {
ControllerProperty[] props = ControllerProperty.values();
return props[randGen.nextInt(props.length)];
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
package com.colonelpanic.n64all.server.service;

import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;

import static com.colonelpanic.n64all.server.model.ControllerProperty.ANALOG_X;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertThrows;

public class ControllerServiceTest {

private ControllerService sut;

@BeforeEach
public void setUp() {
sut = new ControllerService();
}

@AfterEach
public void tearDown() {
}

@Test
public void shouldBarfIfStateUpdatedForUncreatedPlayer() {
//given
int playerId = 15;

assertThrows(PlayerNotFoundException.class,
() -> sut.updatePlayerState(playerId, ANALOG_X, 5));
}

@Test
public void shouldBarfOnGetStateForUncreatedPlayer() {
//given
int playerId = 15;

assertThrows(PlayerNotFoundException.class,
() -> sut.getPlayerState(playerId, ANALOG_X));
}

@Test
public void shouldUpdateStateForPrecreatedPlayer() {
//given
int playerId = 1;
int stateValue = 5;
sut.addPlayer(playerId);
sut.updatePlayerState(playerId, ANALOG_X, 5);

assertEquals(stateValue, sut.getPlayerState(playerId, ANALOG_X));
}

}

0 comments on commit 2e105ce

Please sign in to comment.