diff --git a/.docker/run.sh b/.docker/run.sh new file mode 100755 index 0000000..fe4bcc8 --- /dev/null +++ b/.docker/run.sh @@ -0,0 +1,11 @@ +#!/bin/sh + +PORT=${FAIRHOPPER_API_PORT=8010} + +echo "Starting FairHopper game server on port ${PORT}" + +uvicorn \ + main:app \ + --host 0.0.0.0 \ + --port ${PORT} \ + --workers=1 diff --git a/.docker/settings.py b/.docker/settings.py new file mode 100644 index 0000000..9087854 --- /dev/null +++ b/.docker/settings.py @@ -0,0 +1,40 @@ +import os +import logging + +from hopper.models.config import ( + BoardSettings, + DebugSettings, + GameSettings, + InactivityWatchdogSettings, + Settings, + WSServerSettings, +) +from hopper.models.product import Product + +settings = Settings( + game=GameSettings(), + board=BoardSettings( + WIDTH=20, + HEIGHT=20, + OBSTACLE_COUNT=0, + ), + inacivity_watchdog=InactivityWatchdogSettings(), + purchase_timeout=5, + 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( + HOST="0.0.0.0", + PORT=int(os.environ.get("FAIRHOPPER_WS_PORT", 8011)), + ), + debug=DebugSettings( + PRINT_BOARD=True, + PLAYERS=[], + ), +) diff --git a/Dockerfile b/Dockerfile new file mode 100644 index 0000000..dbd7f58 --- /dev/null +++ b/Dockerfile @@ -0,0 +1,37 @@ +FROM python:3.10.11-alpine3.17 + +# take arguments +ARG INTERNAL_API_PORT +ARG INTERNAL_WS_PORT + +RUN \ + pip install pip -U && \ + pip install poetry --no-cache-dir + +WORKDIR /app + +COPY pyproject.toml . +COPY poetry.lock . + +# create virtual environment +RUN python -m venv /venv +# set python thingies, set environment variables and activate virtual environment +ENV \ + PYTHONDONTWRITEBYTECODE=1 \ + PYTHONUNBUFFERED=1 \ + FAIRHOPPER_API_PORT=${INTERNAL_API_PORT} \ + FAIRHOPPER_WS_PORT=${INTERNAL_WS_PORT} \ + PATH="/venv/bin:$PATH" + +RUN \ + # dump python dependencies into requirements file + poetry export --without-hashes --format=requirements.txt > requirements.txt && \ + # install python libs + pip install -r requirements.txt --no-cache-dir --prefer-binary + +# copy all relevant files +COPY ./.docker/* ./ +COPY ./hopper ./hopper +COPY ./main.py . + +ENTRYPOINT [ "/app/run.sh" ] diff --git a/Makefile b/Makefile index 0ed5697..7b2fd0d 100644 --- a/Makefile +++ b/Makefile @@ -1,3 +1,11 @@ +IMAGE_NAME=fairhopper-service +CONTAINER_NAME=fairhopper-service +INTERNAL_API_PORT=8010 +INTERNAL_WS_PORT=8011 +EXTERNAL_API_PORT=8010 +EXTERNAL_WS_PORT=8011 + + run: @poetry run \ uvicorn \ @@ -20,3 +28,30 @@ create-requirements: --without-hashes \ --format=requirements.txt \ > requirements.txt + +docker-clean: + @echo "> Removing container $(CONTAINER_NAME)" + - @docker rm $(CONTAINER_NAME) + @echo "> Removing image $(CONTAINER_NAME)" + - @docker image rm $(CONTAINER_NAME) + + +docker-build: + @docker \ + build . \ + --build-arg INTERNAL_API_PORT=$(INTERNAL_API_PORT) \ + --build-arg INTERNAL_WS_PORT=$(INTERNAL_WS_PORT) \ + -t $(CONTAINER_NAME) + +docker-run: + @docker \ + run \ + --publish $(EXTERNAL_API_PORT):$(INTERNAL_API_PORT) \ + --publish $(EXTERNAL_WS_PORT):$(INTERNAL_WS_PORT) \ + --name=$(CONTAINER_NAME) \ + $(IMAGE_NAME) \ + --detach + +docker-clean-build: + make clean + make build diff --git a/frontend/js/frontend.js b/frontend/js/frontend.js index 37159dd..c9d4524 100644 --- a/frontend/js/frontend.js +++ b/frontend/js/frontend.js @@ -1,3 +1,7 @@ +if (typeof FAIRHOPPER_WS_SERVER === "undefined") { + var FAIRHOPPER_WS_SERVER = "ws://127.0.0.1:8011"; +} + const BOARD_ICONS = { PLAYER: "😀", PLAYER_ON_DESTINATION: "😎", diff --git a/hopper/models/config.py b/hopper/models/config.py index 9388c13..0af7fae 100644 --- a/hopper/models/config.py +++ b/hopper/models/config.py @@ -29,7 +29,7 @@ class InactivityWatchdogSettings: @dataclass class WSServerSettings: - HOST: str = "localhost" + HOST: str = "127.0.0.1" PORT: int = 8011 @@ -45,7 +45,7 @@ class Settings: board: BoardSettings inacivity_watchdog: InactivityWatchdogSettings ws_server: WSServerSettings - purchase_timeout: int = 10 # seconds + purchase_timeout: int = 10 # seconds log_level: int = logging.INFO products: List[Product] = None debug: Optional[DebugSettings] = None