added flake
This commit is contained in:
+170
@@ -0,0 +1,170 @@
|
||||
# Python
|
||||
from flask import Flask, render_template, request
|
||||
from flask_socketio import SocketIO, join_room
|
||||
import requests
|
||||
|
||||
ozai_url = 'http://localhost:8000/api/'
|
||||
app = Flask(__name__)
|
||||
socketio = SocketIO(app)
|
||||
|
||||
#get tis from env variable
|
||||
import os
|
||||
app.config['SECRET_KEY'] = os.environ.get('OZAI_WEBUI_SECRET_KEY')
|
||||
|
||||
|
||||
#home page
|
||||
@app.route('/')
|
||||
def home():
|
||||
return render_template('home.html')
|
||||
|
||||
#static files
|
||||
@app.route('/azul.webp')
|
||||
def background():
|
||||
#return the background image
|
||||
return app.send_static_file('azul.webp')
|
||||
|
||||
@app.route('/socket.io.js')
|
||||
def socketio_js():
|
||||
#return the background image
|
||||
return app.send_static_file('socket.io.js')
|
||||
|
||||
@app.route('/azul-flake.png')
|
||||
def logo():
|
||||
#return the background image
|
||||
return app.send_static_file('azul-flake.png')
|
||||
|
||||
|
||||
#game creation page
|
||||
@app.route('/create', methods=['GET', 'POST'])
|
||||
def create():
|
||||
if request.method == 'POST':
|
||||
# Handle the post request here
|
||||
#get all the player names data from the form
|
||||
player_names = []
|
||||
for i in range(1, 5):
|
||||
player_name = request.form['player' + str(i)]
|
||||
#purge to long names
|
||||
if len(player_name) > 20:
|
||||
player_name = player_name[:20]
|
||||
#sanitize the input
|
||||
player_name = player_name.strip()
|
||||
#replace spaces with underscores
|
||||
player_name = player_name.replace(' ', '_')
|
||||
# replace illegal characters with nothing
|
||||
illegal_chars = ['<', '>', '(', ')', '[', ']', ',', '.', ':', ';', '-', '/', '|', '\\','=', 'exec', 'spectator']
|
||||
for char in illegal_chars:
|
||||
player_name = player_name.replace(char, '')
|
||||
if player_name:
|
||||
player_names.append(player_name)
|
||||
|
||||
player_names = {"player_names": player_names}
|
||||
print(player_names)
|
||||
response = requests.post(ozai_url + 'game', json=player_names)
|
||||
if response.status_code == 200:
|
||||
game_id = response.json()
|
||||
print("Game ID:", game_id)
|
||||
return render_template('create.html', game_id=game_id)
|
||||
else:
|
||||
print("Error:", response.status_code, response.text)#log the game id
|
||||
|
||||
#return the game id to the user
|
||||
pass
|
||||
return render_template('create.html')
|
||||
|
||||
|
||||
#join page, for when the user has gotten a game id.
|
||||
@app.route('/join', methods=['GET', 'POST'])
|
||||
def join():
|
||||
if request.method == 'POST':
|
||||
#get game id from the form and redirect to the join_game page
|
||||
game_id = request.form['game_id']
|
||||
return render_template('join.html', game_id=game_id)
|
||||
return render_template('join.html')
|
||||
|
||||
#select player name page
|
||||
@app.route('/join_game/<game_id>/', methods=['GET','POST'])
|
||||
def join_game(game_id):
|
||||
|
||||
#get players from servre api and return them to the user
|
||||
response = requests.get(ozai_url + 'game/' + game_id)
|
||||
if response.status_code != 200:
|
||||
#return error message
|
||||
return 'Game not found', 404
|
||||
players = response.json().get('players')
|
||||
|
||||
if request.method == 'POST':
|
||||
#get the chosen player name from the form and redirect to the game page
|
||||
player_name = request.form['player']
|
||||
print('Player Name:', player_name)
|
||||
local_game = request.form.get('local_game')
|
||||
return render_template('join_game.html', game_id=game_id, players=players, player_name=player_name, local_game=local_game)
|
||||
|
||||
return render_template('join_game.html', game_id=game_id, players=players)
|
||||
|
||||
|
||||
#play game page
|
||||
@app.route('/game/<game_id>/player/<player_name>', methods=['GET'])
|
||||
@app.route('/game/<game_id>/player/<player_name>/local/<local_game>', methods=['GET'])
|
||||
def game(game_id, player_name, local_game=None):
|
||||
local_game = local_game == 'True'
|
||||
gamestate = requests.get(ozai_url + 'game/' + game_id).json()
|
||||
#dont send player parameter if the player is a spectator
|
||||
if player_name == 'spectator':
|
||||
gamestate = requests.get(ozai_url + 'game/' + game_id).json()
|
||||
return render_template('game.html', game_id=game_id, gamestate=gamestate, local_game=False)
|
||||
elif player_name in gamestate['players']:
|
||||
gamestate = requests.get(ozai_url + 'game/' + game_id + '?player=' + player_name).json()
|
||||
return render_template('game.html', game_id=game_id, gamestate=gamestate, player_name=player_name, local_game=local_game)
|
||||
else:
|
||||
return 'Player not found', 404
|
||||
|
||||
|
||||
@socketio.on('connect')
|
||||
def ws_connect(message):
|
||||
print('Client connected' + str(message))
|
||||
pass
|
||||
|
||||
@socketio.on('join')
|
||||
def ws_message(message):
|
||||
print('Client message' + str(message))
|
||||
game_id = message['game_id']
|
||||
print('Game ID: ', game_id)
|
||||
join_room(game_id)
|
||||
|
||||
@socketio.on('move')
|
||||
def ws_message(data):
|
||||
print('Client move' + str(data))
|
||||
|
||||
game_id = data['game_id']
|
||||
player_name = data['player_name']
|
||||
|
||||
#if a move was made.
|
||||
source = data['move']['source']
|
||||
color = data['move']['color']
|
||||
destination = data['move']['destination']
|
||||
if source != "market":
|
||||
source = int(source)-1
|
||||
if destination != "floor":
|
||||
destination = int(destination)-1
|
||||
move = {
|
||||
'player': str(player_name),
|
||||
'policy': 'strict', # or 'loose' depending on your needs
|
||||
'color': str(color),
|
||||
'source': source,
|
||||
'destination': destination
|
||||
}
|
||||
print(move)
|
||||
response = requests.put(ozai_url + 'game/' + game_id, json=move)
|
||||
if response.status_code == 200:
|
||||
socketio.emit('move', data, room=game_id)
|
||||
#send message to the other players, that the move was made
|
||||
socketio.emit('move_status', 'sucsess', room=game_id)
|
||||
else:
|
||||
#send message to the player that the move was invalid
|
||||
socketio.emit('move_status', response.text, room=game_id)
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
# app.run(debug=True, host='0.0.0.0', port=5000,ssl_context='adhoc')
|
||||
|
||||
socketio.run(app, debug=True, host='0.0.0.0', port=5000)
|
||||
Binary file not shown.
|
After Width: | Height: | Size: 5.4 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 62 KiB |
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,126 @@
|
||||
<!-- HTML -->
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<title>Ozai:create</title>
|
||||
<link rel="icon" type="image/png" href="/azul-flake.png">
|
||||
<style>
|
||||
body {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
margin-left: 10vw;
|
||||
width: 80vw;
|
||||
background-color: #000;
|
||||
color: #fff;
|
||||
color-scheme: dark;
|
||||
}
|
||||
|
||||
div {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
flex-wrap: wrap; /* Allow the flex items to wrap onto the next line */
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
form {
|
||||
margin-top: 20vh;
|
||||
max-width: 40em;
|
||||
min-width: 300px;
|
||||
margin: 0 auto;
|
||||
}
|
||||
|
||||
input[type="text"] {
|
||||
padding: 1em;
|
||||
margin-top: 1em;
|
||||
width: 100%;
|
||||
box-sizing: border-box;
|
||||
border: 0.5em solid #000;
|
||||
border-radius: 1em;
|
||||
}
|
||||
|
||||
input[type="submit"] {
|
||||
padding: 1em;
|
||||
margin-top: 3em;
|
||||
width: 100%;
|
||||
background-color: #0000FF;
|
||||
color: #fff;
|
||||
border: none;
|
||||
border-radius: 1em;
|
||||
cursor: pointer;
|
||||
box-shadow: 0px 0.1em 0.5em rgba(255, 255, 255, 0.333); /* Add some shadow for depth */
|
||||
transition: background-color 0.3s ease;
|
||||
}
|
||||
|
||||
input[type="submit"]:hover {
|
||||
background-color: #000099;
|
||||
}
|
||||
|
||||
button {
|
||||
padding: 1em;
|
||||
margin-top: 1em;
|
||||
background-color: #0000FF;
|
||||
color: #fff;
|
||||
border: none;
|
||||
border-radius: 0.5em;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
button:hover {
|
||||
background-color: #000099;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
{% if not game_id %}
|
||||
<div>
|
||||
<h1>Create Game</h1>
|
||||
<h2>Fill in playernames for wanted players</h2>
|
||||
<h3>Leave empty for no player ...</h3>
|
||||
</div>
|
||||
<form method="POST" action="/create">
|
||||
<input type="text" name="player1" placeholder="Player 1" required>
|
||||
<input type="text" name="player2" placeholder="Player 2" required>
|
||||
<input type="text" name="player3" placeholder="Player 3" style="background-color: #2a2929;">
|
||||
<input type="text" name="player4" placeholder="Player 4" style="background-color: #2a2929;">
|
||||
<!-- Add more input fields for more players -->
|
||||
<input type="submit" value="Create Game">
|
||||
</form>
|
||||
<button onclick="window.history.back();">Back</button>
|
||||
<script>
|
||||
// Select all player input elements
|
||||
var playerInputs = document.querySelectorAll('input[name^="player"]');
|
||||
|
||||
// Attach event listener to each input
|
||||
playerInputs.forEach(function(input) {
|
||||
input.addEventListener('change', function() {
|
||||
var currentValue = this.value;
|
||||
console.log(currentValue);
|
||||
var isUnique = Array.from(playerInputs).every(function(otherInput) {
|
||||
return otherInput === input || otherInput.value !== currentValue;
|
||||
});
|
||||
if (!isUnique && currentValue !== "") {
|
||||
alert('Player names must be unique!');
|
||||
// append a number to the name
|
||||
this.value = "";
|
||||
}
|
||||
});
|
||||
});
|
||||
</script>
|
||||
{% endif %}
|
||||
{% if game_id %}
|
||||
<p>Your game ID is: {{ game_id }}</p>
|
||||
<!-- button to redirect to /join/gameid -->
|
||||
<a href="/join_game/{{ game_id }}">Join Game</a>
|
||||
|
||||
<script>
|
||||
sessionStorage.setItem('game_id', '{{ game_id }}');
|
||||
//redirect to join game
|
||||
window.location.href = '/join_game/{{ game_id }}';
|
||||
</script>
|
||||
{% endif %}
|
||||
</body>
|
||||
</html>
|
||||
@@ -0,0 +1,506 @@
|
||||
<!-- HTML for game.html -->
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<title>Ozai:game</title>
|
||||
<link rel="icon" type="image/png" href="/azul-flake.png">
|
||||
<style>
|
||||
* {
|
||||
--border-color: rgb(172, 172, 172);
|
||||
--bg-transparency: 0.5;
|
||||
--tile-size: 2em;
|
||||
}
|
||||
|
||||
body {
|
||||
background-color: #383737;
|
||||
color: white;
|
||||
color-scheme: dark;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
a {
|
||||
padding: 1em;
|
||||
display: inline-block;
|
||||
text-decoration: none;
|
||||
color: #aba4f6;
|
||||
background-color: #1919a7;
|
||||
border-radius: 1em;
|
||||
font-weight: bold;
|
||||
font-size: 1.5em; /* increase font size */
|
||||
|
||||
}
|
||||
a:hover {
|
||||
background-color: #204ac8;
|
||||
}
|
||||
input[type="submit"] {
|
||||
border: none;
|
||||
border-radius: 1em;
|
||||
background-color: #3232d1;
|
||||
padding: 1em;
|
||||
}
|
||||
input[type="submit"]:hover {
|
||||
background-color: #3f3ff2;
|
||||
}
|
||||
select {
|
||||
font-size: 1.2em;
|
||||
}
|
||||
|
||||
.move_select {
|
||||
margin-top: 0.5em;
|
||||
display: flex;
|
||||
justify-content: space-around;
|
||||
flex-direction: row;
|
||||
align-items: baseline;
|
||||
}
|
||||
|
||||
/* flexbox class */
|
||||
.flex-row {
|
||||
display: flex;
|
||||
justify-content: left;
|
||||
flex-direction: row;
|
||||
flex-wrap: wrap;
|
||||
align-items: baseline;
|
||||
}
|
||||
|
||||
@media (max-width: 40em) {
|
||||
.flex-row {
|
||||
flex-direction: column;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
}
|
||||
}
|
||||
.flex-row > * {
|
||||
margin-right: 1em;
|
||||
}
|
||||
.flex-col {
|
||||
display: flex;
|
||||
justify-content:space-around;
|
||||
flex-direction: column;
|
||||
}
|
||||
|
||||
.factory {
|
||||
overflow: hidden;
|
||||
border: 0.2em solid var(--border-color);
|
||||
border-radius: 30%;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
/* flex wrap */
|
||||
flex-direction: row;
|
||||
flex-wrap: wrap;
|
||||
|
||||
height: calc(var(--tile-size) * 3);
|
||||
width: calc(var(--tile-size) * 3);
|
||||
|
||||
}
|
||||
#market {
|
||||
height: calc(var(--tile-size) * 7);
|
||||
width: calc(var(--tile-size) * 7);
|
||||
}
|
||||
/* put the first element in the corner of the factory */
|
||||
.factory-name {
|
||||
border-radius: 20%;
|
||||
margin-top: 0;
|
||||
margin-left: 0;
|
||||
position: relative;
|
||||
top: 0;
|
||||
left: 0;
|
||||
border: 0.2em solid var(--border-color);
|
||||
text-align: center;
|
||||
margin: 0.1em;
|
||||
width: 1.5em;
|
||||
height: 1.5em;
|
||||
overflow: hidden;
|
||||
text-align: center;
|
||||
vertical-align: middle;
|
||||
}
|
||||
|
||||
.factory > * {
|
||||
border-radius: 10%;
|
||||
border: 0.15em solid var(--border-color);
|
||||
text-align: center;
|
||||
margin: 0.1em;
|
||||
width: var(--tile-size);
|
||||
height: var(--tile-size);
|
||||
overflow: hidden;
|
||||
text-align: center;
|
||||
vertical-align: middle;
|
||||
}
|
||||
|
||||
.player_area {
|
||||
border: 0.2em solid var(--border-color);
|
||||
border-radius: 2em;
|
||||
padding: 1em;
|
||||
margin: 1em;
|
||||
}
|
||||
|
||||
.wall {
|
||||
/* 5*5 grid */
|
||||
display: grid;
|
||||
grid-template-columns: repeat(5, 1fr);
|
||||
grid-template-rows: repeat(5, 1fr);
|
||||
gap: 0.1em;
|
||||
}
|
||||
.wall > * {
|
||||
border: 0.15em solid var(--border-color);
|
||||
width: var(--tile-size);
|
||||
height: var(--tile-size);
|
||||
text-align: center;
|
||||
margin-top: 0.1em;
|
||||
}
|
||||
.pattern_lines {
|
||||
display: flex;
|
||||
justify-content: space-around;
|
||||
flex-direction: column;
|
||||
align-items: start;
|
||||
}
|
||||
.pattern_line {
|
||||
display: flex;
|
||||
justify-content: right;
|
||||
flex-direction:row-reverse;
|
||||
align-items:baseline;
|
||||
}
|
||||
.pattern_line > * {
|
||||
border: 0.15em solid var(--border-color);
|
||||
text-align: center;
|
||||
margin: 0.1em;
|
||||
width: var(--tile-size);
|
||||
height: var(--tile-size);
|
||||
overflow: hidden;
|
||||
text-align: center;
|
||||
vertical-align: middle;
|
||||
}
|
||||
.floor_container {
|
||||
display: flex;
|
||||
justify-content: left;
|
||||
flex-direction: row;
|
||||
align-items:baseline;
|
||||
}
|
||||
.floor {
|
||||
border: 0.15em solid var(--border-color);
|
||||
text-align: center;
|
||||
width: var(--tile-size);
|
||||
height: var(--tile-size);
|
||||
}
|
||||
.floor_value {
|
||||
text-align: center;
|
||||
width: var(--tile-size);
|
||||
}
|
||||
|
||||
|
||||
|
||||
.blue_bg {
|
||||
background-color: rgb(49, 157, 245, var(--bg-transparency));
|
||||
}
|
||||
.yellow_bg {
|
||||
background-color: rgb(247, 148, 62, var(--bg-transparency));
|
||||
}
|
||||
.red_bg {
|
||||
background-color: rgb(200, 50, 50, var(--bg-transparency));
|
||||
}
|
||||
.black_bg {
|
||||
background-color: rgb(30, 30, 30, var(--bg-transparency));
|
||||
}
|
||||
.white_bg {
|
||||
background-color:rgb(130, 130, 130, var(--bg-transparency));
|
||||
}
|
||||
|
||||
|
||||
.blue {
|
||||
border-radius: calc(var(--tile-size) * 0.2);
|
||||
background-color: rgb(49, 157, 245);
|
||||
}
|
||||
.yellow {
|
||||
border-radius: calc(var(--tile-size) * 0.2);
|
||||
background-color: rgb(247, 148, 62);
|
||||
}
|
||||
.red {
|
||||
border-radius: calc(var(--tile-size) * 0.2);
|
||||
background-color: rgb(200, 50, 50);
|
||||
}
|
||||
.black {
|
||||
border-radius: calc(var(--tile-size) * 0.2);
|
||||
background-color: rgb(30, 30, 30);
|
||||
}
|
||||
.white {
|
||||
border-radius: calc(var(--tile-size) * 0.2);
|
||||
background-color:rgb(130, 130, 130);
|
||||
}
|
||||
.start {
|
||||
border-radius: calc(var(--tile-size) * 0.2);
|
||||
background-color: rgb(165, 1, 155);
|
||||
}
|
||||
|
||||
|
||||
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<div class="flex-row">
|
||||
<p>Number of Players: {{ gamestate.n_players }}</p>
|
||||
<p>Current Player: {{ gamestate.current_player }}</p>
|
||||
<p>Playing as: {{ player_name }}</p>
|
||||
<p>Game Status: {% if gamestate.game_end %}Ended{% else %}Active{% endif %}</p>
|
||||
<p>Rounds: {{ gamestate.rounds }}</p>
|
||||
<p>Days: {{ gamestate.days }}</p>
|
||||
</div>
|
||||
|
||||
<div class="flex-row">
|
||||
<!-- market -->
|
||||
<div class="flex-col">
|
||||
<div class="factory-name">M</div>
|
||||
<div class="factory" id="market">
|
||||
{% for color, number in gamestate.market.items() %}
|
||||
{% if number > 0 %}
|
||||
{% for i in range(0, number) %}
|
||||
<div onclick="selectTile(this)" class="{{ color }}">{{ color[:1] }}</div>
|
||||
{% endfor %}
|
||||
{% endif %}
|
||||
{% endfor %}
|
||||
</div>
|
||||
</div>
|
||||
<!-- factories -->
|
||||
{% for factory in gamestate.factories %}
|
||||
<div class="flex col">
|
||||
<div class="factory-name">{{ loop.index }}</div>
|
||||
<div class="factory" id="factory{{ loop.index }}">
|
||||
{% for color, number in factory.items() %}
|
||||
{% if number > 0 %}
|
||||
{% for i in range(0, number) %}
|
||||
<div onclick="selectTile(this)" class="{{ color }}">{{ color[:1] }}</div>
|
||||
{% endfor %}
|
||||
{% endif %}
|
||||
{% endfor %}
|
||||
</div>
|
||||
</div>
|
||||
{% endfor %}
|
||||
</div>
|
||||
|
||||
<div class="flex-row">
|
||||
{% for name, player_data in gamestate.players.items() %}
|
||||
<div class="flex-col player_area">
|
||||
<div class="flex-row">
|
||||
{% if gamestate.current_player == name %}
|
||||
<p>◉</p>
|
||||
{% else %}
|
||||
<p>○</p>
|
||||
{% endif %}
|
||||
{% if player_name == name %}
|
||||
<div><strong>{{ name }}</strong></div>
|
||||
{% else %}
|
||||
<div>{{ name }}</div>
|
||||
{% endif %}
|
||||
{% if player_data.ready %}
|
||||
<p>Ready</p>
|
||||
{% endif %}
|
||||
<p>Points: {{ player_data.points }}</p>
|
||||
</div>
|
||||
|
||||
<div class="flex-row">
|
||||
<div class="flex-col">
|
||||
<!-- <h3>Pattern Lines</h3> -->
|
||||
{% for line in player_data.pattern_lines %}
|
||||
<div class="pattern_line" onclick="selectPatternLine(this)" value="{{loop.index}}">
|
||||
<!-- TODO: Fix this to not fill empty spaces. -->
|
||||
{% for i in range(0, loop.index) %}
|
||||
{% if line.number > i %}
|
||||
<div class="{{ line.color }}" >{{ line.color[:1] }}</div>
|
||||
{% else %}
|
||||
<div >_</div>
|
||||
{% endif %}
|
||||
{% endfor %}
|
||||
</div>
|
||||
{% endfor %}
|
||||
</div>
|
||||
<div class="flex-col">
|
||||
<!-- <h3>Wall</h3> -->
|
||||
<div class="wall">
|
||||
{% set colors_base = ['blue', 'yellow', 'red', 'black', 'white'] %}
|
||||
{% for row in player_data.wall %}
|
||||
{% set colors = colors_base[-loop.index0:] + colors_base[:-loop.index0] %}
|
||||
{% for cell in row %}
|
||||
{% set color = colors[loop.index0] + "_bg" %}
|
||||
<div class="{{ color }}">{% if cell %}{{ color[:1] }}{% else %}{{ '_' }}{% endif %}</div>
|
||||
{% endfor %}
|
||||
{% endfor %}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="floor_container" onclick="selectPatternLine(this)" value="floor">
|
||||
{% set floor_count = 0 %}
|
||||
{% set floor_negative_values = [1,1,2,2,2,3,3] %}
|
||||
{% for color, number in player_data.floor.items() %}
|
||||
{% if number > 0 %}
|
||||
{% set floor_count = floor_count + number %}
|
||||
{% for i in range(0, number) %}
|
||||
<!-- get index of item and set value to te value of floor_neg.. -->
|
||||
<div class="flex-col">
|
||||
<div class="floor_value">-{{ floor_negative_values[i] }}</div>
|
||||
<div class="{{ color }} floor">{{ color[:1] }}</div>
|
||||
</div>
|
||||
{% endfor %}
|
||||
{% endif %}
|
||||
{% endfor %}
|
||||
{% if floor_count < 7 %}
|
||||
{% set floor_blank_tiles = 7 - floor_count %}
|
||||
{% for i in range(0, floor_blank_tiles) %}
|
||||
<div class="flex-col">
|
||||
<div class="floor_value">-{{ floor_negative_values[i] }}</div>
|
||||
<div class="floor">_</div>
|
||||
</div>
|
||||
{% endfor %}
|
||||
{% endif %}
|
||||
</div>
|
||||
|
||||
{% if player_name == name %}
|
||||
<form id='moveForm'</form>
|
||||
<div class="flex-col">
|
||||
<div class="flex-row move_select">
|
||||
<div>
|
||||
<label for="source">from:</label>
|
||||
<select id="source" name="source">
|
||||
<option value="market">Market</option>
|
||||
{% for factory in gamestate.factories %}
|
||||
<option value="{{ loop.index }}">Factory {{ loop.index }}</option>
|
||||
{% endfor %}
|
||||
</select>
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<label for="color">Color:</label>
|
||||
<select id="color" name="color">
|
||||
<option value="red">Red</option>
|
||||
<option value="blue">Blue</option>
|
||||
<option value="yellow">Yellow</option>
|
||||
<option value="black">Black</option>
|
||||
<option value="white">White</option>
|
||||
</select>
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<label for="destination">to:</label>
|
||||
<select id="destination" name="destination">
|
||||
<option value="1">Line 1</option>
|
||||
<option value="2">Line 2</option>
|
||||
<option value="3">Line 3</option>
|
||||
<option value="4">Line 4</option>
|
||||
<option value="5">Line 5</option>
|
||||
<option value="floor">Floor</option>
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<input type="submit" value="Submit Move" style="margin-top: 1em;">
|
||||
</div>
|
||||
</form>
|
||||
{% endif %}
|
||||
|
||||
</div>
|
||||
{% endfor %}
|
||||
</div>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
{% if player_name %}
|
||||
<!-- form for submitting a move, a move is a selection of marcet or factory, what color, and what patternline or floor it goes to. -->
|
||||
|
||||
<!-- button to go to next player -->
|
||||
|
||||
{% if local_game %}
|
||||
{% set current_index = gamestate.player_names.index(player_name) %}
|
||||
{% set next_index = current_index + 1 if current_index + 1 < gamestate.player_names|length else 0 %}
|
||||
<a href="/game/{{ game_id }}/player/{{ gamestate.player_names[next_index] }}">Next Player</a>
|
||||
{% endif %}
|
||||
|
||||
{% endif %}
|
||||
|
||||
|
||||
|
||||
<script src="/socket.io.js"></script>
|
||||
<script>
|
||||
console.log('Game ID: {{ game_id }}');
|
||||
console.log('Player Name: {{ player_name }}');
|
||||
console.log('Gamestate: {{ gamestate }}');
|
||||
|
||||
function selectTile(tile) {
|
||||
var source = tile.parentElement.id;
|
||||
if (source == 'market') {
|
||||
source = 'market';
|
||||
}else {
|
||||
source = source.replace('factory', '');
|
||||
}
|
||||
var color = tile.getAttribute('class');
|
||||
console.log('Selected tile: ' + color + ' from ' + source);
|
||||
//get elements of the form
|
||||
var sourceElement = document.getElementById('source');
|
||||
var colorElement = document.getElementById('color');
|
||||
//select the selected source and color
|
||||
console.log(sourceElement);
|
||||
console.log(colorElement);
|
||||
|
||||
//find the element in the dropdowns with the same value as the source and color
|
||||
var sourceOption = sourceElement.querySelector('option[value="' + source + '"]');
|
||||
var colorOption = colorElement.querySelector('option[value="' + color + '"]');
|
||||
console.log(sourceOption);
|
||||
console.log(colorOption);
|
||||
//set the selected attribute to true
|
||||
sourceOption.selected = true;
|
||||
colorOption.selected = true;
|
||||
}
|
||||
|
||||
function selectPatternLine(pattern_line) {
|
||||
//get the value of the pattern line element
|
||||
value = pattern_line.getAttribute('value');
|
||||
console.log('Selected pattern line: ' + pattern_line + ' with value: ' + value);
|
||||
var destinationElement = document.getElementById('destination');
|
||||
var destinationOption = destinationElement.querySelector('option[value="' + value + '"]');
|
||||
destinationOption.selected = true;
|
||||
}
|
||||
|
||||
// refresh the page by listening to websocket events
|
||||
|
||||
game_id = '{{ game_id }}';
|
||||
player_name = '{{ player_name }}';
|
||||
|
||||
var socket = io();
|
||||
|
||||
// send a message to the server in the message name space
|
||||
socket.emit('join', {game_id: game_id});
|
||||
|
||||
socket.addEventListener('move', function (event) {
|
||||
console.log('Game update received: ' + event);
|
||||
window.location.reload();
|
||||
});
|
||||
|
||||
// if we wana go over to using websocket entirely to send the move
|
||||
let form = document.querySelector('#moveForm');
|
||||
form.addEventListener('submit', function(event) {
|
||||
// Prevent the form from being submitted normally
|
||||
event.preventDefault();
|
||||
// Create a FormData object from the form
|
||||
let formData = new FormData(form);
|
||||
// Convert the FormData to a plain object
|
||||
let data = {};
|
||||
formData.forEach((value, key) => data[key] = value);
|
||||
console.log(data);
|
||||
socket.emit('move', {game_id: game_id, player_name, move: data});
|
||||
|
||||
// if local_game is tru change player
|
||||
//{% if local_game %}
|
||||
let nextPlayer = '{{ gamestate.player_names[gamestate.player_names.index(player_name) + 1 if gamestate.player_names.index(player_name) + 1 < gamestate.player_names|length else 0] }}';
|
||||
window.location.href = '/game/{{ game_id }}/player/' + nextPlayer;
|
||||
//{% endif %}
|
||||
|
||||
});
|
||||
|
||||
</script>
|
||||
|
||||
|
||||
</body>
|
||||
</html>
|
||||
@@ -0,0 +1,54 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<title>Ozai:home</title>
|
||||
<link rel="icon" type="image/png" href="/azul-flake.png">
|
||||
<style>
|
||||
body {
|
||||
background-color: black;
|
||||
}
|
||||
div {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
flex-wrap: wrap; /* Allow the flex items to wrap onto the next line */
|
||||
width: 90%;
|
||||
position: relative;
|
||||
left: 5%;
|
||||
}
|
||||
|
||||
img {
|
||||
position: relative;
|
||||
left: 40%;
|
||||
width: 20%;
|
||||
}
|
||||
|
||||
a {
|
||||
display: inline-block;
|
||||
margin: 5%;
|
||||
padding: 5vh 5vw; /* increase padding to make buttons larger */
|
||||
text-decoration: none;
|
||||
color: white;
|
||||
background-color: rgb(0, 120, 247); /* Semi-transparent blue color to mimic the tiles */
|
||||
border-radius: 1em;
|
||||
font-weight: bold;
|
||||
font-size: 3em; /* increase font size */
|
||||
box-shadow: 0px 0.5em 1em rgba(255, 255, 255, 0.333); /* Add some shadow for depth */
|
||||
transition: background-color 0.3s ease; /* Smooth transition for hover and focus */
|
||||
}
|
||||
|
||||
a:hover, a:focus {
|
||||
background-color: rgba(0, 120, 247, 0.7); /* Darker blue on hover and focus */
|
||||
outline: none; /* Remove default focus outline */
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<img src="azul-flake.png" alt="">
|
||||
<div>
|
||||
<a href="/create">Create Game</a>
|
||||
<a href="/join">Join Game</a>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
||||
@@ -0,0 +1,88 @@
|
||||
<!-- HTML -->
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<title>Ozai:Join</title>
|
||||
<link rel="icon" type="image/png" href="/azul-flake.png">
|
||||
<style>
|
||||
body {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
background-color: black;
|
||||
color: white;
|
||||
color-scheme: dark;
|
||||
}
|
||||
|
||||
|
||||
form {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
margin-top: 5vh;
|
||||
width: 80%;
|
||||
max-width: 500px;
|
||||
}
|
||||
|
||||
button, input[type="submit"] {
|
||||
background-color: #0000FF;
|
||||
cursor: pointer;
|
||||
box-shadow: 0px 0.1em 0.5em rgba(255, 255, 255, 0.333);
|
||||
margin-top: 2em;
|
||||
}
|
||||
|
||||
button, input[type="submit"], input[type="text"] {
|
||||
margin-top: 5vh;
|
||||
padding: 1em;
|
||||
margin-top: 1em;
|
||||
|
||||
color: #fff;
|
||||
border: none;
|
||||
border-radius: 1em;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
|
||||
@media (max-width: 768px) {
|
||||
input[type="text"], input[type="submit"], button {
|
||||
font-size: 1.5em;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<img src="azul-flake.png" alt="">
|
||||
<!-- a field to add a game id -->
|
||||
<form id="joinGameForm" method="POST" action="/join" onsubmit="submitForm(event)">
|
||||
<input type="text" name="game_id" placeholder="Game ID" required value="{{ game_id }}">
|
||||
<input type="submit" value="Join Game">
|
||||
<button onclick="window.history.back();">Back</button>
|
||||
</form>
|
||||
|
||||
|
||||
</body>
|
||||
<script>
|
||||
function submitForm(e) {
|
||||
e.preventDefault();
|
||||
var game_id = document.querySelector('input[name="game_id"]').value;
|
||||
sessionStorage.setItem('game_id', game_id);
|
||||
document.getElementById('joinGameForm').submit();
|
||||
}
|
||||
|
||||
var game_id = sessionStorage.getItem('game_id');
|
||||
if (game_id) {
|
||||
document.querySelector('input[name="game_id"]').value = game_id;
|
||||
}
|
||||
</script>
|
||||
|
||||
{% if game_id %}
|
||||
<script>
|
||||
var game_id = '{{ game_id }}';
|
||||
sessionStorage.setItem('game_id', game_id);
|
||||
//redirect to join game
|
||||
window.location.href = '/join_game/' + game_id;
|
||||
</script>
|
||||
{% endif %}
|
||||
</html>
|
||||
@@ -0,0 +1,118 @@
|
||||
<!-- HTML -->
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<title>Ozai webui:Join Game</title>
|
||||
<style>
|
||||
body {
|
||||
font-family: Arial, sans-serif;
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
background-color: black;
|
||||
color: white;
|
||||
color-scheme: dark;
|
||||
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
|
||||
}
|
||||
div{
|
||||
margin-top: 20vh;
|
||||
}
|
||||
div,form {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
flex-wrap: wrap; /* Allow the flex items to wrap onto the next line */
|
||||
width: 90vw;
|
||||
}
|
||||
|
||||
ul {
|
||||
list-style-type: none;
|
||||
padding: 0;
|
||||
}
|
||||
li {
|
||||
margin-bottom: 1em;
|
||||
}
|
||||
|
||||
select, input[type="submit"] {
|
||||
padding: 1em;
|
||||
margin-top: 1em;
|
||||
width: 40%;
|
||||
min-width: 30em;
|
||||
max-width: 50em;
|
||||
height: 7vh;
|
||||
}
|
||||
|
||||
input[type="submit"] {
|
||||
background-color: #3779fd;
|
||||
border: none;
|
||||
border-radius: 1em;
|
||||
text-decoration: none;
|
||||
margin: 6em 1em;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
|
||||
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<div>
|
||||
|
||||
{% if game_id %}
|
||||
<p>Selected game to join is: <strong>{{ game_id }}</strong></p>
|
||||
{% endif %}
|
||||
|
||||
{% if players %}
|
||||
<p>Players in game:</p>
|
||||
<ul>
|
||||
{% for player in players %}
|
||||
<li>{{ player }}</li>
|
||||
{% endfor %}
|
||||
</ul>
|
||||
<!-- form to select one player to play as, or to select spectator too play as -->
|
||||
<form method="POST" action="/join_game/{{ game_id }}">
|
||||
<select name="player">
|
||||
<option value="spectator" selected>Spectator</option>
|
||||
{% for player in players %}
|
||||
<option value="{{ player }}">{{ player }}</option>
|
||||
{% endfor %}
|
||||
</select>
|
||||
<p>game type</p>
|
||||
<select name="local_game" required>
|
||||
<option value="True" selected>Local</option>
|
||||
<option value="False">Online</option>
|
||||
</select>
|
||||
<input type="submit" value="Join Game">
|
||||
</form>
|
||||
|
||||
{% else %}
|
||||
<p>No players found in game, please recreate the game.</p>
|
||||
{% endif %}
|
||||
|
||||
|
||||
{% if player_name %}
|
||||
<noscript>
|
||||
<p>Selected player to join as: {{ player_name }}</p>
|
||||
<p>manual redirect</p>
|
||||
<a href="/game/{{ game_id }}/player/{{ player_name }}/local/{{ local_game }}">Go to game</a>
|
||||
</noscript>
|
||||
<script>
|
||||
// Save player name in browser session for auto fill in game page
|
||||
sessionStorage.setItem('player_name', '{{ player_name }}');
|
||||
//redirect to game
|
||||
window.location.href = '/game/{{ game_id }}/player/{{ player_name }}/local/{{ local_game }}';
|
||||
</script>
|
||||
{% endif %}
|
||||
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
||||
Reference in New Issue
Block a user