diff --git a/src/main/java/org/example/Main.java b/src/main/java/org/example/Main.java index fee6cf5..623d8ad 100644 --- a/src/main/java/org/example/Main.java +++ b/src/main/java/org/example/Main.java @@ -2,11 +2,14 @@ import org.example.models.*; +import org.example.services.*; public class Main { public static void main(String[] args) { - PlayerStatus player = new PlayerStatus(); + + IServices service = new Services(); + PlayerStatus player = new PlayerStatus(service); player.initPlayer("Jane Doe"); } } \ No newline at end of file diff --git a/src/main/java/org/example/models/PlayerStatus.java b/src/main/java/org/example/models/PlayerStatus.java index c8cb33f..9e47ee5 100644 --- a/src/main/java/org/example/models/PlayerStatus.java +++ b/src/main/java/org/example/models/PlayerStatus.java @@ -3,25 +3,27 @@ import org.example.enums.*; import org.example.services.*; -import static org.example.enums.Weapons.*; -import static org.example.services.Services.*; - public class PlayerStatus { private static final String GAME_NAME = "UNREAL"; + private final IServices service; private String nickname; - private int score; - private int lives; - private int health = 100; + private int score = 0; + private int lives = 3; + private int health; private WeaponModel weaponInHand; private double positionX; private double positionY; - public boolean shouldAttackOpponent(PlayerStatus opponent) { - if (opponent.getWeaponInHand() == weaponInHand) { - return winProbability(opponent, health, score); + public PlayerStatus(IServices service) { + this.service = service; + } + + public boolean shouldAttackOpponent(PlayerStatus opponent, PlayerStatus self) { + if (opponent.getWeaponInHand() == self.getWeaponInHand()) { + return service.myWinProbability(opponent, self); } else { - var distance = getDistance(opponent, positionX, positionY); - return winDuel(opponent, distance, weaponInHand); + var distance = service.getDistance(opponent, self); + return service.opponentWins(opponent, distance, weaponInHand); } } @@ -29,11 +31,14 @@ public WeaponModel getWeaponInHand() { return weaponInHand; } - public void setWeaponInHand(WeaponModel weapon, Weapons weaponType) { - weaponInHand = new WeaponModel(FIST); - if (!canBuyWeapon(weapon, score)) { - weaponInHand.setName(weaponType); + public boolean setWeaponInHand(WeaponModel weapon) { + weaponInHand = new WeaponModel(Weapons.FIST); + if (service.canBuyWeapon(weapon, score)) { + weaponInHand = weapon; + this.score -= weapon.getCost(); + return true; } + return false; } public String getGameName() { @@ -64,20 +69,24 @@ public int getScore() { } public void setScore(int score) { - this.score = Services.updateScoreService(weaponInHand, score); + this.score = score; } public int getLives() { return lives; } + public void setLives(int lives) { + this.lives += lives; + } + public int getHealth() { return health; } public void setHealth(int health) { - this.health -= health; - if (this.health < 0) { + this.health += health; + if (this.health <= 0) { lives--; this.health = 100; } @@ -90,27 +99,38 @@ public double getPositionX() { return positionX; } - public void movePlayer(double newPosX, double newPosY) { - positionX += newPosX; - positionY += newPosY; + public void setPositionX(double posX) { + positionX = posX; } public double getPositionY() { return positionY; } + public void setPositionY(double positionY) { + this.positionY = positionY; + } + + public void movePlayer(double newPosX, double newPosY) { + positionX += newPosX; + positionY += newPosY; + } + public void findArtifactCode(int artifactCode) { - if (isPerfectNumber(artifactCode)) { - score += 5000; - lives++; - health = 100; - } else if (isPrime(artifactCode)) { - score += 1000; - lives += 2; - health += 25; - } else if (isTrap(artifactCode)) { - score -= 3000; - health -= 25; + if (service.isPerfectNumber(artifactCode)) { + setScore(5000); + setLives(1); + setHealth(100); + } else if (service.isPrime(artifactCode)) { + setScore(1000); + setLives(2); + setHealth(25); + } else if (service.isTrap(artifactCode)) { + setScore(-3000); + if (score < 0) { + setScore(0); + } + setHealth(-25); } else { score += artifactCode; } diff --git a/src/main/java/org/example/models/WeaponModel.java b/src/main/java/org/example/models/WeaponModel.java index c23deba..61d4439 100644 --- a/src/main/java/org/example/models/WeaponModel.java +++ b/src/main/java/org/example/models/WeaponModel.java @@ -3,17 +3,17 @@ import org.example.enums.*; public class WeaponModel { - private String name; + private Weapons weaponName; private int cost; private int combatValue; public WeaponModel(Weapons weapon) { - this.name = weapon.toString(); - setCostAndValue(weapon); + this.weaponName = weapon; + setCostAndValue(); } - private void setCostAndValue(Weapons name) { - switch (name) { + private void setCostAndValue() { + switch (weaponName) { case FIST: this.cost = 0; this.combatValue = 1; @@ -38,21 +38,29 @@ public int getCombatValue() { } public void setCombatValue(double distance) { - if (distance > 1000) { - this.combatValue = 4; + if (weaponName == Weapons.SNIPER) { + if (distance > 1000) { + combatValue = 4; + } else { + combatValue = 3; + } + } else if (weaponName == Weapons.KALASHNIKOV && distance <= 1000) { + combatValue = 4; + } else { + combatValue = 3; } - this.combatValue = 3; + } public int getCost() { return cost; } - public String getName() { - return name; + public Weapons getWeaponName() { + return weaponName; } - public void setName(Weapons weapon) { - this.name = weapon.toString(); + public void setWeaponName(Weapons weapon) { + this.weaponName = weapon; } } diff --git a/src/main/java/org/example/services/IServices.java b/src/main/java/org/example/services/IServices.java new file mode 100644 index 0000000..2b2f653 --- /dev/null +++ b/src/main/java/org/example/services/IServices.java @@ -0,0 +1,31 @@ +package org.example.services; + +import org.example.models.*; + +public interface IServices { + boolean canBuyWeapon(WeaponModel weapon, int playerScore); + + boolean isPerfectNumber(int artifactCode); + + boolean isPrime(int artifact); + + boolean isTrap(int artifact); + + default boolean isSumDivBy3(int artifact) { + int sum = 0; + int num = artifact; + + while (num != 0) { + sum += num % 10; + num /= 10; + } + + return sum % 3 == 0; + } + + boolean myWinProbability(PlayerStatus opponent, PlayerStatus self); + + double getDistance(PlayerStatus opponent, PlayerStatus self); + + boolean opponentWins(PlayerStatus opponent, double distance, WeaponModel myWeapon); +} diff --git a/src/main/java/org/example/services/Services.java b/src/main/java/org/example/services/Services.java index 0c9ff1d..f12d779 100644 --- a/src/main/java/org/example/services/Services.java +++ b/src/main/java/org/example/services/Services.java @@ -2,41 +2,38 @@ import org.example.models.*; -public class Services { +public class Services implements IServices { - private Services() { + public Services() { + //empty constructor } - public static int updateScoreService(WeaponModel weapon, int playerScore) { - return playerScore - weapon.getCost(); - } - - public static boolean canBuyWeapon(WeaponModel weapon, int playerScore) { + @Override + public boolean canBuyWeapon(WeaponModel weapon, int playerScore) { return playerScore >= weapon.getCost(); } - public static boolean isPerfectNumber(int artifactCode) { + @Override + public boolean isPerfectNumber(int artifactCode) { long sum = 0; - boolean isPerfect = false; for (int i = 1; i <= artifactCode / 2; i++) { if (artifactCode % i == 0) { sum += i; } } - if (sum == artifactCode) { - isPerfect = true; - } - return isPerfect; + + return artifactCode != 0 && sum == artifactCode; } - public static boolean isPrime(int artifact) { + @Override + public boolean isPrime(int artifact) { if (artifact <= 1) { return false; } - for (int i = 2; i < Math.sqrt(artifact); i++) { + for (int i = 2; i < artifact; i++) { if (artifact % i == 0) { return false; } @@ -44,40 +41,28 @@ public static boolean isPrime(int artifact) { return true; } - public static boolean isTrap(int artifact) { - return isSumDivBy3(artifact) && isEven(artifact); - } - - private static boolean isSumDivBy3(int artifact) { - int sum = 0; - int num = artifact; - - while (num != 0) { - sum += num % 10; - num /= 10; - } - - return sum % 3 == 0; - } - - private static boolean isEven(int artifact) { - return artifact % 2 == 0; + @Override + public boolean isTrap(int artifact) { + return isSumDivBy3(artifact) && artifact % 2 == 0; } - public static boolean winProbability(PlayerStatus opponent, int health, int score) { - var opponentWinProb = (3 * opponent.getHealth() + opponent.getScore() / 1000) / 4; - var myWinProb = (3 * health + score / 1000) / 4; + @Override + public boolean myWinProbability(PlayerStatus opponent, PlayerStatus self) { + double opponentWinProb = (3 * opponent.getHealth() + (double) opponent.getScore() / 1000) / 4; + double myWinProb = (3 * self.getHealth() + self.getScore() / (double) 1000) / 4; - return myWinProb > opponentWinProb; + return myWinProb >= opponentWinProb; } - public static double getDistance(PlayerStatus opponent, double posX, double posY) { - double ac = Math.abs(opponent.getPositionX() - posX); - double cb = Math.abs(opponent.getPositionY() - posY); + @Override + public double getDistance(PlayerStatus opponent, PlayerStatus self) { + double ac = Math.abs(opponent.getPositionX() - self.getPositionX()); + double cb = Math.abs(opponent.getPositionY() - self.getPositionY()); return Math.hypot(ac, cb); } - public static boolean winDuel(PlayerStatus opponent, double distance, WeaponModel myWeapon) { + @Override + public boolean opponentWins(PlayerStatus opponent, double distance, WeaponModel myWeapon) { opponent.getWeaponInHand().setCombatValue(distance); myWeapon.setCombatValue(distance); diff --git a/src/test/java/org/example/models/PlayerStatusTest.java b/src/test/java/org/example/models/PlayerStatusTest.java new file mode 100644 index 0000000..56a1bc6 --- /dev/null +++ b/src/test/java/org/example/models/PlayerStatusTest.java @@ -0,0 +1,114 @@ +package org.example.models; + +import org.example.enums.*; +import org.example.services.*; +import org.junit.jupiter.api.*; + +class PlayerStatusTest { + private final IServices service = new Services(); + + @Test + void shouldAttackOpponent_ShouldReturnFalseIfOppWinsSameWeapon() { + + //Given + PlayerStatus opp = new PlayerStatus(service); + PlayerStatus self = new PlayerStatus(service); + WeaponModel weapon = new WeaponModel(Weapons.SNIPER); + + //When + self.setScore(10); + self.setHealth(-50); + opp.setScore(190); + opp.setHealth(100); + opp.setWeaponInHand(weapon); + self.setWeaponInHand(weapon); + var result = self.shouldAttackOpponent(opp, self); + + //Then + Assertions.assertFalse(result); + } + + @Test + void shouldAttackOpponent_ShouldReturnTrueIfOppLoosesSameWeapon() { + + //Given + PlayerStatus opp = new PlayerStatus(service); + PlayerStatus self = new PlayerStatus(service); + WeaponModel weapon = new WeaponModel(Weapons.KALASHNIKOV); + + //When + self.setScore(290); + self.setHealth(50); + opp.setScore(190); + opp.setHealth(-50); + opp.setWeaponInHand(weapon); + self.setWeaponInHand(weapon); + var result = self.shouldAttackOpponent(opp, self); + + //Then + Assertions.assertTrue(result); + } + + @Test + void findArtifactCode_ShouldReturnPerfectNumberScore() { + + //Given + int artifact; + PlayerStatus player = new PlayerStatus(service); + + //When + artifact = 6; + player.findArtifactCode(artifact); + player.setHealth(100); + + //Then + Assertions.assertAll( + () -> Assertions.assertEquals(5000, player.getScore()), + () -> Assertions.assertEquals(4, player.getLives()), + () -> Assertions.assertEquals(100, player.getHealth()) + + ); + } + + @Test + void findArtifactCode_ShouldReturnPrimeNumberScore() { + + //Given + int artifact; + PlayerStatus player = new PlayerStatus(service); + + //When + artifact = 7; + player.findArtifactCode(artifact); + player.setHealth(100); + + //Then + Assertions.assertAll( + () -> Assertions.assertEquals(1000, player.getScore()), + () -> Assertions.assertEquals(5, player.getLives()), + () -> Assertions.assertEquals(100, player.getHealth()) + + ); + } + + @Test + void findArtifactCode_ShouldReturnTrapScore() { + + //Given + int artifact; + PlayerStatus player = new PlayerStatus(service); + + //When + artifact = 18; + player.findArtifactCode(artifact); + player.setHealth(25); + + //Then + Assertions.assertAll( + () -> Assertions.assertEquals(0, player.getScore()), + () -> Assertions.assertEquals(100, player.getHealth()), + () -> Assertions.assertEquals(2, player.getLives()) + + ); + } +} \ No newline at end of file diff --git a/src/test/java/org/example/services/ServicesTest.java b/src/test/java/org/example/services/ServicesTest.java index 86951c3..3a9ceea 100644 --- a/src/test/java/org/example/services/ServicesTest.java +++ b/src/test/java/org/example/services/ServicesTest.java @@ -3,36 +3,325 @@ import org.example.enums.*; import org.example.models.*; import org.junit.jupiter.api.*; +import org.junit.jupiter.params.*; +import org.junit.jupiter.params.provider.*; + +import java.util.stream.*; class ServicesTest { + private final IServices service = new Services(); + + public static Stream provideArgsForScoreLessThanCost() { + return Stream.of( + Arguments.of(992, Weapons.KNIFE), + Arguments.of(9999, Weapons.SNIPER), + Arguments.of(1999, Weapons.KALASHNIKOV) + ); + } + + public static Stream provideArgsForScoreEqualOrMoreThanCost() { + return Stream.of( + Arguments.of(1001, Weapons.KNIFE), + Arguments.of(10_000, Weapons.SNIPER), + Arguments.of(20_543, Weapons.KALASHNIKOV) + ); + } - @org.junit.jupiter.api.Test - void updateScoreService() { + + @ParameterizedTest + @MethodSource("provideArgsForScoreLessThanCost") + void canBuyWeaponTest_ShouldReturnFalseWhenScoreIsLessThanCost(int cost, Weapons type) { //Given - int gave = 3; - int exp = 5; + WeaponModel weapon = new WeaponModel(type); + //When + var result = service.canBuyWeapon(weapon, cost); //Then - Assertions.assertEquals(gave, exp); + Assertions.assertFalse(result); + } + @ParameterizedTest + @MethodSource("provideArgsForScoreEqualOrMoreThanCost") + void canBuyWeaponTest_ShouldReturnTrueWhenScoreIsEqualOrBiggerThanCost() { - @org.junit.jupiter.api.Test - void canBuyWeaponTest_ShouldReturnFalse() { + //Given + WeaponModel weapon = new WeaponModel(Weapons.FIST); + int score = 100_000; + + //When + var result = service.canBuyWeapon(weapon, score); + + //Then + Assertions.assertTrue(result); + + } + + @ParameterizedTest + @ValueSource(ints = {0, 6, 28, 496, 8128}) + void isPerfectNumberTest_ShouldReturnTrueWhenPerfectNumber(int number) { //Given - PlayerStatus player = new PlayerStatus(); - WeaponModel weapon = new WeaponModel(Weapons.KNIFE); //When - player.setWeaponInHand(weapon, Weapons.SNIPER); + var result = service.isPerfectNumber(number); + //Then + Assertions.assertTrue(result); + } + + @ParameterizedTest + @ValueSource(ints = {0, 3, 8, 26, 486, 8138}) + void isPerfectNumberTest_ShouldReturnFalseWhenNotPerfectNumber(int number) { + + //Given + + //When + + var result = service.isPerfectNumber(number); + + //Then + Assertions.assertFalse(result); + } + + @ParameterizedTest + @ValueSource(ints = {2, 3, 5, 7}) + void isPrime_ShouldReturnTrueWhenPrime(int nr) { + //Given + //When + var result = service.isPrime(nr); + //Then + Assertions.assertTrue(result); } + @ParameterizedTest + @ValueSource(ints = {1, 4, 9, 15}) + void isPrime_ShouldReturnFalseWhenNotPrime(int nr) { + //Given + + //When + var result = service.isPrime(nr); + + //Then + Assertions.assertFalse(result); + } + + @ParameterizedTest + @ValueSource(ints = {3574, 11, 10, 14}) + void isSumDivBy3_ShouldReturnFalseWhenSumNumbersIsNotDivBy3(int number) { + //Given + + //When + var result = service.isSumDivBy3(number); + + //Then + Assertions.assertFalse(result); + } + + @ParameterizedTest + @ValueSource(ints = {12, 18, 36, 15}) + void isSumDivBy3_ShouldReturnFalseWhenSumNumbersIsDivBy3(int number) { + //Given + + //When + var result = service.isSumDivBy3(number); + + //Then + Assertions.assertTrue(result); + } + + @ParameterizedTest + @ValueSource(ints = {12, 18, 36, 42}) + void isTrap_ShouldReturnTrueWhenNrIsSumDivBy3AndIsEven(int number) { + //Given + + //When + var result = service.isTrap(number); + + //Then + Assertions.assertTrue(result); + } + + @ParameterizedTest + @ValueSource(ints = {11, 16, 37, 44}) + void isTrap_ShouldReturnFalseWhenNrIsNotSumDivBy3OrIsEven(int number) { + //Given + + //When + var result = service.isTrap(number); + + //Then + Assertions.assertFalse(result); + } + @Test + void myWinProbability_ShouldReturnTrueIfLowerOpponent() { + //Given + PlayerStatus opp = new PlayerStatus(service); + PlayerStatus self = new PlayerStatus(service); + + //When + self.setHealth(50); + self.setScore(200); + opp.setScore(-90); + opp.setHealth(150); + + var result = service.myWinProbability(opp, self); + + //Then + Assertions.assertTrue(result); + } + + @Test + void myWinProbability_ShouldReturnFalseIfHigherOpponent() { + //Given + PlayerStatus opp = new PlayerStatus(service); + PlayerStatus self = new PlayerStatus(service); + + //When + self.setScore(90); + self.setHealth(50); + opp.setScore(190); + opp.setHealth(250); + + var result = service.myWinProbability(opp, self); + + //Then + Assertions.assertFalse(result); + } + + + @Test + void getDistanceBetweenSamePoints_ShouldReturn0() { + + //Given + PlayerStatus opp = new PlayerStatus(service); + PlayerStatus self = new PlayerStatus(service); + + //When + self.setPositionX(0); + self.setPositionY(0); + opp.setPositionX(0); + opp.setPositionY(0); + + var result = service.getDistance(opp, self); + + //then + Assertions.assertEquals(0, result, "distance is 0"); + } + + @Test + void getDistanceBetweenSamePoints_ShouldReturn5() { + + //Given + PlayerStatus opp = new PlayerStatus(service); + PlayerStatus self = new PlayerStatus(service); + + //When + self.setPositionX(1); + self.setPositionY(2); + opp.setPositionX(4); + opp.setPositionY(6); + + var result = service.getDistance(opp, self); + + //then + Assertions.assertEquals(5, result, "distance is 5"); + } + + @Test + void getDistanceBetweenSamePoints_ShouldReturn5WithNegativeValues() { + + //Given + PlayerStatus opp = new PlayerStatus(service); + PlayerStatus self = new PlayerStatus(service); + + //When + self.setPositionX(-1); + self.setPositionY(-2); + opp.setPositionX(-4); + opp.setPositionY(-6); + + var result = service.getDistance(opp, self); + + //then + Assertions.assertEquals(5, result, "distance is 5"); + } + + @Test + void opponentWins_ShouldReturnTrueWhenOpponentSniperDistanceGreaterThan1000() { + + //Given + PlayerStatus opp = new PlayerStatus(service); + PlayerStatus self = new PlayerStatus(service); + WeaponModel oppWeapon; + WeaponModel myWeapon; + double distance; + + //When + oppWeapon = new WeaponModel(Weapons.SNIPER); + myWeapon = new WeaponModel(Weapons.KALASHNIKOV); + opp.setScore(250000000); + self.setScore(50000); + opp.setWeaponInHand(oppWeapon); + self.setWeaponInHand(myWeapon); + distance = 10001; + + //Then + var result = service.opponentWins(opp, distance, myWeapon); + Assertions.assertTrue(result); + } + + @Test + void opponentWins_ShouldReturnTrueWhenOpponentKalashDistanceSmallerThan1000() { + + //Given + PlayerStatus opp = new PlayerStatus(service); + PlayerStatus self = new PlayerStatus(service); + WeaponModel oppWeapon; + WeaponModel myWeapon; + double distance; + + //When + oppWeapon = new WeaponModel(Weapons.KALASHNIKOV); + myWeapon = new WeaponModel(Weapons.SNIPER); + opp.setScore(250000000); + self.setScore(50000); + opp.setWeaponInHand(oppWeapon); + self.setWeaponInHand(myWeapon); + distance = 999; + + //Then + var result = service.opponentWins(opp, distance, myWeapon); + Assertions.assertTrue(result); + } + + @Test + void opponentWins_ShouldReturnTrueWhenOpponentKnifeVSMyKakash() { + + //Given + PlayerStatus opp = new PlayerStatus(service); + PlayerStatus self = new PlayerStatus(service); + WeaponModel oppWeapon; + WeaponModel myWeapon; + double distance; + + //When + oppWeapon = new WeaponModel(Weapons.KNIFE); + myWeapon = new WeaponModel(Weapons.KALASHNIKOV); + opp.setScore(250000000); + self.setScore(50000); + opp.setWeaponInHand(oppWeapon); + self.setWeaponInHand(myWeapon); + distance = 999; + + //Then + var result = service.opponentWins(opp, distance, myWeapon); + Assertions.assertFalse(result); + } } \ No newline at end of file