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 traceback
|
||||
import urllib.parse
|
||||
import os
|
||||
import json
|
||||
|
||||
from model import Model
|
||||
|
||||
@ -50,7 +52,7 @@ async def handler(request: aiohttp.web.Request):
|
||||
|
||||
data = await request.json()
|
||||
|
||||
print(f'{client=} {data=}')
|
||||
print(f'{method=} {client=} {data=}')
|
||||
|
||||
try:
|
||||
assert method in model.ApiMethod.dict
|
||||
@ -60,7 +62,8 @@ async def handler(request: aiohttp.web.Request):
|
||||
del e # unused?
|
||||
traceback.print_exc()
|
||||
return aiohttp.web.Response(status=400)
|
||||
|
||||
finally:
|
||||
await model.send_state(client)
|
||||
|
||||
@routes.get(CLIENT_REGEX + '/ws')
|
||||
async def _(request: aiohttp.web.Request):
|
||||
@ -110,7 +113,13 @@ if __name__ == '__main__':
|
||||
app = aiohttp.web.Application()
|
||||
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)
|
||||
app['model'].save()
|
||||
|
190
model.py
190
model.py
@ -22,28 +22,22 @@ class Model(object):
|
||||
def __contains__(self, item):
|
||||
return item in self.dict
|
||||
|
||||
def __init__(self, filename="tehmodel.json"):
|
||||
self.sockets = {} # mapping: client -> socket
|
||||
self.filename = filename
|
||||
self.model = None
|
||||
if os.path.isfile(filename):
|
||||
with open(filename) as f:
|
||||
try:
|
||||
self.model = json.load(f)
|
||||
except:
|
||||
self.model = {}
|
||||
else:
|
||||
self.model = {}
|
||||
self.assert_model()
|
||||
def __init__(self, model = {}):
|
||||
if "sessions" not in model:
|
||||
model["sessions"] = []
|
||||
if "clients" not in model:
|
||||
model["clients"] = []
|
||||
self.sockets = {} # mapping: clientid -> sockets
|
||||
self.sessions = { session: Session(model = model["sessions"][session]) for session in model["sessions"] }
|
||||
self.clients = { client: Client(model = model["clients"][client]) for client in model["clients"] }
|
||||
self.filename = "tehsession.json"
|
||||
|
||||
def assert_model(self):
|
||||
if not "clients" in self.model:
|
||||
self.model["clients"] = {}
|
||||
if not "sessions" in self.model:
|
||||
self.model["sessions"] = {}
|
||||
for session in self.model["sessions"]:
|
||||
if not "name" in self.model["sessions"][session]:
|
||||
self.model["sessions"][session]["name"] = "Defaultname"
|
||||
def to_json(self):
|
||||
model = {
|
||||
"sessions": {session: self.sessions[session].to_json() for session in self.sessions },
|
||||
"clients": {client: self.clients[client].to_json() for client in self.clients },
|
||||
}
|
||||
return model
|
||||
|
||||
@ApiMethod
|
||||
async def test_api(self, clientid):
|
||||
@ -55,79 +49,96 @@ class Model(object):
|
||||
|
||||
@ApiMethod
|
||||
async def change_username(self, clientid, username) -> str:
|
||||
self.model["clients"][clientid]["username"] = username
|
||||
await self.send_state(clientid)
|
||||
self.clients[clientid].name = username
|
||||
|
||||
@ApiMethod
|
||||
async def create_session(self, clientid, sessionname) -> str:
|
||||
if not sessionname:
|
||||
raise Exception("Cant be empty!")
|
||||
sessionid = generate_random_id()
|
||||
newsession = {"id": sessionid, "owner": clientid, "clients": [], "name": sessionname }
|
||||
self.model["sessions"][sessionid] = newsession
|
||||
await self.send_state(clientid)
|
||||
raise Exception(f"Sessionname cant be empty!")
|
||||
session = Session(name = sessionname, owner = clientid)
|
||||
self.sessions[session.id] = session
|
||||
print("create_session was called")
|
||||
|
||||
@ApiMethod
|
||||
async def change_sessionname(self, clientid, sessionid, sessionname) -> str:
|
||||
if not sessionname:
|
||||
raise Exception("Cant be empty!")
|
||||
if self.model["sessions"][sessionid]["owner"] == clientid:
|
||||
self.model["sessions"][sessionid]["name"] = sessionname
|
||||
await self.send_state(clientid)
|
||||
session = self.sessions[sessionid]
|
||||
if not (session.owner == clientid):
|
||||
raise Exception("Ownly owner can change sessionname")
|
||||
session.name = sessionname
|
||||
|
||||
@ApiMethod
|
||||
async def leave_session(self, clientid):
|
||||
sessionid = self.model["clients"][clientid]["session"]
|
||||
del self.model["clients"][clientid]["session"]
|
||||
self.model["sessions"][sessionid]["clients"].remove(clientid)
|
||||
await self.send_state(clientid)
|
||||
client = self.clients[clientid]
|
||||
sessionid = client.session
|
||||
if sessionid:
|
||||
session = self.sessions[sessionid]
|
||||
session.clients.remove(clientid)
|
||||
self.clients[clientid].session = ""
|
||||
|
||||
@ApiMethod
|
||||
async def join_session(self, clientid, sessionid):
|
||||
if sessionid in self.model["sessions"]:
|
||||
# session exists
|
||||
self.model["clients"][clientid]["session"] = sessionid
|
||||
if not clientid in self.model["sessions"][sessionid]["clients"]:
|
||||
self.model["sessions"][sessionid]["clients"].append(clientid)
|
||||
await self.send_state(clientid)
|
||||
client = self.clients[clientid]
|
||||
old_sessionid = client.session
|
||||
# leave old session
|
||||
if old_sessionid:
|
||||
old_session = self.sessions[old_sessionid]
|
||||
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):
|
||||
# TODO: compute state, send to client
|
||||
data = {}
|
||||
if "session" in self.model["clients"][clientid]:
|
||||
sessionid = self.model["clients"][clientid]["session"]
|
||||
data["session"] = {"id": sessionid, "name": self.model["sessions"][sessionid]["name"] }
|
||||
allsessions = { name: { "id": name, "name": self.model["sessions"][name]["name"] } for name in self.model["sessions"] }
|
||||
for session in allsessions:
|
||||
if self.model["sessions"][session]["owner"] == 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)
|
||||
client = self.clients[clientid]
|
||||
session = self.sessions[client.session] if client.session else None
|
||||
if session:
|
||||
await self.send_session_view(clientid)
|
||||
else:
|
||||
await self.send_lobby_view(clientid)
|
||||
|
||||
def save(self):
|
||||
with open(self.filename, "w") as f:
|
||||
json.dump(self.model, 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)
|
||||
json.dump(self.to_json(), f)
|
||||
|
||||
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:
|
||||
if not name:
|
||||
raise Exception("Username cannot be empty!")
|
||||
clientname = generate_random_id()
|
||||
newclient = {"id": clientname, "username": name, "sessions": []}
|
||||
self.model["clients"][clientname] = newclient
|
||||
return clientname
|
||||
client = Client()
|
||||
client.name = name
|
||||
self.clients[client.id] = client
|
||||
return client.id
|
||||
|
||||
async def subscribe(self, clientid, socket):
|
||||
if not clientid in self.sockets:
|
||||
@ -139,3 +150,50 @@ class Model(object):
|
||||
for client in self.sockets:
|
||||
if socket in self.sockets[client]:
|
||||
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');
|
||||
const ws = new WebSocket(ws_url.href);
|
||||
|
||||
ws.onmessage = function(event) {
|
||||
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";
|
||||
}
|
||||
function draw_lobby(msg) {
|
||||
if (msg.hasOwnProperty('username')) {
|
||||
document.getElementById('label-username').innerText = msg.username;
|
||||
}
|
||||
if (msg.hasOwnProperty('sessions')) {
|
||||
const sessions = document.getElementById('sessions');
|
||||
|
||||
if (msg.hasOwnProperty('allsessions')) {
|
||||
const all_sessions = document.getElementById('all_sessions');
|
||||
while (sessions.children.length) sessions.lastChild.remove();
|
||||
|
||||
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 labelname = document.createElement('span');
|
||||
owned = ("owner" in msg.allsessions[session]);
|
||||
labelname.innerText = sessionname;
|
||||
|
||||
tehsession.appendChild(labelname);
|
||||
@ -99,5 +86,22 @@ ws.onmessage = function(event) {
|
||||
|
||||
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