mirror of
https://github.com/Fluffy-Bean/GameExpo23.git
synced 2025-05-19 01:44:51 +00:00
Add highscores server
This commit is contained in:
parent
0d28b50944
commit
b6dc53dfaa
10 changed files with 192 additions and 6 deletions
|
@ -1,8 +1,13 @@
|
||||||
# Expo Website
|
<!-- # Expo Website
|
||||||
:5000 {
|
expo.example.com {
|
||||||
reverse_proxy 127.0.0.1:5000
|
reverse_proxy 127.0.0.1:5000
|
||||||
}
|
}
|
||||||
# Highscore Server
|
# Highscore Server
|
||||||
:6000 {
|
highscore.example.com {
|
||||||
reverse_proxy 127.0.0.1:6000
|
reverse_proxy 127.0.0.1:6000
|
||||||
}
|
} -->
|
||||||
|
# Highscore Server
|
||||||
|
expo.leggy.dev:443 {
|
||||||
|
reverse_proxy localhost:5000
|
||||||
|
file_server
|
||||||
|
}
|
8
Highscore-Server/Dockerfile
Normal file
8
Highscore-Server/Dockerfile
Normal file
|
@ -0,0 +1,8 @@
|
||||||
|
# syntax=docker/dockerfile:1
|
||||||
|
FROM python:3.10
|
||||||
|
WORKDIR /app
|
||||||
|
COPY requirements.txt requirements.txt
|
||||||
|
RUN pip install -r requirements.txt
|
||||||
|
EXPOSE 5000
|
||||||
|
COPY server server
|
||||||
|
CMD ["flask", "run", "--port=5000", "--host=localhost"]
|
2
Highscore-Server/README.md
Normal file
2
Highscore-Server/README.md
Normal file
|
@ -0,0 +1,2 @@
|
||||||
|
# Highscores-Server
|
||||||
|
Server (and website) to store and display Highscores of the players who completed the game
|
5
Highscore-Server/requirements.txt
Normal file
5
Highscore-Server/requirements.txt
Normal file
|
@ -0,0 +1,5 @@
|
||||||
|
Flask
|
||||||
|
Flask-SQLAlchemy
|
||||||
|
Flask-Migrate
|
||||||
|
Flask-Caching
|
||||||
|
Flask-wtf
|
14
Highscore-Server/server/__init__.py
Normal file
14
Highscore-Server/server/__init__.py
Normal file
|
@ -0,0 +1,14 @@
|
||||||
|
from flask import Flask
|
||||||
|
from server.extensions import db, migrate, cache
|
||||||
|
from server.views import blueprint
|
||||||
|
|
||||||
|
app = Flask(__name__)
|
||||||
|
app.config.from_pyfile('config.py')
|
||||||
|
|
||||||
|
db.init_app(app)
|
||||||
|
migrate.init_app(app, db)
|
||||||
|
cache.init_app(app)
|
||||||
|
|
||||||
|
db.create_all(app=app)
|
||||||
|
|
||||||
|
app.register_blueprint(blueprint)
|
4
Highscore-Server/server/config.py
Normal file
4
Highscore-Server/server/config.py
Normal file
|
@ -0,0 +1,4 @@
|
||||||
|
SECRET_KEY = 'dev'
|
||||||
|
|
||||||
|
SQLALCHEMY_DATABASE_URI = 'sqlite:///db.sqlite'
|
||||||
|
SQLALCHEMY_TRACK_MODIFICATIONS = False
|
7
Highscore-Server/server/extensions.py
Normal file
7
Highscore-Server/server/extensions.py
Normal file
|
@ -0,0 +1,7 @@
|
||||||
|
from flask_sqlalchemy import SQLAlchemy
|
||||||
|
from flask_migrate import Migrate
|
||||||
|
from flask_caching import Cache
|
||||||
|
|
||||||
|
db = SQLAlchemy()
|
||||||
|
migrate = Migrate()
|
||||||
|
cache = Cache()
|
43
Highscore-Server/server/models.py
Normal file
43
Highscore-Server/server/models.py
Normal file
|
@ -0,0 +1,43 @@
|
||||||
|
"""
|
||||||
|
Database models for the server
|
||||||
|
"""
|
||||||
|
from server.extensions import db
|
||||||
|
|
||||||
|
|
||||||
|
class Scores(db.Model):
|
||||||
|
"""
|
||||||
|
Post table
|
||||||
|
"""
|
||||||
|
__tablename__ = "scores"
|
||||||
|
|
||||||
|
id = db.Column(db.Integer, primary_key=True)
|
||||||
|
|
||||||
|
score = db.Column(db.Integer, nullable=False)
|
||||||
|
difficulty = db.Column(db.String, nullable=False)
|
||||||
|
achievements = db.Column(db.String, nullable=False)
|
||||||
|
user_id = db.Column(db.Integer, db.ForeignKey('users.id'), nullable=False)
|
||||||
|
|
||||||
|
scored_at = db.Column(
|
||||||
|
db.DateTime,
|
||||||
|
nullable=False,
|
||||||
|
server_default=db.func.now(),
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
class Users(db.Model):
|
||||||
|
"""
|
||||||
|
User table
|
||||||
|
"""
|
||||||
|
__tablename__ = "users"
|
||||||
|
|
||||||
|
id = db.Column(db.Integer, primary_key=True)
|
||||||
|
steam_uuid = db.Column(db.String, unique=True, nullable=False)
|
||||||
|
steam_name = db.Column(db.String, nullable=False)
|
||||||
|
|
||||||
|
scores = db.relationship('Scores', backref='user', lazy=True)
|
||||||
|
|
||||||
|
creation_data = db.Column(
|
||||||
|
db.DateTime,
|
||||||
|
nullable=False,
|
||||||
|
server_default=db.func.now(),
|
||||||
|
)
|
95
Highscore-Server/server/views.py
Normal file
95
Highscore-Server/server/views.py
Normal file
|
@ -0,0 +1,95 @@
|
||||||
|
from flask import Blueprint, jsonify, render_template_string, request, abort
|
||||||
|
from flask_wtf import FlaskForm
|
||||||
|
from wtforms import StringField, IntegerField
|
||||||
|
from wtforms.validators import DataRequired
|
||||||
|
|
||||||
|
from server.models import Scores, Users
|
||||||
|
from server.extensions import db, cache
|
||||||
|
|
||||||
|
blueprint = Blueprint('views', __name__)
|
||||||
|
|
||||||
|
|
||||||
|
class ScoreForm(FlaskForm):
|
||||||
|
playerName = StringField('Player Name', validators=[DataRequired()])
|
||||||
|
playerId = StringField('Player ID', validators=[DataRequired()])
|
||||||
|
score = IntegerField('Score', validators=[DataRequired()])
|
||||||
|
difficulty = StringField('Difficulty', validators=[DataRequired()])
|
||||||
|
achievements = StringField('Achievements', validators=[DataRequired()])
|
||||||
|
|
||||||
|
|
||||||
|
@blueprint.route('/', methods=['GET'])
|
||||||
|
@cache.cached(timeout=60)
|
||||||
|
def index():
|
||||||
|
top_scores = Scores.query.order_by(Scores.score.desc()).limit(10).all()
|
||||||
|
users = Users.query.all()
|
||||||
|
return render_template_string('''
|
||||||
|
<h1>Top Scores</h1>
|
||||||
|
<table>
|
||||||
|
<tr>
|
||||||
|
<th>Score</th>
|
||||||
|
<th>Difficulty</th>
|
||||||
|
<th>Achievements</th>
|
||||||
|
<th>Player</th>
|
||||||
|
</tr>
|
||||||
|
{% for score in top_scores %}
|
||||||
|
<tr>
|
||||||
|
<td>{{ score.score }}</td>
|
||||||
|
<td>{{ score.difficulty }}</td>
|
||||||
|
<td>{{ score.achievements }}</td>
|
||||||
|
<td>{{ score.user.steam_name }}</td>
|
||||||
|
</tr>
|
||||||
|
{% endfor %}
|
||||||
|
</table>
|
||||||
|
|
||||||
|
<h1>Players</h1>
|
||||||
|
<table>
|
||||||
|
<tr>
|
||||||
|
<th>Steam ID</th>
|
||||||
|
<th>Steam Name</th>
|
||||||
|
</tr>
|
||||||
|
{% for user in users %}
|
||||||
|
<tr>
|
||||||
|
<td>{{ user.steam_uuid }}</td>
|
||||||
|
<td>{{ user.steam_name }}</td>
|
||||||
|
</tr>
|
||||||
|
{% endfor %}
|
||||||
|
</table>
|
||||||
|
''', top_scores=top_scores, users=users)
|
||||||
|
|
||||||
|
|
||||||
|
@blueprint.route('/post', methods=['POST'])
|
||||||
|
def post():
|
||||||
|
form = ScoreForm()
|
||||||
|
|
||||||
|
if not form:
|
||||||
|
return "Invalid form", 400
|
||||||
|
if request.headers.get('Authentication') != 'Bearer 1234':
|
||||||
|
return "Invalid authentication", 401
|
||||||
|
|
||||||
|
if not isinstance(form.score.data, int):
|
||||||
|
return "Score must be an integer", 400
|
||||||
|
if form.score.data < 0:
|
||||||
|
return "Score must be greater than 0", 400
|
||||||
|
if form.difficulty.data not in ['easy', 'medium', 'hard']:
|
||||||
|
return "Invalid difficulty", 400
|
||||||
|
|
||||||
|
user = Users.query.filter_by(steam_uuid=form.playerId.data).first()
|
||||||
|
if not user:
|
||||||
|
user = Users(
|
||||||
|
steam_uuid=form.playerId.data,
|
||||||
|
steam_name=form.playerName.data,
|
||||||
|
)
|
||||||
|
db.session.add(user)
|
||||||
|
db.session.commit()
|
||||||
|
|
||||||
|
score = Scores(
|
||||||
|
score=form.score.data,
|
||||||
|
difficulty=form.difficulty.data,
|
||||||
|
achievements=form.achievements.data,
|
||||||
|
user_id=user.id,
|
||||||
|
)
|
||||||
|
db.session.add(score)
|
||||||
|
db.session.commit()
|
||||||
|
return jsonify({'message': 'Success!'})
|
||||||
|
|
||||||
|
|
|
@ -1,14 +1,17 @@
|
||||||
version: "3.8"
|
version: "3.8"
|
||||||
|
|
||||||
services:
|
services:
|
||||||
|
highscores:
|
||||||
|
build: ./Highscore-Server/
|
||||||
|
# restart: unless-stopped
|
||||||
|
ports:
|
||||||
|
- "5000:5000"
|
||||||
caddy:
|
caddy:
|
||||||
image: caddy:latest
|
image: caddy:latest
|
||||||
# restart: unless-stopped
|
# restart: unless-stopped
|
||||||
ports:
|
ports:
|
||||||
- "80:80"
|
- "80:80"
|
||||||
- "443:443"
|
- "443:443"
|
||||||
- "5000:5000"
|
|
||||||
- "6000:6000"
|
|
||||||
volumes:
|
volumes:
|
||||||
- ./Caddy/Caddyfile:/etc/caddy/Caddyfile
|
- ./Caddy/Caddyfile:/etc/caddy/Caddyfile
|
||||||
- ./Caddy/data:/data
|
- ./Caddy/data:/data
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue