Endgame WS messages & docs

This commit is contained in:
Eden Kirin
2023-05-11 19:36:16 +02:00
parent 76ee207bce
commit d660845d30
6 changed files with 47 additions and 115 deletions

117
README.md
View File

@ -234,8 +234,8 @@ loop #lightyellow Product select countdown timer (60s)
Game ->o WS: Timer timeout Game ->o WS: Timer timeout
activate Game activate Game
activate WS #coral activate WS #coral
WS o-> Client1: Cancel selection WS o-> Client1: Selection timeout
WS o-> Client2: Cancel selection WS o-> Client2: Selection timeout
deactivate WS deactivate WS
Game -> Game: Unlock game Game -> Game: Unlock game
deactivate Game deactivate Game
@ -400,6 +400,8 @@ Response body:
### Game state structure ### Game state structure
Direction: Game server -> Clients
Message: `game_dump` Message: `game_dump`
Data: Data:
@ -503,109 +505,42 @@ Data:
} }
``` ```
### Product purchase start ### Player reached destination
Message: `product_purchase_start` Direction: Game server -> Clients
Message: `player_reached_destination`
Data: Data:
```json ```json
{ {
"player": { "player": {
"id": "test-player-pero", "id": "2e0f1a50-eaa6-4efd-b0c3-adbf7000eec2",
"name": "Pero", "name": "Joso",
"active": true, "active": true,
"position": { "position": {
"x": 10, "x": 5,
"y": 10 "y": 5
}, },
"move_count": 1, "move_count": 6,
"move_attempt_count": 1, "move_attempt_count": 6,
"state": "ON_DESTINATION"
},
"products": [
{
"name": "CocaCola",
"id": "cocacola-id",
"description": null
},
{
"name": "Pepsi",
"id": "pepsi-id",
"description": null
},
{
"name": "Fanta",
"id": "fanta-id",
"description": null
},
{
"name": "Snickers",
"id": "snickers-id",
"description": null
},
{
"name": "Mars",
"id": "mars-id",
"description": null
},
{
"name": "Burek",
"id": "burek-id",
"description": null
}
],
"timeout": 5
}
```
### Product purchase timer tick
Message: `product_purchase_timer_tick`
Data:
```json
{
"time_left": 4,
"player": {
"id": "test-player-pero",
"name": "Pero",
"active": true,
"position": {
"x": 10,
"y": 10
},
"move_count": 1,
"move_attempt_count": 1,
"state": "ON_DESTINATION" "state": "ON_DESTINATION"
} }
} }
``` ```
### Product purchase timer done ### Product selection timeout
Message: `product_purchase_done` Direction: Game server -> Clients
Data: Message: `product_selection_timeout`
```json
{
"player": {
"id": "test-player-pero",
"name": "Pero",
"active": true,
"position": {
"x": 10,
"y": 10
},
"move_count": 1,
"move_attempt_count": 1,
"state": "ON_DESTINATION"
},
"product": {
"name": "CocaCola",
"id": "cocacola-id",
"description": null
}
}
```
If product selection timeout occured, product will be null. Data: `null`
### Product selection done
Message: `product_selection_done`
Direction: Client -> Game server, Game server -> Clients
Data: `null`

View File

@ -22,9 +22,6 @@
<h1 class="mt-1 mb-2"> <h1 class="mt-1 mb-2">
FairHopper Visualisation Client FairHopper Visualisation Client
</h1> </h1>
<button type="button" class="btn btn-primary test-button">
Launch demo modal
</button>
<div id="purchase-container" class="purchase-container d-none"> <div id="purchase-container" class="purchase-container d-none">
<div class="d-flex header"> <div class="d-flex header">
<h3> <h3>
@ -68,18 +65,6 @@
</div> </div>
</div> </div>
</div> </div>
<script>
document.querySelector(".test-button").onclick = () => {
playerReachedDestination({
player: {
name: "Pero Perić",
move_count: 123,
}
});
}
</script>
</body> </body>
</html> </html>

View File

@ -104,6 +104,10 @@ function playerReachedDestination(data) {
playerOnDestinationModal.show(); playerOnDestinationModal.show();
} }
function productSelectionTimeout() {
playerOnDestinationModal.hide();
}
function productSelectionDone() { function productSelectionDone() {
playerOnDestinationModal.hide(); playerOnDestinationModal.hide();
} }
@ -127,6 +131,9 @@ function wsConnect() {
case "player_reached_destination": case "player_reached_destination":
playerReachedDestination(wsMessage.data); playerReachedDestination(wsMessage.data);
break; break;
case "product_selection_timeout":
productSelectionTimeout();
break;
case "product_selection_done": case "product_selection_done":
productSelectionDone(); productSelectionDone();
break; break;

View File

@ -185,7 +185,7 @@ class GameEngine:
logging.info("Ding ding! Product selection countdown timer timeout") logging.info("Ding ding! Product selection countdown timer timeout")
self._purchase_countdown_timer = None self._purchase_countdown_timer = None
asyncio.run( asyncio.run(
self.ws_server.send_product_selection_done_message() self.ws_server.send_product_selection_timeout_message()
) )
self.game_state = GameState.RUNNING self.game_state = GameState.RUNNING
asyncio.run(self.send_game_dump()) asyncio.run(self.send_game_dump())

View File

@ -6,13 +6,7 @@ from typing import Optional, TypeVar
from pydantic import Field from pydantic import Field
from pydantic.generics import GenericModel from pydantic.generics import GenericModel
from hopper.api.dto import ( from hopper.api.dto import BaseModel, BoardDto, DestinationDto, PlayerDto, PositionDto
BaseModel,
BoardDto,
DestinationDto,
PlayerDto,
PositionDto,
)
from hopper.enums import ObjectType from hopper.enums import ObjectType
@ -65,6 +59,10 @@ class WSProductSelectionDoneMessage(WSMessage):
message: str = "product_selection_done" message: str = "product_selection_done"
class WSProductSelectionTimeoutMessage(WSMessage):
message: str = "product_selection_timeout"
class WSPlayerReachedDestinationMessage(WSMessage): class WSPlayerReachedDestinationMessage(WSMessage):
message: str = "player_reached_destination" message: str = "player_reached_destination"
data: PlayerReachedDestinationDto data: PlayerReachedDestinationDto

View File

@ -15,6 +15,7 @@ from hopper.models.ws_dto import (
WSMessage, WSMessage,
WSPlayerReachedDestinationMessage, WSPlayerReachedDestinationMessage,
WSProductSelectionDoneMessage, WSProductSelectionDoneMessage,
WSProductSelectionTimeoutMessage,
) )
@ -63,7 +64,9 @@ class WSServer(Thread):
try: try:
# we're expecting nothing from client, but read if client sends a message # we're expecting nothing from client, but read if client sends a message
rcv_data = await websocket.recv() rcv_data = await websocket.recv()
await self.handle_rcv_message(client=websocket, raw_message=rcv_data) await self.handle_rcv_message(
client=websocket, raw_message=rcv_data
)
except ConnectionClosedOK: except ConnectionClosedOK:
logging.info(f"Connection closed OK for client: {websocket.id}") logging.info(f"Connection closed OK for client: {websocket.id}")
connected = False connected = False
@ -126,6 +129,10 @@ class WSServer(Thread):
message = WSProductSelectionDoneMessage() message = WSProductSelectionDoneMessage()
await self.send_message_to_clients(message) await self.send_message_to_clients(message)
async def send_product_selection_timeout_message(self) -> None:
message = WSProductSelectionTimeoutMessage()
await self.send_message_to_clients(message)
async def run_async(self) -> None: async def run_async(self) -> None:
logging.info( logging.info(
f"Starting FairHopper Websockets Server on {self.host}:{self.port}" f"Starting FairHopper Websockets Server on {self.host}:{self.port}"