Overhaul Model, Start Rendering of Lobby view
This commit is contained in:
parent
cc35dec294
commit
af2ef29585
15
main.py
15
main.py
@ -1,6 +1,8 @@
|
|||||||
import aiohttp.web
|
import aiohttp.web
|
||||||
import traceback
|
import traceback
|
||||||
import urllib.parse
|
import urllib.parse
|
||||||
|
import os
|
||||||
|
import json
|
||||||
|
|
||||||
from model import Model
|
from model import Model
|
||||||
|
|
||||||
@ -50,7 +52,7 @@ async def handler(request: aiohttp.web.Request):
|
|||||||
|
|
||||||
data = await request.json()
|
data = await request.json()
|
||||||
|
|
||||||
print(f'{client=} {data=}')
|
print(f'{method=} {client=} {data=}')
|
||||||
|
|
||||||
try:
|
try:
|
||||||
assert method in model.ApiMethod.dict
|
assert method in model.ApiMethod.dict
|
||||||
@ -60,7 +62,8 @@ async def handler(request: aiohttp.web.Request):
|
|||||||
del e # unused?
|
del e # unused?
|
||||||
traceback.print_exc()
|
traceback.print_exc()
|
||||||
return aiohttp.web.Response(status=400)
|
return aiohttp.web.Response(status=400)
|
||||||
|
finally:
|
||||||
|
await model.send_state(client)
|
||||||
|
|
||||||
@routes.get(CLIENT_REGEX + '/ws')
|
@routes.get(CLIENT_REGEX + '/ws')
|
||||||
async def _(request: aiohttp.web.Request):
|
async def _(request: aiohttp.web.Request):
|
||||||
@ -110,7 +113,13 @@ if __name__ == '__main__':
|
|||||||
app = aiohttp.web.Application()
|
app = aiohttp.web.Application()
|
||||||
app.add_routes(routes)
|
app.add_routes(routes)
|
||||||
|
|
||||||
app['model'] = Model()
|
data = {}
|
||||||
|
filename = "tehsession.json"
|
||||||
|
if os.path.isfile(filename):
|
||||||
|
with open(filename) as f:
|
||||||
|
data = json.load(f)
|
||||||
|
|
||||||
|
app['model'] = Model(model = data)
|
||||||
|
|
||||||
aiohttp.web.run_app(app, port=42042)
|
aiohttp.web.run_app(app, port=42042)
|
||||||
app['model'].save()
|
app['model'].save()
|
||||||
|
190
model.py
190
model.py
@ -22,28 +22,22 @@ class Model(object):
|
|||||||
def __contains__(self, item):
|
def __contains__(self, item):
|
||||||
return item in self.dict
|
return item in self.dict
|
||||||
|
|
||||||
def __init__(self, filename="tehmodel.json"):
|
def __init__(self, model = {}):
|
||||||
self.sockets = {} # mapping: client -> socket
|
if "sessions" not in model:
|
||||||
self.filename = filename
|
model["sessions"] = []
|
||||||
self.model = None
|
if "clients" not in model:
|
||||||
if os.path.isfile(filename):
|
model["clients"] = []
|
||||||
with open(filename) as f:
|
self.sockets = {} # mapping: clientid -> sockets
|
||||||
try:
|
self.sessions = { session: Session(model = model["sessions"][session]) for session in model["sessions"] }
|
||||||
self.model = json.load(f)
|
self.clients = { client: Client(model = model["clients"][client]) for client in model["clients"] }
|
||||||
except:
|
self.filename = "tehsession.json"
|
||||||
self.model = {}
|
|
||||||
else:
|
|
||||||
self.model = {}
|
|
||||||
self.assert_model()
|
|
||||||
|
|
||||||
def assert_model(self):
|
def to_json(self):
|
||||||
if not "clients" in self.model:
|
model = {
|
||||||
self.model["clients"] = {}
|
"sessions": {session: self.sessions[session].to_json() for session in self.sessions },
|
||||||
if not "sessions" in self.model:
|
"clients": {client: self.clients[client].to_json() for client in self.clients },
|
||||||
self.model["sessions"] = {}
|
}
|
||||||
for session in self.model["sessions"]:
|
return model
|
||||||
if not "name" in self.model["sessions"][session]:
|
|
||||||
self.model["sessions"][session]["name"] = "Defaultname"
|
|
||||||
|
|
||||||
@ApiMethod
|
@ApiMethod
|
||||||
async def test_api(self, clientid):
|
async def test_api(self, clientid):
|
||||||
@ -55,79 +49,96 @@ class Model(object):
|
|||||||
|
|
||||||
@ApiMethod
|
@ApiMethod
|
||||||
async def change_username(self, clientid, username) -> str:
|
async def change_username(self, clientid, username) -> str:
|
||||||
self.model["clients"][clientid]["username"] = username
|
self.clients[clientid].name = username
|
||||||
await self.send_state(clientid)
|
|
||||||
|
|
||||||
@ApiMethod
|
@ApiMethod
|
||||||
async def create_session(self, clientid, sessionname) -> str:
|
async def create_session(self, clientid, sessionname) -> str:
|
||||||
if not sessionname:
|
if not sessionname:
|
||||||
raise Exception("Cant be empty!")
|
raise Exception(f"Sessionname cant be empty!")
|
||||||
sessionid = generate_random_id()
|
session = Session(name = sessionname, owner = clientid)
|
||||||
newsession = {"id": sessionid, "owner": clientid, "clients": [], "name": sessionname }
|
self.sessions[session.id] = session
|
||||||
self.model["sessions"][sessionid] = newsession
|
print("create_session was called")
|
||||||
await self.send_state(clientid)
|
|
||||||
|
|
||||||
@ApiMethod
|
@ApiMethod
|
||||||
async def change_sessionname(self, clientid, sessionid, sessionname) -> str:
|
async def change_sessionname(self, clientid, sessionid, sessionname) -> str:
|
||||||
if not sessionname:
|
if not sessionname:
|
||||||
raise Exception("Cant be empty!")
|
raise Exception("Cant be empty!")
|
||||||
if self.model["sessions"][sessionid]["owner"] == clientid:
|
session = self.sessions[sessionid]
|
||||||
self.model["sessions"][sessionid]["name"] = sessionname
|
if not (session.owner == clientid):
|
||||||
await self.send_state(clientid)
|
raise Exception("Ownly owner can change sessionname")
|
||||||
|
session.name = sessionname
|
||||||
|
|
||||||
@ApiMethod
|
@ApiMethod
|
||||||
async def leave_session(self, clientid):
|
async def leave_session(self, clientid):
|
||||||
sessionid = self.model["clients"][clientid]["session"]
|
client = self.clients[clientid]
|
||||||
del self.model["clients"][clientid]["session"]
|
sessionid = client.session
|
||||||
self.model["sessions"][sessionid]["clients"].remove(clientid)
|
if sessionid:
|
||||||
await self.send_state(clientid)
|
session = self.sessions[sessionid]
|
||||||
|
session.clients.remove(clientid)
|
||||||
|
self.clients[clientid].session = ""
|
||||||
|
|
||||||
@ApiMethod
|
@ApiMethod
|
||||||
async def join_session(self, clientid, sessionid):
|
async def join_session(self, clientid, sessionid):
|
||||||
if sessionid in self.model["sessions"]:
|
client = self.clients[clientid]
|
||||||
# session exists
|
old_sessionid = client.session
|
||||||
self.model["clients"][clientid]["session"] = sessionid
|
# leave old session
|
||||||
if not clientid in self.model["sessions"][sessionid]["clients"]:
|
if old_sessionid:
|
||||||
self.model["sessions"][sessionid]["clients"].append(clientid)
|
old_session = self.sessions[old_sessionid]
|
||||||
await self.send_state(clientid)
|
old_session.clients.remove(clientid)
|
||||||
|
session = self.sessions[sessionid]
|
||||||
|
client.session = sessionid
|
||||||
|
session.clients.append(client.id)
|
||||||
|
|
||||||
|
async def send_lobby_view(self, clientid):
|
||||||
|
data = {}
|
||||||
|
client = self.clients[clientid]
|
||||||
|
|
||||||
|
data["view"] = "lobby"
|
||||||
|
data["username"] = client.name
|
||||||
|
data["sessions"] = {
|
||||||
|
session.id: {
|
||||||
|
"id": session.id,
|
||||||
|
"name": session.name,
|
||||||
|
"owned": session.owner == client.id,
|
||||||
|
} for session in self.sessions.values()
|
||||||
|
}
|
||||||
|
for socket in self.sockets[clientid]:
|
||||||
|
await socket.send_json(data)
|
||||||
|
|
||||||
|
async def send_session_view(self, clientid):
|
||||||
|
data = {}
|
||||||
|
client = self.clients[clientid]
|
||||||
|
|
||||||
|
data["view"] = "session"
|
||||||
|
data["username"] = client.name
|
||||||
|
|
||||||
|
for socket in self.sockets[clientid]:
|
||||||
|
await socket.send_json(data)
|
||||||
|
|
||||||
async def send_state(self, clientid):
|
async def send_state(self, clientid):
|
||||||
# TODO: compute state, send to client
|
# TODO: compute state, send to client
|
||||||
data = {}
|
data = {}
|
||||||
if "session" in self.model["clients"][clientid]:
|
client = self.clients[clientid]
|
||||||
sessionid = self.model["clients"][clientid]["session"]
|
session = self.sessions[client.session] if client.session else None
|
||||||
data["session"] = {"id": sessionid, "name": self.model["sessions"][sessionid]["name"] }
|
if session:
|
||||||
allsessions = { name: { "id": name, "name": self.model["sessions"][name]["name"] } for name in self.model["sessions"] }
|
await self.send_session_view(clientid)
|
||||||
for session in allsessions:
|
else:
|
||||||
if self.model["sessions"][session]["owner"] == clientid:
|
await self.send_lobby_view(clientid)
|
||||||
allsessions[session]["owner"] = True
|
|
||||||
data["allsessions"] = allsessions
|
|
||||||
data["username"] = self.model["clients"][clientid]["username"] if "username" in self.model["clients"][clientid] else "Joe"
|
|
||||||
for socket in self.sockets[clientid]:
|
|
||||||
await socket.send_json(data)
|
|
||||||
|
|
||||||
def save(self):
|
def save(self):
|
||||||
with open(self.filename, "w") as f:
|
with open(self.filename, "w") as f:
|
||||||
json.dump(self.model, f)
|
json.dump(self.to_json(), f)
|
||||||
if not os.path.isdir("backups"):
|
|
||||||
try:
|
|
||||||
os.mkdir("backups")
|
|
||||||
except FileExistsError:
|
|
||||||
print("backups is a file, no directory. Please delete yourself")
|
|
||||||
datestring = datetime.datetime.strftime(datetime.datetime.now(), "%Y-%m-%d-%H%M%S")
|
|
||||||
with open(f"backups/{datestring}_{self.filename}", "w") as f:
|
|
||||||
json.dump(self.model, f)
|
|
||||||
|
|
||||||
def exists_client(self, clientid: str) -> bool:
|
def exists_client(self, clientid: str) -> bool:
|
||||||
return clientid in self.model["clients"]
|
return clientid in self.clients
|
||||||
|
|
||||||
def create_client(self, name="Joe") -> str:
|
def create_client(self, name="Joe") -> str:
|
||||||
if not name:
|
if not name:
|
||||||
raise Exception("Username cannot be empty!")
|
raise Exception("Username cannot be empty!")
|
||||||
clientname = generate_random_id()
|
client = Client()
|
||||||
newclient = {"id": clientname, "username": name, "sessions": []}
|
client.name = name
|
||||||
self.model["clients"][clientname] = newclient
|
self.clients[client.id] = client
|
||||||
return clientname
|
return client.id
|
||||||
|
|
||||||
async def subscribe(self, clientid, socket):
|
async def subscribe(self, clientid, socket):
|
||||||
if not clientid in self.sockets:
|
if not clientid in self.sockets:
|
||||||
@ -139,3 +150,50 @@ class Model(object):
|
|||||||
for client in self.sockets:
|
for client in self.sockets:
|
||||||
if socket in self.sockets[client]:
|
if socket in self.sockets[client]:
|
||||||
self.sockets[client].remove(socket)
|
self.sockets[client].remove(socket)
|
||||||
|
|
||||||
|
class Session:
|
||||||
|
|
||||||
|
def __init__(self, model = None, owner = None, name = None):
|
||||||
|
if model:
|
||||||
|
self.id = model["id"]
|
||||||
|
self.name = model["name"]
|
||||||
|
self.clients = model["clients"]
|
||||||
|
self.owner = model["owner"]
|
||||||
|
elif owner and name:
|
||||||
|
self.id = generate_random_id()
|
||||||
|
self.clients = []
|
||||||
|
self.owner = owner
|
||||||
|
self.name = name
|
||||||
|
else:
|
||||||
|
raise Exception("Illegal session constructor")
|
||||||
|
|
||||||
|
def to_json(self):
|
||||||
|
model = {
|
||||||
|
"id": self.id,
|
||||||
|
"name": self.name,
|
||||||
|
"clients": self.clients,
|
||||||
|
"owner": self.owner,
|
||||||
|
}
|
||||||
|
return model
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
class Client:
|
||||||
|
|
||||||
|
def __init__(self, model = None):
|
||||||
|
if model:
|
||||||
|
self.id = model["id"]
|
||||||
|
self.name = model["name"]
|
||||||
|
self.session = model["session"]
|
||||||
|
else:
|
||||||
|
self.id = generate_random_id()
|
||||||
|
self.name = "Default Client Name"
|
||||||
|
self.session = ""
|
||||||
|
|
||||||
|
def to_json(self):
|
||||||
|
model = {
|
||||||
|
"id": self.id,
|
||||||
|
"name": self.name,
|
||||||
|
"session": self.session,
|
||||||
|
}
|
||||||
|
return model
|
||||||
|
@ -2,36 +2,23 @@ const ws_url = new URL('ws', window.location.href);
|
|||||||
ws_url.protocol = ws_url.protocol.replace('http', 'ws');
|
ws_url.protocol = ws_url.protocol.replace('http', 'ws');
|
||||||
const ws = new WebSocket(ws_url.href);
|
const ws = new WebSocket(ws_url.href);
|
||||||
|
|
||||||
ws.onmessage = function(event) {
|
function draw_lobby(msg) {
|
||||||
const msg = JSON.parse(event.data);
|
|
||||||
|
|
||||||
console.log(msg);
|
|
||||||
|
|
||||||
if (msg.hasOwnProperty('session')) {
|
|
||||||
document.getElementById('active-session').innerText = msg.session["name"];
|
|
||||||
document.getElementById('btn-leave-session').style.display = "inline-block";
|
|
||||||
} else {
|
|
||||||
document.getElementById('active-session').innerText = "None";
|
|
||||||
document.getElementById('btn-leave-session').style.display = "none";
|
|
||||||
}
|
|
||||||
if (msg.hasOwnProperty('username')) {
|
if (msg.hasOwnProperty('username')) {
|
||||||
document.getElementById('label-username').innerText = msg.username;
|
document.getElementById('label-username').innerText = msg.username;
|
||||||
}
|
}
|
||||||
|
if (msg.hasOwnProperty('sessions')) {
|
||||||
|
const sessions = document.getElementById('sessions');
|
||||||
|
|
||||||
if (msg.hasOwnProperty('allsessions')) {
|
while (sessions.children.length) sessions.lastChild.remove();
|
||||||
const all_sessions = document.getElementById('all_sessions');
|
|
||||||
|
|
||||||
while (all_sessions.children.length) all_sessions.lastChild.remove();
|
Object.keys(msg.sessions).forEach( session => {
|
||||||
|
session = msg.sessions[session];
|
||||||
|
var sessionid = session["id"];
|
||||||
|
var sessionname = session["name"];
|
||||||
|
var owned = session["owned"];
|
||||||
|
|
||||||
//for (let session in msg.allsessions) {
|
|
||||||
Object.keys(msg.allsessions).forEach( session => {
|
|
||||||
|
|
||||||
var sessionid = msg.allsessions[session]["id"]
|
|
||||||
var sessionname = msg.allsessions[session]["name"]
|
|
||||||
const tehsession = document.createElement('div');
|
const tehsession = document.createElement('div');
|
||||||
|
|
||||||
const labelname = document.createElement('span');
|
const labelname = document.createElement('span');
|
||||||
owned = ("owner" in msg.allsessions[session]);
|
|
||||||
labelname.innerText = sessionname;
|
labelname.innerText = sessionname;
|
||||||
|
|
||||||
tehsession.appendChild(labelname);
|
tehsession.appendChild(labelname);
|
||||||
@ -99,5 +86,22 @@ ws.onmessage = function(event) {
|
|||||||
|
|
||||||
all_sessions.appendChild(tehsession);
|
all_sessions.appendChild(tehsession);
|
||||||
})
|
})
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
}
|
||||||
|
|
||||||
|
ws.onmessage = function(event) {
|
||||||
|
const msg = JSON.parse(event.data);
|
||||||
|
|
||||||
|
console.log(msg);
|
||||||
|
|
||||||
|
var view = "lobby";
|
||||||
|
if (msg.hasOwnProperty('view')) {
|
||||||
|
view = msg.view;
|
||||||
|
}
|
||||||
|
if (view == "lobby") {
|
||||||
|
draw_lobby(msg);
|
||||||
|
} else if (view == "session") {
|
||||||
|
console.log("cant draw session yet");
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
1
tehsession.json
Normal file
1
tehsession.json
Normal file
@ -0,0 +1 @@
|
|||||||
|
{"sessions": {"2b7jrklcn6eulwbw": {"id": "2b7jrklcn6eulwbw", "name": "die neue session", "clients": ["bkrqopf5j6q3tpta"], "owner": "bkrqopf5j6q3tpta"}}, "clients": {"bkrqopf5j6q3tpta": {"id": "bkrqopf5j6q3tpta", "name": "dominic", "session": ""}}}
|
Loading…
Reference in New Issue
Block a user