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