Tested the http part and added a simple little UI.
This commit is contained in:
parent
a7ff4f2a3d
commit
1a2dae816a
44
src/app.py
44
src/app.py
@ -1,4 +1,5 @@
|
||||
from flask import Flask, render_template, request, redirect, url_for, flash, session, jsonify
|
||||
|
||||
from uuid import uuid4
|
||||
from flask_socketio import SocketIO
|
||||
import json
|
||||
@ -7,6 +8,8 @@ app = Flask(__name__)
|
||||
app.config['SECRET_KEY'] = 'DEV'
|
||||
socketio = SocketIO(app)
|
||||
|
||||
NAME_LENGTH = 50
|
||||
MAX_PLAYERS = 100
|
||||
|
||||
def find_game_by_id(id:str) -> dict:
|
||||
games = []
|
||||
@ -24,13 +27,17 @@ def start_game(game:dict):
|
||||
pass
|
||||
|
||||
|
||||
@app.route('/')
|
||||
def index():
|
||||
return "Empty for now"
|
||||
|
||||
@app.route('/new/<string:name>/<int:players>', methods=['POST'])
|
||||
def new_game(name, players):
|
||||
# Log new game into json file and return a websocket url for the game
|
||||
if len(name) > NAME_LENGTH:
|
||||
return {"error": f"Game name too long (max {NAME_LENGTH} characters)"}
|
||||
|
||||
# Check if too many players
|
||||
if players > MAX_PLAYERS:
|
||||
return {"error": f"Too many players (max {MAX_PLAYERS}))"}
|
||||
|
||||
|
||||
games = []
|
||||
with open('games.json', 'r') as f:
|
||||
games = json.load(f)
|
||||
@ -44,6 +51,7 @@ def new_game(name, players):
|
||||
"join": None,
|
||||
"id": f"{uuid4().hex}",
|
||||
"status": "waiting",
|
||||
"private":False if request.args.get('private') is None else request.args.get('private'),
|
||||
}
|
||||
games.append(game)
|
||||
|
||||
@ -53,6 +61,26 @@ def new_game(name, players):
|
||||
return jsonify(game)
|
||||
|
||||
|
||||
@app.route('/games/')
|
||||
def list_games(internal=False):
|
||||
# List all public games
|
||||
games = []
|
||||
with open('games.json', 'r') as f:
|
||||
games = json.load(f)
|
||||
games = [game for game in games if not game['private']]
|
||||
|
||||
if internal:
|
||||
return games
|
||||
return jsonify(games)
|
||||
|
||||
@app.route('/games/<string:game_id>')
|
||||
def get_game(game_id):
|
||||
# Get game by id
|
||||
game = find_game_by_id(game_id)
|
||||
if "error" in game:
|
||||
return game["error"]
|
||||
return jsonify(game['game'])
|
||||
|
||||
@app.route('/join/<uuid:game_id>', methods=['POST'])
|
||||
def join_game(game_id):
|
||||
|
||||
@ -60,7 +88,7 @@ def join_game(game_id):
|
||||
# Check if game exists
|
||||
game = find_game_by_id(game_id)
|
||||
if "error" in game:
|
||||
return {"error": "Game not found"}
|
||||
return game["error"]
|
||||
|
||||
# Check if game is full
|
||||
game, idx = game['game'], game['idx']
|
||||
@ -83,6 +111,12 @@ def join_game(game_id):
|
||||
with open('games.json', 'w') as f:
|
||||
json.dump(games, f)
|
||||
|
||||
|
||||
@app.route('/')
|
||||
def index():
|
||||
# List games
|
||||
return render_template('index.html', games=list_games(internal=True))
|
||||
|
||||
if __name__ == '__main__':
|
||||
socketio.run(app, debug=True)
|
||||
|
||||
|
157
src/games.json
157
src/games.json
@ -1 +1,156 @@
|
||||
[]
|
||||
[
|
||||
{
|
||||
"game": "lol",
|
||||
"players": 12434,
|
||||
"in": [
|
||||
"127.0.0.1"
|
||||
],
|
||||
"join": null,
|
||||
"id": "a856d3347eef47cab21f5af12418c74d",
|
||||
"status": "waiting",
|
||||
"private": false
|
||||
},
|
||||
{
|
||||
"game": "pwdlnrvb",
|
||||
"players": 7,
|
||||
"in": [
|
||||
"127.0.0.1"
|
||||
],
|
||||
"join": null,
|
||||
"id": "30423073350446919e45aa3a1fb74f07",
|
||||
"status": "waiting",
|
||||
"private": "1"
|
||||
},
|
||||
{
|
||||
"game": "alxlcxskxjcqtxxxabgsitygyktusmscoqlwzrkeoalodzemipadwmbbgrcuqgivpsmbtadhhaiyqmuafayxyoaactmmub",
|
||||
"players": 84,
|
||||
"in": [
|
||||
"127.0.0.1"
|
||||
],
|
||||
"join": null,
|
||||
"id": "2bef5585c8474f9aa84b84b262f70bf3",
|
||||
"status": "waiting",
|
||||
"private": "0"
|
||||
},
|
||||
{
|
||||
"game": "zgdmxjsmytlnllemougmgwylthkjswxkgjodihtzkx",
|
||||
"players": 23,
|
||||
"in": [
|
||||
"127.0.0.1"
|
||||
],
|
||||
"join": null,
|
||||
"id": "a43e02fb2ba44119972939bdee0de79b",
|
||||
"status": "waiting",
|
||||
"private": "0"
|
||||
},
|
||||
{
|
||||
"game": "dxdrqlegvkewqmbnxqewxtfbuabnvpjgtievgiahljrmcfzgmkcmqhgvuscixtfairqtrdlulieyqfsmly",
|
||||
"players": 97,
|
||||
"in": [
|
||||
"127.0.0.1"
|
||||
],
|
||||
"join": null,
|
||||
"id": "8376a6187cf14af398438d1d3180527b",
|
||||
"status": "waiting",
|
||||
"private": "1"
|
||||
},
|
||||
{
|
||||
"game": "lnqezetegyjbiugvmavjyruuhkrjovvpqgg",
|
||||
"players": 47,
|
||||
"in": [
|
||||
"127.0.0.1"
|
||||
],
|
||||
"join": null,
|
||||
"id": "4a528ea9d4414feab863b57cbeec81c0",
|
||||
"status": "waiting",
|
||||
"private": "0"
|
||||
},
|
||||
{
|
||||
"game": "ndafqktzbjvdcrgzyaatncyqorktpgraccpnrwfgikmgiwqtyfflochqzpvfqhq",
|
||||
"players": 58,
|
||||
"in": [
|
||||
"127.0.0.1"
|
||||
],
|
||||
"join": null,
|
||||
"id": "28120581cfde4c52986e90db8c9482c1",
|
||||
"status": "waiting",
|
||||
"private": "0"
|
||||
},
|
||||
{
|
||||
"game": "tojmewhiezbotczdauzrguwalkjrwsbdwtrbvmcexpfrxfocindtekqyznxcfljemqqzjxmmjrwuynqbp",
|
||||
"players": 57,
|
||||
"in": [
|
||||
"127.0.0.1"
|
||||
],
|
||||
"join": null,
|
||||
"id": "41f056fd84b941e083d5ebbe6a7d8b57",
|
||||
"status": "waiting",
|
||||
"private": "1"
|
||||
},
|
||||
{
|
||||
"game": "pssuf",
|
||||
"players": 79,
|
||||
"in": [
|
||||
"127.0.0.1"
|
||||
],
|
||||
"join": null,
|
||||
"id": "dc6d4137a0a449488ab53e0a3f74395b",
|
||||
"status": "waiting",
|
||||
"private": "0"
|
||||
},
|
||||
{
|
||||
"game": "arzroeispbeoolyhdewldelnujpdtervbkgpmhogiokyd",
|
||||
"players": 63,
|
||||
"in": [
|
||||
"127.0.0.1"
|
||||
],
|
||||
"join": null,
|
||||
"id": "e854f973d8ed42ffa108f36da7582ce5",
|
||||
"status": "waiting",
|
||||
"private": "0"
|
||||
},
|
||||
{
|
||||
"game": "pmhvdefegfdiasyqabsgzfttcgvxaykwljymzqlobccikdwxzgilncdgtbnmvctmeqcayneahiknphamghnaor",
|
||||
"players": 71,
|
||||
"in": [
|
||||
"127.0.0.1"
|
||||
],
|
||||
"join": null,
|
||||
"id": "643fe4f9ef594a5ca86fc9cda58d4c20",
|
||||
"status": "waiting",
|
||||
"private": false
|
||||
},
|
||||
{
|
||||
"game": "krlwcdjnkdrjvumynonpozzlyynnexvikjlndyfvbjzklmzqenzwsygaktzrwckjabmvcccijenhzukjainvohvrzzp",
|
||||
"players": 69,
|
||||
"in": [
|
||||
"127.0.0.1"
|
||||
],
|
||||
"join": null,
|
||||
"id": "dae25c91472f42cc8e618bde021f3128",
|
||||
"status": "waiting",
|
||||
"private": false
|
||||
},
|
||||
{
|
||||
"game": "xvbwrznbzycqvcmpxpczskdkrmmiqpajeonuppfvqskvrxasngemhwkxsxvkgzimyxidnwtiir",
|
||||
"players": 27,
|
||||
"in": [
|
||||
"127.0.0.1"
|
||||
],
|
||||
"join": null,
|
||||
"id": "3814255ee40b46498a35aea08507a428",
|
||||
"status": "waiting",
|
||||
"private": false
|
||||
},
|
||||
{
|
||||
"game": "pyhjdpbhekncclbvwjeenlaxtdphmyxszfzzfeeyuqclolztoaiflpo",
|
||||
"players": 62,
|
||||
"in": [
|
||||
"127.0.0.1"
|
||||
],
|
||||
"join": null,
|
||||
"id": "2f9f612e40e04df6b54a45e83029b240",
|
||||
"status": "waiting",
|
||||
"private": false
|
||||
}
|
||||
]
|
140
src/templates/index.html
Normal file
140
src/templates/index.html
Normal file
@ -0,0 +1,140 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>Games</title>
|
||||
<!-- TODO: Add script and style to static(didn't wanna do that fuck) -->
|
||||
<style>
|
||||
/* change font to roboto */
|
||||
|
||||
body {
|
||||
font-family: 'Roboto', sans-serif;
|
||||
/* Gray to darker gray full-page gradient */
|
||||
|
||||
}
|
||||
|
||||
a {
|
||||
text-decoration: none;
|
||||
color: black;
|
||||
|
||||
}
|
||||
.underline {
|
||||
display: inline-block;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.underline::after {
|
||||
content: '';
|
||||
position: absolute;
|
||||
width: 100%;
|
||||
transform: scaleX(0);
|
||||
height: 2px;
|
||||
bottom: 0;
|
||||
left: 0;
|
||||
background-color: gray;
|
||||
transform-origin: bottom right;
|
||||
transition: transform 0.25s ease-out;
|
||||
}
|
||||
|
||||
.underline:hover::after {
|
||||
transform: scaleX(1);
|
||||
transform-origin: bottom left;
|
||||
}
|
||||
|
||||
|
||||
|
||||
#header {
|
||||
width: 100%;
|
||||
background: linear-gradient(180deg, #ECECEC 0%, #D9D9D9 100%);
|
||||
text-align: center;
|
||||
margin-bottom: 10px;
|
||||
padding: 5px;
|
||||
|
||||
}
|
||||
.content{
|
||||
display:flex;
|
||||
flex-wrap: wrap;
|
||||
justify-content: space-evenly;
|
||||
}
|
||||
|
||||
.games {
|
||||
|
||||
background: white;
|
||||
border-radius: 10px;
|
||||
border: 1px solid black;
|
||||
padding: 10px;
|
||||
margin:10px;
|
||||
color: black;
|
||||
text-align: center;
|
||||
flex-shrink: calc(100% / 3 - 20px);
|
||||
}
|
||||
.zoom {
|
||||
|
||||
transition: transform .5s; /* Animation */
|
||||
|
||||
}
|
||||
|
||||
.zoom:hover {
|
||||
transform: scale(1.1); /* (150% zoom - Note: if the zoom is too large, it will go outside of the viewport) */
|
||||
}
|
||||
</style>
|
||||
|
||||
<script>
|
||||
// Create a game and return its json
|
||||
function createGame() {
|
||||
let game = prompt("What game are we playing?")
|
||||
let players = Number(prompt("How many players?"))
|
||||
let data = {name: game, players: players}
|
||||
|
||||
fetch(`/new/${game}/${players}`, {
|
||||
method: 'POST',
|
||||
})
|
||||
|
||||
.then(response => response.json())
|
||||
.then(data => {
|
||||
console.log('Success:', data);
|
||||
document.getElementById("create").innerHTML = "Game created!";
|
||||
document.getElementById("create").onclick = redirect(data.id);
|
||||
// make a href to the game
|
||||
})
|
||||
}
|
||||
|
||||
function redirect(game_id) {
|
||||
window.location.replace(`/games/${game_id}`)
|
||||
}
|
||||
</script>
|
||||
</head>
|
||||
<body>
|
||||
|
||||
<div id = "header">
|
||||
<h1>Game Lobby</h1>
|
||||
<p>Create a game or join one(programmatically)!</p>
|
||||
</div>
|
||||
<div class="content">
|
||||
<!-- List all active games if there is a game -->
|
||||
<!-- Given a list of dictionaries passed by flask -->
|
||||
{% if games %}
|
||||
<table>
|
||||
{% for game in games %}
|
||||
<!-- <li>
|
||||
<a href="/games/{{ game['id'] }}">{{ game['game'] }}</a>
|
||||
</li> -->
|
||||
<a href="/games/{{game['id']}}">
|
||||
<div class="games zoom underline">
|
||||
<h4> {{game['game']}} </h4>
|
||||
<!-- horizontal line -->
|
||||
<hr>
|
||||
<p>{{game['in']|length}}/{{game['players']}} players </p>
|
||||
<p> {{game['status']}} </p>
|
||||
</div>
|
||||
</a>
|
||||
{% endfor %}
|
||||
</table>
|
||||
{% else %}
|
||||
<h1>No one's playing...</h1>
|
||||
<h2 onclick="createGame()", id="create"> Create one?</h2>
|
||||
{% endif %}
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
22
src/tests/random_lobbies.py
Normal file
22
src/tests/random_lobbies.py
Normal file
@ -0,0 +1,22 @@
|
||||
from random import randint
|
||||
from requests import post
|
||||
|
||||
def random_lobbies():
|
||||
"""Generates a random number of lobbies"""
|
||||
n = randint(1, 100)
|
||||
for i in range(n):
|
||||
# Random string
|
||||
name = ""
|
||||
for i in range(randint(1, 100)):
|
||||
name += chr(randint(97, 122))
|
||||
# Random number of players
|
||||
players = randint(1, 100)
|
||||
# Random private status
|
||||
|
||||
|
||||
# Create lobby
|
||||
req = post(f"http://localhost:5000/new/{name}/{players}")
|
||||
print(req.text)
|
||||
|
||||
if __name__ == "__main__":
|
||||
random_lobbies()
|
Loading…
x
Reference in New Issue
Block a user