3 Commits

Author SHA1 Message Date
c30529c087 Merge branch 'rename-uuid-to-id' 2023-03-31 17:21:08 +02:00
80c7c80451 uuid -> id 2023-03-31 17:20:23 +02:00
d45aca6c30 uuid -> id 2023-03-31 17:16:00 +02:00
8 changed files with 116 additions and 34 deletions

View File

@ -92,7 +92,7 @@ To activate virtual environment:
poetry shell poetry shell
``` ```
WebSockets server runs on port **8011**. To run WS Server on different port, edit `settings.py` configuration. WebSockets server runs on port **8011**. To run WS Server on different port, edit `settings.py` configuration.
## System overview ## System overview
@ -220,7 +220,7 @@ Response body:
} }
}, },
"player": { "player": {
"uuid": "75bba7cd-a4c1-4b50-b0b5-6382c2822a25", "id": "75bba7cd-a4c1-4b50-b0b5-6382c2822a25",
"name": "Pero", "name": "Pero",
"position": { "position": {
"x": 0, "x": 0,
@ -234,17 +234,17 @@ Response body:
### Player Move ### Player Move
- POST `/player/{uuid}/move/left` - POST `/player/{id}/move/left`
- POST `/player/{uuid}/move/right` - POST `/player/{id}/move/right`
- POST `/player/{uuid}/move/up` - POST `/player/{id}/move/up`
- POST `/player/{uuid}/move/down` - POST `/player/{id}/move/down`
Request body: None Request body: None
Response code: Response code:
- 200 OK: Destination reached - 200 OK: Destination reached
- 201 Created: Player moved successfully - 201 Created: Player moved successfully
- 403 Forbidden: Player uuid not valid, probably timeout - 403 Forbidden: Player id not valid, probably timeout
- 409 Conflict: Invalid move, obstacle or position out of board - 409 Conflict: Invalid move, obstacle or position out of board
- 422 Unprocessable Content: Validation error - 422 Unprocessable Content: Validation error
@ -252,7 +252,7 @@ Response body:
```json ```json
{ {
"player": { "player": {
"uuid": "string", "id": "string",
"name": "Pero", "name": "Pero",
"position": { "position": {
"x": 50, "x": 50,
@ -266,7 +266,7 @@ Response body:
### Get Player Info ### Get Player Info
GET `/player/{{uuid}}` GET `/player/{{id}}`
Request body: None Request body: None
@ -274,7 +274,7 @@ Response body:
```json ```json
{ {
"player": { "player": {
"uuid": "string", "id": "string",
"name": "Pero", "name": "Pero",
"position": { "position": {
"x": 50, "x": 50,
@ -334,7 +334,7 @@ Data:
}, },
"players": [ "players": [
{ {
"uuid": "test-player-id", "id": "test-player-id",
"name": "Pero", "name": "Pero",
"active": true, "active": true,
"position": { "position": {
@ -345,7 +345,7 @@ Data:
"move_attempt_count": 3 "move_attempt_count": 3
}, },
{ {
"uuid": "95962b49-0003-4bf2-b205-71f2590f2318", "id": "95962b49-0003-4bf2-b205-71f2590f2318",
"name": "Mirko", "name": "Mirko",
"active": true, "active": true,
"position": { "position": {

View File

@ -39,7 +39,7 @@ POST http://localhost:8010/player/test-player-pero/product/purchase
Content-Type: application/json Content-Type: application/json
{ {
"product_uuid": "cocacola-id" "product_id": "cocacola-id"
} }
### ###

View File

@ -27,7 +27,7 @@ class PositionDto(BaseModel):
class PlayerDto(BaseModel): class PlayerDto(BaseModel):
uuid: str id: str
name: str name: str
active: bool active: bool
position: PositionDto position: PositionDto
@ -42,7 +42,7 @@ class DestinationDto(BaseModel):
class ProductDto(BaseModel): class ProductDto(BaseModel):
name: str name: str
uuid: str id: str
description: Optional[str] = None description: Optional[str] = None
class StartGameRequestDto(BaseModel): class StartGameRequestDto(BaseModel):
@ -75,4 +75,4 @@ class GetProductsResponse(BaseModel):
class PurchaseProductDto(BaseModel): class PurchaseProductDto(BaseModel):
product_uuid: str product_id: str

View File

@ -24,8 +24,8 @@ from settings import settings
router = APIRouter() router = APIRouter()
def get_player(uuid: str, engine: GameEngine = Depends(get_game_engine)) -> Player: def get_player(id: str, engine: GameEngine = Depends(get_game_engine)) -> Player:
player = engine.players.find(uuid) player = engine.players.find(id)
if player is None: if player is None:
raise HTTPException( raise HTTPException(
status_code=status.HTTP_404_NOT_FOUND, detail="Player not found" status_code=status.HTTP_404_NOT_FOUND, detail="Player not found"
@ -76,7 +76,7 @@ async def start_game(
@router.get( @router.get(
"/player/{uuid}", "/player/{id}",
response_model=PlayerInfoResponseDto, response_model=PlayerInfoResponseDto,
responses={ responses={
status.HTTP_403_FORBIDDEN: { status.HTTP_403_FORBIDDEN: {
@ -85,7 +85,7 @@ async def start_game(
}, },
status.HTTP_404_NOT_FOUND: { status.HTTP_404_NOT_FOUND: {
"model": ErrorResponseDto, "model": ErrorResponseDto,
"description": " Player with uuid not found, probably kicked out", "description": " Player with id not found, probably kicked out",
}, },
}, },
) )
@ -96,7 +96,7 @@ async def get_player_info(
@router.post( @router.post(
"/player/{uuid}/move/{direction}", "/player/{id}/move/{direction}",
response_model=MovePlayerResponseDto, response_model=MovePlayerResponseDto,
status_code=status.HTTP_201_CREATED, status_code=status.HTTP_201_CREATED,
responses={ responses={
@ -110,7 +110,7 @@ async def get_player_info(
}, },
status.HTTP_404_NOT_FOUND: { status.HTTP_404_NOT_FOUND: {
"model": ErrorResponseDto, "model": ErrorResponseDto,
"description": " Player with uuid not found, probably kicked out", "description": " Player with id not found, probably kicked out",
}, },
status.HTTP_409_CONFLICT: { status.HTTP_409_CONFLICT: {
"model": ErrorResponseDto, "model": ErrorResponseDto,
@ -157,24 +157,24 @@ async def get_products() -> GetProductsResponse:
) )
@router.get("/products/{uuid}", response_model=ProductDto) @router.get("/products/{id}", response_model=ProductDto)
async def get_product(uuid: str) -> ProductDto: async def get_product(id: str) -> ProductDto:
for product in settings.products: for product in settings.products:
if product.uuid == uuid: if product.id == id:
return ProductDto.from_orm(product) return ProductDto.from_orm(product)
raise HTTPException( raise HTTPException(
status_code=status.HTTP_404_NOT_FOUND, detail="Product not found" status_code=status.HTTP_404_NOT_FOUND, detail="Product not found"
) )
@router.post("/player/{uuid}/product/purchase") @router.post("/player/{id}/product/purchase")
async def purchase_product( async def purchase_product(
body: PurchaseProductDto, body: PurchaseProductDto,
engine: GameEngine = Depends(get_game_engine), engine: GameEngine = Depends(get_game_engine),
player: Player = Depends(get_player), player: Player = Depends(get_player),
): ):
for product in settings.products: for product in settings.products:
if product.uuid == body.product_uuid: if product.id == body.product_id:
try: try:
await engine.purchase_product(player=player, product=product) await engine.purchase_product(player=player, product=product)
except PurchaseForbiddenForPlayer: except PurchaseForbiddenForPlayer:

View File

@ -15,7 +15,7 @@ class Position:
@dataclass @dataclass
class Player: class Player:
name: str name: str
uuid: str = field(default_factory=lambda: str(uuid.uuid4())) id: str = field(default_factory=lambda: str(uuid.uuid4()))
position: Position = field(default_factory=lambda: Position(0, 0)) position: Position = field(default_factory=lambda: Position(0, 0))
move_count: int = 0 move_count: int = 0
move_attempt_count: int = 0 move_attempt_count: int = 0
@ -31,8 +31,8 @@ class Player:
class PlayerList(list[Player]): class PlayerList(list[Player]):
def find(self, uuid: str) -> Optional[Player]: def find(self, id: str) -> Optional[Player]:
for player in self: for player in self:
if player.uuid == uuid: if player.id == id:
return player return player
return None return None

View File

@ -6,5 +6,5 @@ from typing import Optional
@dataclass @dataclass
class Product: class Product:
name: str name: str
uuid: str = field(default_factory=lambda: str(uuid.uuid4())) id: str = field(default_factory=lambda: str(uuid.uuid4()))
description: Optional[str] = None description: Optional[str] = None

51
sdk/demo.py Normal file
View File

@ -0,0 +1,51 @@
import random
from fh_sdk import Direction, FairHopper, Position
import math
HOST = "http://localhost"
PORT = 8010
def calc_angle(position1: Position, position2: Position) -> float:
x1, y1 = position1.x, position1.y
x2, y2 = position2.x, position2.y
return math.atan2(y2 - y1, x2 - x1) * (180 / math.pi)
fh = FairHopper(host=HOST, port=PORT)
res = fh.ping()
game = fh.start_game(player_name=f"Mirko {random.randint(0, 9999)}")
print(game.player.position)
quit()
res = fh.get_game_info()
print(">>>>>", res)
res = fh.get_player_info("XX")
print(">>>>>", res)
position = game.player.position
dest_position = game.destination.position
# p1 = PositionDto(x=0, y=20)
# p2 = PositionDto(x=10, y=10)
# angle = calc_angle(p1, p2)
# print(angle)
# quit()
for _ in range(10):
angle = calc_angle(position, dest_position) + 180
if 0 <= angle < 90:
direction = Direction.RIGHT
elif 90 <= angle <= 180:
direction = Direction.DOWN
elif 180 <= angle <= 270:
direction = Direction.RIGHT
else:
direction = Direction.UP
print(position, dest_position, int(angle), direction)
move_response = fh.move(game.player.id, direction)
position = move_response.player.position

View File

@ -2,18 +2,49 @@ import logging
from hopper.models.config import ( from hopper.models.config import (
BoardSettings, BoardSettings,
DebugSettings,
GameSettings, GameSettings,
InactivityWatchdogSettings, InactivityWatchdogSettings,
Settings, Settings,
WSServerSettings, WSServerSettings,
) )
from hopper.models.player import Player, Position
from hopper.models.product import Product
settings = Settings( settings = Settings(
game=GameSettings(), game=GameSettings(),
board=BoardSettings(), board=BoardSettings(
WIDTH=20,
HEIGHT=20,
OBSTACLE_COUNT=10,
),
inacivity_watchdog=InactivityWatchdogSettings(), inacivity_watchdog=InactivityWatchdogSettings(),
purchase_timeout=5,
log_level=logging.INFO, log_level=logging.INFO,
products=[
Product(name="CocaCola", id="cocacola-id"),
Product(name="Pepsi", id="pepsi-id"),
Product(name="Fanta", id="fanta-id"),
Product(name="Snickers", id="snickers-id"),
Product(name="Mars", id="mars-id"),
Product(name="Burek", id="burek-id"),
],
ws_server=WSServerSettings(), ws_server=WSServerSettings(),
purchase_timeout=10, debug=DebugSettings(
debug=None, PRINT_BOARD=True,
PLAYERS=[
Player(
name="Pero",
id="test-player-pero",
position=Position(x=9, y=10),
can_be_deactivated=False,
),
Player(
name="Mirko",
id="test-player-mirko",
position=Position(x=10, y=5),
can_be_deactivated=False,
),
],
),
) )