From 7c2371766b940742f3986d7904d4c20a4127ea70 Mon Sep 17 00:00:00 2001 From: joffrey-bion Date: Wed, 3 Feb 2021 02:37:38 +0100 Subject: Add auto-game with bots only Resolves: https://github.com/joffrey-bion/seven-wonders/issues/82 --- .../server/config/WebSecurityConfig.kt | 4 +- .../server/controllers/AutoGameController.kt | 52 ++++++++++++++++++++++ .../server/controllers/LobbyController.kt | 18 ++++++-- .../luxons/sevenwonders/server/SevenWondersTest.kt | 15 +++---- 4 files changed, 76 insertions(+), 13 deletions(-) create mode 100644 sw-server/src/main/kotlin/org/luxons/sevenwonders/server/controllers/AutoGameController.kt (limited to 'sw-server/src') diff --git a/sw-server/src/main/kotlin/org/luxons/sevenwonders/server/config/WebSecurityConfig.kt b/sw-server/src/main/kotlin/org/luxons/sevenwonders/server/config/WebSecurityConfig.kt index 9557ba1a..aa080189 100644 --- a/sw-server/src/main/kotlin/org/luxons/sevenwonders/server/config/WebSecurityConfig.kt +++ b/sw-server/src/main/kotlin/org/luxons/sevenwonders/server/config/WebSecurityConfig.kt @@ -8,5 +8,7 @@ import org.springframework.security.config.annotation.web.configuration.WebSecur class WebSecurityConfig : WebSecurityConfigurerAdapter() { // this disables default authentication settings - override fun configure(httpSecurity: HttpSecurity) = Unit + override fun configure(httpSecurity: HttpSecurity) { + http.cors().and().csrf().disable() + } } diff --git a/sw-server/src/main/kotlin/org/luxons/sevenwonders/server/controllers/AutoGameController.kt b/sw-server/src/main/kotlin/org/luxons/sevenwonders/server/controllers/AutoGameController.kt new file mode 100644 index 00000000..4acdc3be --- /dev/null +++ b/sw-server/src/main/kotlin/org/luxons/sevenwonders/server/controllers/AutoGameController.kt @@ -0,0 +1,52 @@ +package org.luxons.sevenwonders.server.controllers + +import kotlinx.coroutines.withTimeout +import org.luxons.sevenwonders.bot.connectBot +import org.luxons.sevenwonders.bot.connectBots +import org.luxons.sevenwonders.client.SevenWondersClient +import org.luxons.sevenwonders.model.api.AutoGameAction +import org.luxons.sevenwonders.model.api.AutoGameResult +import org.slf4j.LoggerFactory +import org.springframework.beans.factory.annotation.Value +import org.springframework.web.bind.annotation.PostMapping +import org.springframework.web.bind.annotation.RequestBody +import org.springframework.web.bind.annotation.RestController +import java.security.Principal +import kotlin.time.ExperimentalTime +import kotlin.time.minutes + +/** + * Handles actions in the game's lobby. The lobby is the place where players gather before a game. + */ +@RestController +class AutoGameController( + @Value("\${server.port}") private val serverPort: String, +) { + @OptIn(ExperimentalTime::class) + @PostMapping("/autoGame") + suspend fun autoGame(@RequestBody action: AutoGameAction, principal: Principal): AutoGameResult { + logger.info("Starting auto-game {}", action.gameName) + val client = SevenWondersClient() + val serverUrl = "ws://localhost:$serverPort" + + val lastTurn = withTimeout(5.minutes) { + val otherBotNames = List(action.nbPlayers - 1) { "JoinerBot${it + 1}" } + val owner = client.connectBot(serverUrl, "OwnerBot", action.config) + val joiners = client.connectBots(serverUrl, otherBotNames, action.config) + + owner.createGameWithBotFriendsAndAutoPlay( + gameName = action.gameName, + otherBots = joiners, + customWonders = action.customWonders, + customSettings = action.customSettings, + ) + } + + val scoreBoard = lastTurn.scoreBoard ?: error("Last turn info doesn't have scoreboard") + return AutoGameResult(scoreBoard, lastTurn.table) + } + + companion object { + private val logger = LoggerFactory.getLogger(AutoGameController::class.java) + } +} diff --git a/sw-server/src/main/kotlin/org/luxons/sevenwonders/server/controllers/LobbyController.kt b/sw-server/src/main/kotlin/org/luxons/sevenwonders/server/controllers/LobbyController.kt index aa01a23a..557a1714 100644 --- a/sw-server/src/main/kotlin/org/luxons/sevenwonders/server/controllers/LobbyController.kt +++ b/sw-server/src/main/kotlin/org/luxons/sevenwonders/server/controllers/LobbyController.kt @@ -2,7 +2,10 @@ package org.luxons.sevenwonders.server.controllers import kotlinx.coroutines.GlobalScope import kotlinx.coroutines.launch -import org.luxons.sevenwonders.bot.SevenWondersBot +import kotlinx.coroutines.runBlocking +import kotlinx.coroutines.withTimeout +import org.luxons.sevenwonders.bot.connectBot +import org.luxons.sevenwonders.client.SevenWondersClient import org.luxons.sevenwonders.model.api.GameListEvent import org.luxons.sevenwonders.model.api.actions.AddBotAction import org.luxons.sevenwonders.model.api.actions.ReassignWondersAction @@ -22,6 +25,8 @@ import org.springframework.messaging.simp.SimpMessagingTemplate import org.springframework.stereotype.Controller import org.springframework.validation.annotation.Validated import java.security.Principal +import kotlin.time.ExperimentalTime +import kotlin.time.hours /** * Handles actions in the game's lobby. The lobby is the place where players gather before a game. @@ -144,14 +149,19 @@ class LobbyController( template.convertAndSend("/topic/games", GameListEvent.CreateOrUpdate(lobbyDto).wrap()) } + @OptIn(ExperimentalTime::class) @MessageMapping("/lobby/addBot") fun addBot(@Validated action: AddBotAction, principal: Principal) { val lobby = principal.player.ownedLobby - val bot = SevenWondersBot(action.botDisplayName) + val bot = runBlocking { + SevenWondersClient().connectBot("ws://localhost:$serverPort", action.botDisplayName, action.config) + } + logger.info("Starting bot {} in game '{}'", action.botDisplayName, lobby.name) GlobalScope.launch { - bot.play("ws://localhost:$serverPort", lobby.id) + withTimeout(6.hours) { + bot.joinAndAutoPlay(lobby.id) + } } - logger.info("Added bot {} to game '{}'", action.botDisplayName, lobby.name) } /** diff --git a/sw-server/src/test/kotlin/org/luxons/sevenwonders/server/SevenWondersTest.kt b/sw-server/src/test/kotlin/org/luxons/sevenwonders/server/SevenWondersTest.kt index 02f43fcf..7c830140 100644 --- a/sw-server/src/test/kotlin/org/luxons/sevenwonders/server/SevenWondersTest.kt +++ b/sw-server/src/test/kotlin/org/luxons/sevenwonders/server/SevenWondersTest.kt @@ -9,6 +9,7 @@ import kotlinx.coroutines.withTimeoutOrNull import org.junit.runner.RunWith import org.luxons.sevenwonders.client.SevenWondersClient import org.luxons.sevenwonders.client.SevenWondersSession +import org.luxons.sevenwonders.client.createGameAndWaitLobby import org.luxons.sevenwonders.client.joinGameAndWaitLobby import org.luxons.sevenwonders.model.Action import org.luxons.sevenwonders.model.api.GameListEvent @@ -60,7 +61,7 @@ class SevenWondersTest { val session2 = newPlayer("Player2") val gameName = "Test Game" - val lobby = ownerSession.createGameAndWaitLobby(gameName) + val lobby = ownerSession.createGameWithLegacySettingsAndWaitLobby(gameName) session1.joinGameAndWaitLobby(lobby.id) session2.joinGameAndWaitLobby(lobby.id) @@ -80,7 +81,7 @@ class SevenWondersTest { val ownerSession = newPlayer("GameOwner") val gameName = "Test Game" - val lobby = ownerSession.createGameAndWaitLobby(gameName) + val lobby = ownerSession.createGameWithLegacySettingsAndWaitLobby(gameName) assertEquals(gameName, lobby.name) disconnect(ownerSession) @@ -97,7 +98,7 @@ class SevenWondersTest { val ownerSession = newPlayer("GameOwner") val gameName = "Test Game" - val createdLobby = ownerSession.createGameAndWaitLobby(gameName) + val createdLobby = ownerSession.createGameWithLegacySettingsAndWaitLobby(gameName) val afterGameListEvent = withTimeout(500) { games.receive() } assertTrue(afterGameListEvent is GameListEvent.CreateOrUpdate) @@ -114,7 +115,7 @@ class SevenWondersTest { val session2 = newPlayer("Player2") val startEvents1 = session1.watchGameStarted() - val lobby = session1.createGameAndWaitLobby("Test Game") + val lobby = session1.createGameWithLegacySettingsAndWaitLobby("Test Game") val startEvents2 = session2.watchGameStarted() session2.joinGameAndWaitLobby(lobby.id) @@ -146,10 +147,8 @@ class SevenWondersTest { } } -private suspend fun SevenWondersSession.createGameAndWaitLobby(gameName: String): LobbyDTO { - val joinedLobbies = watchLobbyJoined() - createGame(gameName) - val lobby = joinedLobbies.first() +private suspend fun SevenWondersSession.createGameWithLegacySettingsAndWaitLobby(gameName: String): LobbyDTO { + val lobby = createGameAndWaitLobby(gameName) updateSettings(lobby.settings.copy(askForReadiness = true)) return lobby } -- cgit