diff --git a/Game/src/main/java/com/kepler/model/Sector.java b/Game/src/main/java/com/kepler/model/Sector.java new file mode 100644 index 0000000..4f59fc4 --- /dev/null +++ b/Game/src/main/java/com/kepler/model/Sector.java @@ -0,0 +1,13 @@ +package com.kepler.model; + +import lombok.Builder; +import lombok.Data; + + +@Data +@Builder +public class Sector { + private String title; + private Integer chance; +} + diff --git a/Game/src/main/java/com/kepler/service/Bot.java b/Game/src/main/java/com/kepler/service/Bot.java new file mode 100644 index 0000000..1a12b44 --- /dev/null +++ b/Game/src/main/java/com/kepler/service/Bot.java @@ -0,0 +1,109 @@ +package com.kepler.service; + +import java.util.ArrayList; +import java.util.List; +import com.kepler.model.Sector; +import java.io.File; +import java.io.IOException; +import java.util.Random; +import lombok.extern.slf4j.Slf4j; +import org.ini4j.Wini; +import org.springframework.stereotype.Service; + + +@Slf4j +@Service +public class Bot { + + /** + * Generate array bot hits + * @return tokens + */ + public String[] makeMove() { + List botTokens = makeRandomHits( + makeBotTableChanceToHitSectors() + ); + return botTokens.toArray(String[]::new); + } + + /** + * Calculate random chance by take multiplier + * @param sector + * @return multiplier + */ + private String multiplierChance(String sector) { + if(sector.equalsIgnoreCase("полубуль") || //skip bull and half bull + sector.equalsIgnoreCase("буль")) { + return ""; + } else { + if(new Random().nextInt(15) == 0) { // 15% -> x2 + return "удвоение"; + } else if(new Random().nextInt(10) == 0) { // 10% -> x3 + return "утроение"; + } else { + return ""; // bad luck + } + } + } + + /** + * Algorithm take random chance by hit sector + * @param sectors + * @return list hits + */ + private List makeRandomHits(List sectors) { + List result = new ArrayList<>(); + for (int j = 0; j < 3; j++) { // 3 darts + int randInt = new Random().nextInt(100) + 1; // rand int 1 .. 100 + int sumChances = 0; + for (int i = 0; i < sectors.size(); i++) { + sumChances += sectors.get(i).getChance(); + if (100 - sumChances < randInt) { + result.add(multiplierChance(sectors.get(i).getTitle())); // take chance by multiplier + result.add(sectors.get(i).getTitle()); // add hitted sector + break; + } + } + } + return result; + } + + /** + * Read ini file with settings % chance for hit any sectors + * @return list chances + */ + private List makeBotTableChanceToHitSectors() { + List sectors = new ArrayList<>(); + Wini ini = null; + try { + ini = new Wini(new File("src/main/resources/sectorChance.ini")); + } catch (IOException e) { + throw new RuntimeException(e); + } + for (int i = 1; i <= 20; i++) { + int chance = ini.get("easy-bot", String.valueOf(i), int.class); + sectors.add(Sector.builder().title(String.valueOf(i)).chance(chance).build()); + } + sectors.add(Sector.builder().title("полубуль").chance(ini.get("easy-bot", "half-bull", int.class)).build()); + sectors.add(Sector.builder().title("буль").chance(ini.get("easy-bot", "bull", int.class)).build()); + + reverseSortListByChance(sectors); // need reverse sort list for found chance hit sector + return sectors; + } + + /** + * Reverse sort list chances + * @param sectors + */ + private void reverseSortListByChance(List sectors) { + sectors.sort(((o1, o2) -> { + if (o1.getChance() < o2.getChance()) { + return 1; + } else if (o1.getChance() > o2.getChance()) { + return -1; + } else { + return 0; + } + })); + } +} diff --git a/Game/src/main/resources/sectorChance.ini b/Game/src/main/resources/sectorChance.ini new file mode 100644 index 0000000..1227552 --- /dev/null +++ b/Game/src/main/resources/sectorChance.ini @@ -0,0 +1,25 @@ +# key -> sector = value -> chance + +[easy-bot] +20 = 14 +19 = 12 +18 = 11 +17 = 10 +16 = 2 +15 = 1 +14 = 2 +13 = 1 +12 = 2 +11 = 2 +10 = 1 +9 = 2 +8 = 2 +7 = 6 +6 = 1 +5 = 6 +4 = 4 +3 = 6 +2 = 4 +1 = 6 +half-bull = 3 +bull = 2 diff --git a/Game/src/test/java/com/kepler/BotTest.java b/Game/src/test/java/com/kepler/BotTest.java new file mode 100644 index 0000000..552a153 --- /dev/null +++ b/Game/src/test/java/com/kepler/BotTest.java @@ -0,0 +1,40 @@ +package com.kepler; + +import com.kepler.service.Bot; +import com.kepler.service.PointsCalculator; +import java.util.stream.Stream; +import lombok.extern.slf4j.Slf4j; +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.MethodOrderer; +import org.junit.jupiter.api.Order; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.TestMethodOrder; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.context.SpringBootTest; + + +@TestMethodOrder(MethodOrderer.OrderAnnotation.class) +@DisplayName("Test case: make bot random hits") +@Slf4j +@SpringBootTest +public class BotTest { + @Autowired + private Bot bot; + + @Autowired + private PointsCalculator pointsCalculator; + + @Test + @Order(10) + @DisplayName("makeMoveTest") + void makeMoveTest() { + String[] tokens = bot.makeMove(); + Integer botSumPoints = pointsCalculator.process(tokens); + + Stream.of(tokens).forEach(sector -> log.info("Bot hit sector: {}", String.valueOf(sector))); + log.info("Bot have sum points: {}", botSumPoints); + + Assertions.assertTrue(botSumPoints >= 0); + } +} diff --git a/pom.xml b/pom.xml index 8c589c8..2a4cfd0 100644 --- a/pom.xml +++ b/pom.xml @@ -38,6 +38,13 @@ org.springframework.boot spring-boot-starter-data-jpa + + + org.ini4j + ini4j + 0.5.4 + + com.h2database h2