From 957c1e9450df5a41b129fd9abf54852ae7e44948 Mon Sep 17 00:00:00 2001
From: Nils G <nils.gondermann@ruhr-uni-bochum.de>
Date: Sun, 19 Apr 2020 13:38:54 +0200
Subject: [PATCH] Added /game/roles API

---
 controllers/game.py          | 57 +++++++++++++++++++++++++++++++++++-
 modules/room_util.py         |  7 +++--
 views/game/index.html        |  1 +
 views/include/websocket.html |  8 ++++-
 4 files changed, 69 insertions(+), 4 deletions(-)

diff --git a/controllers/game.py b/controllers/game.py
index 774f25d..d91ff71 100644
--- a/controllers/game.py
+++ b/controllers/game.py
@@ -1,6 +1,6 @@
 from parameter_util import JSON_BODY, JSON_CONTAINS
 from http_util import FAIL, CODE_JSON, CODE_MISSING, CODE_SEMANTIC, CODE_GONE, CODE_CONFLICT
-from room_util import ROOM_GET
+from room_util import ROOM_GET, PLAYERS_GET
 from websocket_util import WEBSOCKET_SEND
 import base64
 
@@ -39,3 +39,58 @@ def start():
 
     json_response = {"status": "success"}
     return(response.json(json_response))
+
+
+def roles():
+    parameters = JSON_BODY(request)
+
+    if parameters == None:
+        return(FAIL(CODE_JSON))
+
+    if not JSON_CONTAINS(parameters, [('room_id', int), ('room_pw', str), ('user_roles', dict)]):
+        return(FAIL(CODE_MISSING))
+
+    room_id = parameters['room_id']
+    room_pw = parameters['room_pw']
+    user_roles = parameters['user_roles']
+
+    room_record = ROOM_GET(room_id, room_pw)
+
+    if not room_record:
+        return(FAIL(CODE_SEMANTIC))
+
+    if room_record.closed:
+        return(FAIL(CODE_GONE))
+
+    players = PLAYERS_GET(room_record, True)
+    server_rolechange = {}
+    client_rolechange = {}
+
+    for player in players:
+        playerid = str(player["id"])
+
+        if not playerid in user_roles:
+            continue
+
+        definition = user_roles[playerid]
+
+        if not isinstance(definition, dict):
+            return(FAIL(CODE_MISSING))
+
+        if not JSON_CONTAINS(definition, [("role", str)]):
+            return(FAIL(CODE_MISSING))
+
+        client_rolechange[player["uid"]] = {"role": definition["role"]}
+
+        if player["role"] != definition["role"]:
+            server_rolechange[player["uid"]] = definition["role"]
+
+    for uid in server_rolechange:
+        db(db.Player.id == uid).update(role=server_rolechange[uid])
+
+    websocket_response = base64.standard_b64encode(json.dumps(client_rolechange).encode("ascii")).decode("utf-8")
+
+    WEBSOCKET_SEND(room_record, "role", websocket_response)
+
+    json_response = {"status": "success"}
+    return(response.json(json_response))
diff --git a/modules/room_util.py b/modules/room_util.py
index 2281b46..071ea42 100644
--- a/modules/room_util.py
+++ b/modules/room_util.py
@@ -18,13 +18,16 @@ def ROOM_GET_CODE(_code):
     return(room_record)
 
 
-def PLAYERS_GET(_room):
+def PLAYERS_GET(_room, _uid=False):
     rows = current.db(current.db.Player.room_id == _room.id).select(orderby=current.db.Player.id)
 
     players = []
     player_id = 0
     for row in rows:
-        players.append({"id": player_id, "name": row.name, "role": row.role})
+        obj = {"id": player_id, "name": row.name, "role": row.role}
+        if _uid:
+            obj["uid"] = row.id
+        players.append(obj)
         player_id = player_id + 1
 
     return(players)
diff --git a/views/game/index.html b/views/game/index.html
index f02631f..6d1720a 100644
--- a/views/game/index.html
+++ b/views/game/index.html
@@ -15,6 +15,7 @@
 
 <script type="text/javascript">
     var name = "{{=player_record.name}}";
+    var playerid = "{{=player_record.id}}";
     var role = "{{=player_record.role}}";
     var roles = JSON.parse(atob('{{=XML(room_record.roles)}}'));
 </script>
diff --git a/views/include/websocket.html b/views/include/websocket.html
index 3092c5e..4acf400 100644
--- a/views/include/websocket.html
+++ b/views/include/websocket.html
@@ -20,12 +20,18 @@
                 switch(type) {
                     case "roles":
                         roles = JSON.parse(atob(data));
-                        render(name, role, roles);
+                        break;
+                    case "role":
+                        role_definition = JSON.parse(atob(data));
+                        if(playerid in role_definition) {
+                            role = role_definition[playerid]["role"];
+                        }
                         break;
                     default:
                         set_error("{{=T('Invalid WebSocket data received')}}: '" + type + "'");
                         return;
                 }
+                render(name, role, roles);
 
             };
             ws.onerror = function(e) {
-- 
GitLab