Player Addition
This commit is contained in:
parent
ab3899e5c5
commit
731bce91a7
1
.gitignore
vendored
Normal file
1
.gitignore
vendored
Normal file
@ -0,0 +1 @@
|
|||||||
|
instance/
|
6
DEVELOPMENT.md
Normal file
6
DEVELOPMENT.md
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
# Run locally
|
||||||
|
|
||||||
|
In increasing complexity:
|
||||||
|
|
||||||
|
* `./basic-run.sh` - just raw-dog it
|
||||||
|
* `docker compose up --build`
|
51
Dockerfile
Normal file
51
Dockerfile
Normal file
@ -0,0 +1,51 @@
|
|||||||
|
# syntax=docker/dockerfile:1
|
||||||
|
|
||||||
|
# Comments are provided throughout this file to help you get started.
|
||||||
|
# If you need more help, visit the Dockerfile reference guide at
|
||||||
|
# https://docs.docker.com/go/dockerfile-reference/
|
||||||
|
|
||||||
|
ARG PYTHON_VERSION=3.9.6
|
||||||
|
FROM python:${PYTHON_VERSION}-slim as base
|
||||||
|
|
||||||
|
# Prevents Python from writing pyc files.
|
||||||
|
ENV PYTHONDONTWRITEBYTECODE=1
|
||||||
|
|
||||||
|
# Keeps Python from buffering stdout and stderr to avoid situations where
|
||||||
|
# the application crashes without emitting any logs due to buffering.
|
||||||
|
ENV PYTHONUNBUFFERED=1
|
||||||
|
|
||||||
|
WORKDIR /app
|
||||||
|
|
||||||
|
# Create a non-privileged user that the app will run under.
|
||||||
|
# See https://docs.docker.com/go/dockerfile-user-best-practices/
|
||||||
|
ARG UID=10001
|
||||||
|
RUN adduser \
|
||||||
|
--disabled-password \
|
||||||
|
--gecos "" \
|
||||||
|
--home "/nonexistent" \
|
||||||
|
--shell "/sbin/nologin" \
|
||||||
|
--no-create-home \
|
||||||
|
--uid "${UID}" \
|
||||||
|
appuser
|
||||||
|
|
||||||
|
# Download dependencies as a separate step to take advantage of Docker's caching.
|
||||||
|
# Leverage a cache mount to /root/.cache/pip to speed up subsequent builds.
|
||||||
|
# Leverage a bind mount to requirements.txt to avoid having to copy them into
|
||||||
|
# into this layer.
|
||||||
|
RUN --mount=type=cache,target=/root/.cache/pip \
|
||||||
|
--mount=type=bind,source=requirements.txt,target=requirements.txt \
|
||||||
|
python -m pip install -r requirements.txt
|
||||||
|
|
||||||
|
# Switch to the non-privileged user to run the application.
|
||||||
|
USER appuser
|
||||||
|
|
||||||
|
# Copy the source code into the container.
|
||||||
|
COPY . .
|
||||||
|
|
||||||
|
# Expose the port that the application listens on.
|
||||||
|
EXPOSE 5000
|
||||||
|
|
||||||
|
|
||||||
|
# Run the application. Note that this sets a hard-coded secret key, which is not secure - use proper secret generation
|
||||||
|
# and management in production!
|
||||||
|
CMD FLASK_APP=app SECRET_KEY=super-secret flask run --host=0.0.0.0
|
40
NOTES.md
Normal file
40
NOTES.md
Normal file
@ -0,0 +1,40 @@
|
|||||||
|
# Development plan
|
||||||
|
|
||||||
|
- [X] Basic Game Definition
|
||||||
|
- [X] Basic Player Definition
|
||||||
|
- [ ] Basic Deck Definition
|
||||||
|
- [ ] Basic testing
|
||||||
|
- [ ] Swagger API
|
||||||
|
- [ ] Local development tool to clear/seed database
|
||||||
|
...
|
||||||
|
- [ ] Authentication (will need to link `user` table to `player`)
|
||||||
|
...
|
||||||
|
- [ ] Helm chart including an initContainer to create the database if it doesn't exist already
|
||||||
|
|
||||||
|
|
||||||
|
# Tables
|
||||||
|
|
||||||
|
Tables:
|
||||||
|
* Decks
|
||||||
|
* Name
|
||||||
|
* Description
|
||||||
|
* Owner
|
||||||
|
* DecklistId (optional)
|
||||||
|
* Players (not the same as Users! Can model a Player who is not a User)
|
||||||
|
* Users
|
||||||
|
* Standard auth stuff
|
||||||
|
* Games
|
||||||
|
* Date
|
||||||
|
* Location
|
||||||
|
* DeckIds (array)
|
||||||
|
* WinningDeckId
|
||||||
|
* FinalTurnNum
|
||||||
|
* Notes
|
||||||
|
|
||||||
|
# Database Migrations
|
||||||
|
|
||||||
|
https://flask-sqlalchemy.palletsprojects.com/en/3.1.x/quickstart/#create-the-tables
|
||||||
|
|
||||||
|
# Authentication
|
||||||
|
|
||||||
|
https://www.digitalocean.com/community/tutorials/how-to-add-authentication-to-your-app-with-flask-login
|
32
app/__init__.py
Normal file
32
app/__init__.py
Normal file
@ -0,0 +1,32 @@
|
|||||||
|
import os
|
||||||
|
import sys
|
||||||
|
|
||||||
|
from flask import Flask
|
||||||
|
from flask_sqlalchemy import SQLAlchemy
|
||||||
|
|
||||||
|
db = SQLAlchemy()
|
||||||
|
|
||||||
|
def create_app():
|
||||||
|
app = Flask(__name__)
|
||||||
|
|
||||||
|
secret_key = os.environ.get('SECRET_KEY')
|
||||||
|
if not secret_key:
|
||||||
|
sys.stderr.write('YOU NEED TO SET AN ENV VARIABLE NAMED SECRET_KEY\n')
|
||||||
|
sys.exit(1)
|
||||||
|
app.config['SECRET_KEY'] = secret_key
|
||||||
|
|
||||||
|
# TODO - support other database types 🙃
|
||||||
|
app.config['SQLALCHEMY_DATABASE_URI'] = 'sqlite:///db.sqlite'
|
||||||
|
|
||||||
|
db.init_app(app)
|
||||||
|
|
||||||
|
from .main import main as main_blueprint
|
||||||
|
app.register_blueprint(main_blueprint)
|
||||||
|
|
||||||
|
# TODO - understand how this works, since `db.create_all()` requires that the model classes have already been
|
||||||
|
# imported in order to know what to create. Perhaps `__init__.py` just magically has the context of everything in
|
||||||
|
# its module? Good opportunity to learn more about the Python import system!
|
||||||
|
with app.app_context():
|
||||||
|
db.create_all()
|
||||||
|
|
||||||
|
return app
|
22
app/main.py
Normal file
22
app/main.py
Normal file
@ -0,0 +1,22 @@
|
|||||||
|
from flask import Blueprint, request
|
||||||
|
from . import db
|
||||||
|
from .models import Deck, Game, Player
|
||||||
|
|
||||||
|
main = Blueprint("main", __name__)
|
||||||
|
|
||||||
|
@main.route("/")
|
||||||
|
def index():
|
||||||
|
return 'Hello, World - but new!'
|
||||||
|
|
||||||
|
@main.route("/player", methods=["POST"])
|
||||||
|
def create_player():
|
||||||
|
data = request.json
|
||||||
|
player = Player(
|
||||||
|
name=data['name']
|
||||||
|
)
|
||||||
|
db.session.add(player)
|
||||||
|
db.session.commit()
|
||||||
|
return {'id': player.id}
|
||||||
|
|
||||||
|
# TODO - implement a GET method - can it be a separate method, or must it be the same annotation with an `if method==`?
|
||||||
|
# Time for testing, methinks!
|
32
app/models.py
Normal file
32
app/models.py
Normal file
@ -0,0 +1,32 @@
|
|||||||
|
from . import db
|
||||||
|
|
||||||
|
# Note that a `Player` is "someone who plays in the Pod", whereas `User` (which will be implemented later) is "a user of
|
||||||
|
# this system". While all Users will _probably_ be Players, they do not have to be - and, it is likely that several
|
||||||
|
# Players will not be Users (if they don't register to use the system).
|
||||||
|
class Player(db.Model):
|
||||||
|
id = db.Column(db.Integer, primary_key=True)
|
||||||
|
name = db.Column(db.String, nullable=False)
|
||||||
|
|
||||||
|
class Deck(db.Model):
|
||||||
|
id = db.Column(db.Integer, primary_key=True)
|
||||||
|
name = db.Column(db.String(60), nullable=False)
|
||||||
|
description = db.Column(db.String)
|
||||||
|
owner = db.Column(db.String, db.ForeignKey(Player.__table__.c.id), nullable=False, )
|
||||||
|
|
||||||
|
class Game(db.Model):
|
||||||
|
id = db.Column(db.Integer, primary_key=True)
|
||||||
|
# TODO - columns like `location`, `writeups`, etc.
|
||||||
|
|
||||||
|
# Not wild about this structure ("fill in non-null columns to indicate decks that were present"), but what can you
|
||||||
|
# do with a database that doesn't support arrays? (Postgres _does_, but I don't wanna ramp up on a whole other
|
||||||
|
# database system just for that...)
|
||||||
|
deck_1 = db.Column(db.Integer)
|
||||||
|
deck_2 = db.Column(db.Integer)
|
||||||
|
deck_3 = db.Column(db.Integer)
|
||||||
|
deck_4 = db.Column(db.Integer)
|
||||||
|
deck_5 = db.Column(db.Integer)
|
||||||
|
deck_6 = db.Column(db.Integer)
|
||||||
|
deck_7 = db.Column(db.Integer)
|
||||||
|
deck_8 = db.Column(db.Integer)
|
||||||
|
deck_9 = db.Column(db.Integer)
|
||||||
|
deck_10 = db.Column(db.Integer)
|
5
basic-run.sh
Executable file
5
basic-run.sh
Executable file
@ -0,0 +1,5 @@
|
|||||||
|
#!/usr/bin/env bash
|
||||||
|
|
||||||
|
# Idempotent
|
||||||
|
source .venv/bin/activate
|
||||||
|
FLASK_APP=app SECRET_KEY=super-secret flask run
|
49
compose.yaml
Normal file
49
compose.yaml
Normal file
@ -0,0 +1,49 @@
|
|||||||
|
# Comments are provided throughout this file to help you get started.
|
||||||
|
# If you need more help, visit the Docker compose reference guide at
|
||||||
|
# https://docs.docker.com/go/compose-spec-reference/
|
||||||
|
|
||||||
|
# Here the instructions define your application as a service called "server".
|
||||||
|
# This service is built from the Dockerfile in the current directory.
|
||||||
|
# You can add other services your application may depend on here, such as a
|
||||||
|
# database or a cache. For examples, see the Awesome Compose repository:
|
||||||
|
# https://github.com/docker/awesome-compose
|
||||||
|
services:
|
||||||
|
server:
|
||||||
|
build:
|
||||||
|
context: .
|
||||||
|
ports:
|
||||||
|
- 5000:5000
|
||||||
|
|
||||||
|
# The commented out section below is an example of how to define a PostgreSQL
|
||||||
|
# database that your application can use. `depends_on` tells Docker Compose to
|
||||||
|
# start the database before your application. The `db-data` volume persists the
|
||||||
|
# database data between container restarts. The `db-password` secret is used
|
||||||
|
# to set the database password. You must create `db/password.txt` and add
|
||||||
|
# a password of your choosing to it before running `docker compose up`.
|
||||||
|
# depends_on:
|
||||||
|
# db:
|
||||||
|
# condition: service_healthy
|
||||||
|
# db:
|
||||||
|
# image: postgres
|
||||||
|
# restart: always
|
||||||
|
# user: postgres
|
||||||
|
# secrets:
|
||||||
|
# - db-password
|
||||||
|
# volumes:
|
||||||
|
# - db-data:/var/lib/postgresql/data
|
||||||
|
# environment:
|
||||||
|
# - POSTGRES_DB=example
|
||||||
|
# - POSTGRES_PASSWORD_FILE=/run/secrets/db-password
|
||||||
|
# expose:
|
||||||
|
# - 5432
|
||||||
|
# healthcheck:
|
||||||
|
# test: [ "CMD", "pg_isready" ]
|
||||||
|
# interval: 10s
|
||||||
|
# timeout: 5s
|
||||||
|
# retries: 5
|
||||||
|
# volumes:
|
||||||
|
# db-data:
|
||||||
|
# secrets:
|
||||||
|
# db-password:
|
||||||
|
# file: db/password.txt
|
||||||
|
|
4
requirements.txt
Normal file
4
requirements.txt
Normal file
@ -0,0 +1,4 @@
|
|||||||
|
Flask
|
||||||
|
Flask-SQLAlchemy
|
||||||
|
flasgger
|
||||||
|
flask-login
|
Loading…
x
Reference in New Issue
Block a user