Compare commits

..

No commits in common. "ueb10" and "main" have entirely different histories.
ueb10 ... main

7 changed files with 12 additions and 308 deletions

View File

@ -1,5 +1,2 @@
/classes/
/bin/
/out/
/lib/
/.attach_pid*

View File

@ -1,35 +0,0 @@
<component name="libraryTable">
<library name="junit.jupiter" type="repository">
<properties maven-id="org.junit.jupiter:junit-jupiter:5.9.0" />
<CLASSES>
<root url="jar://$PROJECT_DIR$/lib/junit-jupiter-5.9.0.jar!/" />
<root url="jar://$PROJECT_DIR$/lib/junit-jupiter-api-5.9.0.jar!/" />
<root url="jar://$PROJECT_DIR$/lib/opentest4j-1.2.0.jar!/" />
<root url="jar://$PROJECT_DIR$/lib/junit-platform-commons-1.9.0.jar!/" />
<root url="jar://$PROJECT_DIR$/lib/apiguardian-api-1.1.2.jar!/" />
<root url="jar://$PROJECT_DIR$/lib/junit-jupiter-params-5.9.0.jar!/" />
<root url="jar://$PROJECT_DIR$/lib/junit-jupiter-engine-5.9.0.jar!/" />
<root url="jar://$PROJECT_DIR$/lib/junit-platform-engine-1.9.0.jar!/" />
</CLASSES>
<JAVADOC>
<root url="jar://$PROJECT_DIR$/lib/junit-jupiter-5.9.0-javadoc.jar!/" />
<root url="jar://$PROJECT_DIR$/lib/junit-jupiter-api-5.9.0-javadoc.jar!/" />
<root url="jar://$PROJECT_DIR$/lib/opentest4j-1.2.0-javadoc.jar!/" />
<root url="jar://$PROJECT_DIR$/lib/junit-platform-commons-1.9.0-javadoc.jar!/" />
<root url="jar://$PROJECT_DIR$/lib/apiguardian-api-1.1.2-javadoc.jar!/" />
<root url="jar://$PROJECT_DIR$/lib/junit-jupiter-params-5.9.0-javadoc.jar!/" />
<root url="jar://$PROJECT_DIR$/lib/junit-jupiter-engine-5.9.0-javadoc.jar!/" />
<root url="jar://$PROJECT_DIR$/lib/junit-platform-engine-1.9.0-javadoc.jar!/" />
</JAVADOC>
<SOURCES>
<root url="jar://$PROJECT_DIR$/lib/junit-jupiter-5.9.0-sources.jar!/" />
<root url="jar://$PROJECT_DIR$/lib/junit-jupiter-api-5.9.0-sources.jar!/" />
<root url="jar://$PROJECT_DIR$/lib/opentest4j-1.2.0-sources.jar!/" />
<root url="jar://$PROJECT_DIR$/lib/junit-platform-commons-1.9.0-sources.jar!/" />
<root url="jar://$PROJECT_DIR$/lib/apiguardian-api-1.1.2-sources.jar!/" />
<root url="jar://$PROJECT_DIR$/lib/junit-jupiter-params-5.9.0-sources.jar!/" />
<root url="jar://$PROJECT_DIR$/lib/junit-jupiter-engine-5.9.0-sources.jar!/" />
<root url="jar://$PROJECT_DIR$/lib/junit-platform-engine-1.9.0-sources.jar!/" />
</SOURCES>
</library>
</component>

View File

@ -1,23 +0,0 @@
<component name="libraryTable">
<library name="mockito.core" type="repository">
<properties maven-id="org.mockito:mockito-core:5.12.0" />
<CLASSES>
<root url="jar://$PROJECT_DIR$/lib/mockito-core-5.12.0.jar!/" />
<root url="jar://$PROJECT_DIR$/lib/byte-buddy-1.14.15.jar!/" />
<root url="jar://$PROJECT_DIR$/lib/byte-buddy-agent-1.14.15.jar!/" />
<root url="jar://$PROJECT_DIR$/lib/objenesis-3.3.jar!/" />
</CLASSES>
<JAVADOC>
<root url="jar://$PROJECT_DIR$/lib/mockito-core-5.12.0-javadoc.jar!/" />
<root url="jar://$PROJECT_DIR$/lib/byte-buddy-1.14.15-javadoc.jar!/" />
<root url="jar://$PROJECT_DIR$/lib/byte-buddy-agent-1.14.15-javadoc.jar!/" />
<root url="jar://$PROJECT_DIR$/lib/objenesis-3.3-javadoc.jar!/" />
</JAVADOC>
<SOURCES>
<root url="jar://$PROJECT_DIR$/lib/mockito-core-5.12.0-sources.jar!/" />
<root url="jar://$PROJECT_DIR$/lib/byte-buddy-1.14.15-sources.jar!/" />
<root url="jar://$PROJECT_DIR$/lib/byte-buddy-agent-1.14.15-sources.jar!/" />
<root url="jar://$PROJECT_DIR$/lib/objenesis-3.3-sources.jar!/" />
</SOURCES>
</library>
</component>

View File

@ -5,7 +5,6 @@
<content url="file://$MODULE_DIR$">
<sourceFolder url="file://$MODULE_DIR$/src" isTestSource="false" />
<sourceFolder url="file://$MODULE_DIR$/res" type="java-resource" />
<sourceFolder url="file://$MODULE_DIR$/test" isTestSource="true" />
<excludeFolder url="file://$MODULE_DIR$/specs" />
<excludeFolder url="file://$MODULE_DIR$/tools" />
</content>
@ -20,23 +19,5 @@
<SOURCES />
</library>
</orderEntry>
<orderEntry type="module-library" scope="TEST">
<library name="JUnit5.8.1">
<CLASSES>
<root url="jar://$MAVEN_REPOSITORY$/org/junit/jupiter/junit-jupiter/5.8.1/junit-jupiter-5.8.1.jar!/" />
<root url="jar://$MAVEN_REPOSITORY$/org/junit/jupiter/junit-jupiter-api/5.8.1/junit-jupiter-api-5.8.1.jar!/" />
<root url="jar://$MAVEN_REPOSITORY$/org/opentest4j/opentest4j/1.2.0/opentest4j-1.2.0.jar!/" />
<root url="jar://$MAVEN_REPOSITORY$/org/junit/platform/junit-platform-commons/1.8.1/junit-platform-commons-1.8.1.jar!/" />
<root url="jar://$MAVEN_REPOSITORY$/org/apiguardian/apiguardian-api/1.1.2/apiguardian-api-1.1.2.jar!/" />
<root url="jar://$MAVEN_REPOSITORY$/org/junit/jupiter/junit-jupiter-params/5.8.1/junit-jupiter-params-5.8.1.jar!/" />
<root url="jar://$MAVEN_REPOSITORY$/org/junit/jupiter/junit-jupiter-engine/5.8.1/junit-jupiter-engine-5.8.1.jar!/" />
<root url="jar://$MAVEN_REPOSITORY$/org/junit/platform/junit-platform-engine/1.8.1/junit-platform-engine-1.8.1.jar!/" />
</CLASSES>
<JAVADOC />
<SOURCES />
</library>
</orderEntry>
<orderEntry type="library" name="mockito.core" level="project" />
<orderEntry type="library" name="junit.jupiter" level="project" />
</component>
</module>

View File

@ -62,18 +62,26 @@ public class LevelModel extends Observable implements Runnable {
/**
* Class constructor
*
* @param levelName Level name
* @param audioLoadHelper Audio load helper
* @param mode Instance mode
*/
public LevelModel(LevelLoadHelper levelLoadHelper, AudioLoadHelper audioLoadHelper, String mode) {
public LevelModel(String levelName, AudioLoadHelper audioLoadHelper, String mode) {
this.levelName = levelName;
this.audioLoadHelper = audioLoadHelper;
this.gamePaused = false;
this.gameRunning = true;
this.mode = mode;
setLevelLoadHelper(levelLoadHelper);
this.levelLoadHelper = new LevelLoadHelper(this.levelName);
this.groundGrid = this.levelLoadHelper.getGroundGrid();
this.sizeWidth = this.levelLoadHelper.getWidthSizeValue();
this.sizeHeight = this.levelLoadHelper.getHeightSizeValue();
this.cursorModel = new CursorModel();
this.gameInformationModel = new GameInformationModel(this.levelLoadHelper.getDiamondsToCatch());
this.createLimits();
if(this.mode.equals("game")) {
@ -89,7 +97,7 @@ public class LevelModel extends Observable implements Runnable {
* @param audioLoadHelper Audio load helper
*/
public LevelModel(String levelName, AudioLoadHelper audioLoadHelper) {
this(new LevelLoadHelper(levelName), audioLoadHelper, "game");
this(levelName, audioLoadHelper, "game");
}
/**
@ -257,7 +265,6 @@ public class LevelModel extends Observable implements Runnable {
int x = (int) (Math.random() * (this.getSizeHeight() - 2));
int y = (int) (Math.random() * (this.getSizeWidth() - 2));
this.groundGrid[x + 1][y + 1] = new DoorModel();
System.out.println("placed exit at " + (x + 1) + "," + (y + 1));
}
/**
@ -518,19 +525,6 @@ public class LevelModel extends Observable implements Runnable {
return this.levelLoadHelper;
}
/**
* Set custom LevelLoadHelper and create a new GameInformationModel based on it.
*/
public void setLevelLoadHelper(LevelLoadHelper levelLoadHelper) {
this.levelLoadHelper = levelLoadHelper;
this.groundGrid = this.levelLoadHelper.getGroundGrid();
this.sizeWidth = this.levelLoadHelper.getWidthSizeValue();
this.sizeHeight = this.levelLoadHelper.getHeightSizeValue();
setGameInformationModel(new GameInformationModel(this.levelLoadHelper.getDiamondsToCatch()));
}
/**
* Gets the cursor position X value
*
@ -765,13 +759,6 @@ public class LevelModel extends Observable implements Runnable {
return this.gameInformationModel;
}
/**
* Set custom GameInformationModel
*/
public void setGameInformationModel(GameInformationModel gameInformationModel) {
this.gameInformationModel = gameInformationModel;
}
/**
* Explose the brick wall
*

View File

@ -5,7 +5,6 @@ import java.awt.*;
import java.util.Observable;
import java.util.Observer;
import fr.enssat.BoulderDash.helpers.LevelLoadHelper;
import fr.enssat.BoulderDash.helpers.LevelSelectorHelper;
import fr.enssat.BoulderDash.controllers.LevelEditorController;
import fr.enssat.BoulderDash.controllers.NavigationBetweenViewController;
@ -170,7 +169,7 @@ public class LevelEditorView extends JFrame implements Observer {
if(selectedLevelValue != null && !selectedLevelValue.isEmpty()) {
// Load existing model
pickedLevelModel = new LevelModel(new LevelLoadHelper(selectedLevelValue), this.nav.getAudioLoadHelper(), "editor");
pickedLevelModel = new LevelModel(selectedLevelValue, this.nav.getAudioLoadHelper(), "editor");
} else {
// New blank model for editor
pickedLevelModel = new LevelModel(this.nav.getAudioLoadHelper());

View File

@ -1,202 +0,0 @@
package fr.enssat.BoulderDash.models;
import fr.enssat.BoulderDash.helpers.AudioLoadHelper;
import fr.enssat.BoulderDash.helpers.LevelLoadHelper;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import java.util.Arrays;
import static org.mockito.Mockito.*;
import static org.junit.jupiter.api.Assertions.*;
public class LevelModelTest {
private LevelModel levelModel;
DisplayableElementModel[][] groundLevelModel;
LevelLoadHelper levelLoadHelper;
AudioLoadHelper audioLoadHelper;
GameInformationModel gameInformationModel;
@BeforeEach
public void setUp() {
levelLoadHelper = mock(LevelLoadHelper.class);
audioLoadHelper = mock(AudioLoadHelper.class);
gameInformationModel = mock(GameInformationModel.class);
// boundaries and 2x2 field inside
when(levelLoadHelper.getHeightSizeValue()).thenReturn(4);
when(levelLoadHelper.getWidthSizeValue()).thenReturn(4);
when(levelLoadHelper.getRockfordPositionX()).thenReturn(1);
when(levelLoadHelper.getRockfordPositionY()).thenReturn(1);
when(levelLoadHelper.getRockfordInstance()).thenReturn(new RockfordModel());
when(levelLoadHelper.getGroundGrid()).thenReturn(
new DisplayableElementModel[4][4]
);
// We add one diamond below, thus return 1.
when(levelLoadHelper.getDiamondsToCatch()).thenReturn(1);
levelModel = new LevelModel(levelLoadHelper, audioLoadHelper, "game");
// Place diamond next to Rockford
levelModel.getGroundLevelModel()[1][2] = new DiamondModel();
groundLevelModel = levelModel.getGroundLevelModel();
}
/**
* During an ongoing game, the player character is moved to an exit. The following
* behavior is expected and should be verified:
* The game ends.
* The player character is located on the field where the exit was previously located.
* No sound is played.
*/
@Test
void test1bi(){
// Place exit next to Rockford
levelModel.getGroundLevelModel()[2][2] = new DoorModel();
// Move Rockford from (1,1) to (2,2)
levelModel.setPositionOfRockford(2,2);
// Verify:
// Game ended
assertFalse(levelModel.isGameRunning());
// Rockford is located at exit/door
assertEquals(2, levelModel.getRockfordPositionX());
assertEquals(2,levelModel.getRockfordPositionY());
// The sounds are played in a different thread after an action occurred.
// This might happen after we verify the number of method calls.
// To avoid this, we sleep one second.
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
// No sound is played
verify(audioLoadHelper, never()).playSound(anyString());
}
/**
* During an ongoing game, the player character collects the last diamond. The
* following behavior is expected and should be verified:
* The score increases by 1.
* The number of remaining diamonds decreases to 0.
* Exactly one exit appears on the game field.
* The player character is located on the field where the diamond was previously located.
* The starting field of the player character becomes an empty field.
* The sound for collecting a diamond is played.
*/
@Test
void test1bii(){
int oldScore = levelModel.getGameInformationModel().getScore();
int oldRemainingDiamonds = levelModel.getGameInformationModel().getRemainingsDiamonds();
// Verify:
// 1 Remaining diamond
assertEquals(1, oldRemainingDiamonds);
// No exit.
assertEquals(0, numOfExits());
// Move Rockford from (1,1) to (1,2)
levelModel.setPositionOfRockford(1,2);
// Verify:
// Score increased by 1
assertEquals(oldScore + 1, levelModel.getGameInformationModel().getScore());
// No remaining diamonds
assertEquals(0, levelModel.getGameInformationModel().getRemainingsDiamonds());
// Verify: One exit appeared.
// Math.random -> sometimes spawned at old or new position of Rockford,
// then this assertion fails
assertEquals(1, numOfExits());
// Rockford placed at previous diamond location
assertEquals(1, levelModel.getRockfordPositionX());
assertEquals(2,levelModel.getRockfordPositionY());
// The starting field of Rockford becomes an empty field
assertInstanceOf(EmptyModel.class, groundLevelModel[1][1]);
// The sounds are played in a different thread after an action occurred.
// This might happen after we verify the number of method calls (which would make this test fail).
// To avoid this, we sleep one second.
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
// The sound for collecting a diamond is played.
verify(audioLoadHelper).playSound("coin");
}
int numOfExits(){
// We can't use
// verify(levelModel, times(1)).spawnExit();
// as spawnExit() is a private method.
// Iterate over the ground level and count DoorModel objects.
return (int) Arrays.stream(groundLevelModel)
.flatMap(Arrays::stream)
.filter(x -> x instanceof DoorModel)
.count();
}
/**
* During an ongoing game, the player character collects the last diamond again.
* However, this test case should minimize concrete state changes in the application and instead verify that the appropriate methods are called with the
* correct parameters to achieve the desired behavior. Explain and justify for
* which of the following points this is not possible. The following behavior is
* expected and should be verified:
* The increase in score is triggered.
* The decrease in the number of remaining diamonds is triggered.
* The appearance of an exit on the game field is triggered.
* The update of the player characters position is triggered.
* Replacing the player characters starting field with an empty field is triggered.
* Playing the sound for the entered field is triggered.
*/
@Test
void test1biii(){
GameInformationModel gameInformationModel = mock(GameInformationModel.class);
levelModel.setGameInformationModel(gameInformationModel);
levelModel = spy(levelModel);
// Move Rockford from (1,1) to (1,2)
levelModel.setPositionOfRockford(1,2);
// Verify:
// increase score
verify(gameInformationModel).incrementScore();
// decrease remaining diamonds
verify(gameInformationModel).decrementRemainingsDiamonds();
// exit appearance - IMPOSSIBLE
// 'spawnExit()' has private access
// We can only verify there are no remaining diamonds
verify(gameInformationModel).getRemainingsDiamonds();
// update character's position
verify(levelModel).updateRockfordPosition(anyInt(), anyInt());
// replace with empty field - IMPOSSIBLE
// We can't verify if the field at the position is being emptied,
// because this happens inside the method setPositionOfRockford using a constructor call:
// `this.groundGrid[oldX][oldY] = new EmptyModel();`
assertInstanceOf(EmptyModel.class, groundLevelModel[1][1]);
// The sounds are played in a different thread after an action occurred.
// This might happen after we verify the number of method calls (which would make this test fail).
// To avoid this, we sleep one second.
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
// The sound for collecting a diamond is played.
verify(audioLoadHelper).playSound("coin");
}
}