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 flask import Flask, render_template, request, redirect, url_for, flash, session, jsonify
|
||||||
|
|
||||||
from uuid import uuid4
|
from uuid import uuid4
|
||||||
from flask_socketio import SocketIO
|
from flask_socketio import SocketIO
|
||||||
import json
|
import json
|
||||||
@ -7,6 +8,8 @@ app = Flask(__name__)
|
|||||||
app.config['SECRET_KEY'] = 'DEV'
|
app.config['SECRET_KEY'] = 'DEV'
|
||||||
socketio = SocketIO(app)
|
socketio = SocketIO(app)
|
||||||
|
|
||||||
|
NAME_LENGTH = 50
|
||||||
|
MAX_PLAYERS = 100
|
||||||
|
|
||||||
def find_game_by_id(id:str) -> dict:
|
def find_game_by_id(id:str) -> dict:
|
||||||
games = []
|
games = []
|
||||||
@ -24,13 +27,17 @@ def start_game(game:dict):
|
|||||||
pass
|
pass
|
||||||
|
|
||||||
|
|
||||||
@app.route('/')
|
|
||||||
def index():
|
|
||||||
return "Empty for now"
|
|
||||||
|
|
||||||
@app.route('/new/<string:name>/<int:players>', methods=['POST'])
|
@app.route('/new/<string:name>/<int:players>', methods=['POST'])
|
||||||
def new_game(name, players):
|
def new_game(name, players):
|
||||||
# Log new game into json file and return a websocket url for the game
|
# 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 = []
|
games = []
|
||||||
with open('games.json', 'r') as f:
|
with open('games.json', 'r') as f:
|
||||||
games = json.load(f)
|
games = json.load(f)
|
||||||
@ -44,6 +51,7 @@ def new_game(name, players):
|
|||||||
"join": None,
|
"join": None,
|
||||||
"id": f"{uuid4().hex}",
|
"id": f"{uuid4().hex}",
|
||||||
"status": "waiting",
|
"status": "waiting",
|
||||||
|
"private":False if request.args.get('private') is None else request.args.get('private'),
|
||||||
}
|
}
|
||||||
games.append(game)
|
games.append(game)
|
||||||
|
|
||||||
@ -53,6 +61,26 @@ def new_game(name, players):
|
|||||||
return jsonify(game)
|
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'])
|
@app.route('/join/<uuid:game_id>', methods=['POST'])
|
||||||
def join_game(game_id):
|
def join_game(game_id):
|
||||||
|
|
||||||
@ -60,7 +88,7 @@ def join_game(game_id):
|
|||||||
# Check if game exists
|
# Check if game exists
|
||||||
game = find_game_by_id(game_id)
|
game = find_game_by_id(game_id)
|
||||||
if "error" in game:
|
if "error" in game:
|
||||||
return {"error": "Game not found"}
|
return game["error"]
|
||||||
|
|
||||||
# Check if game is full
|
# Check if game is full
|
||||||
game, idx = game['game'], game['idx']
|
game, idx = game['game'], game['idx']
|
||||||
@ -83,6 +111,12 @@ def join_game(game_id):
|
|||||||
with open('games.json', 'w') as f:
|
with open('games.json', 'w') as f:
|
||||||
json.dump(games, f)
|
json.dump(games, f)
|
||||||
|
|
||||||
|
|
||||||
|
@app.route('/')
|
||||||
|
def index():
|
||||||
|
# List games
|
||||||
|
return render_template('index.html', games=list_games(internal=True))
|
||||||
|
|
||||||
if __name__ == '__main__':
|
if __name__ == '__main__':
|
||||||
socketio.run(app, debug=True)
|
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