Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit fb27c7c

Browse files
Logs & bug fixes
1 parent 4c59a2e commit fb27c7c

File tree

6 files changed

+147
-30
lines changed

6 files changed

+147
-30
lines changed

main.py

Lines changed: 94 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
import time
44
import os
55
import json
6+
from urllib.parse import unquote
67

78
hostName = "0.0.0.0"
89
serverPort = 11112
@@ -33,6 +34,7 @@ class Game:
3334
def __init__(self):
3435
self.history = []
3536
self.status = GameStatus.WAITING_TO_START
37+
self.activePlayer = None
3638
def get(self, path, query, gameno):
3739
if path == "/check":
3840
# Check for game status openings
@@ -63,12 +65,14 @@ def get(self, path, query, gameno):
6365
return {
6466
"status": 303,
6567
"headers": {
66-
"Location": f"/"
68+
"Location": f"/?" + query.orig
6769
},
6870
"content": ""
6971
}
7072
elif path == "/draw":
7173
if self.status == GameStatus.NEEDS_PICTURE:
74+
if self.activePlayer == None:
75+
self.activePlayer = unquote(query.orig.split("=")[-1])
7276
self.status = GameStatus.CREATING_PICTURE
7377
return {
7478
"status": 200,
@@ -77,6 +81,15 @@ def get(self, path, query, gameno):
7781
},
7882
"content": read_file("public_files/draw.html")
7983
}
84+
elif self.status == GameStatus.CREATING_PICTURE:
85+
if self.activePlayer == unquote(query.orig.split("=")[-1]):
86+
return {
87+
"status": 200,
88+
"headers": {
89+
"Content-Type": "text/html"
90+
},
91+
"content": read_file("public_files/draw.html")
92+
}
8093
return {
8194
"status": 303,
8295
"headers": {
@@ -86,6 +99,8 @@ def get(self, path, query, gameno):
8699
}
87100
elif path == "/word":
88101
if self.status == GameStatus.NEEDS_WORD:
102+
if self.activePlayer == None:
103+
self.activePlayer = unquote(query.orig.split("=")[-1])
89104
self.status = GameStatus.CREATING_WORD
90105
return {
91106
"status": 200,
@@ -94,7 +109,9 @@ def get(self, path, query, gameno):
94109
},
95110
"content": read_file("public_files/word.html")
96111
}
97-
if self.status == GameStatus.WAITING_FOR_FIRST_WORD:
112+
elif self.status == GameStatus.WAITING_FOR_FIRST_WORD:
113+
if self.activePlayer == None:
114+
self.activePlayer = unquote(query.orig.split("=")[-1])
98115
self.status = GameStatus.CREATING_WORD
99116
return {
100117
"status": 200,
@@ -103,6 +120,23 @@ def get(self, path, query, gameno):
103120
},
104121
"content": read_file("public_files/word.html").replace("/*X", "")
105122
}
123+
elif self.status == GameStatus.CREATING_WORD:
124+
if self.activePlayer == unquote(query.orig.split("=")[-1]):
125+
if len(self.history) == 0:
126+
return {
127+
"status": 200,
128+
"headers": {
129+
"Content-Type": "text/html"
130+
},
131+
"content": read_file("public_files/word.html").replace("/*X", "")
132+
}
133+
return {
134+
"status": 200,
135+
"headers": {
136+
"Content-Type": "text/html"
137+
},
138+
"content": read_file("public_files/word.html")
139+
}
106140
return {
107141
"status": 303,
108142
"headers": {
@@ -121,14 +155,15 @@ def get(self, path, query, gameno):
121155
elif path == "/last_photo.svg":
122156
try:
123157
r = """<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 520 520">
124-
\t<style>
125-
\t\tpath{fill:none;stroke:black;stroke-width:1px;stroke-linecap:round;stroke-linejoin:round;}</style>
126-
\t<g style="transform: translate(10px, 10px);">"""
158+
\t<style>
159+
\t\tpath{fill:none;stroke:black;stroke-width:1px;stroke-linecap:round;stroke-linejoin:round;}</style>
160+
\t<g style="transform: translate(10px, 10px);">"""
127161
img = self.history[-1]["image"]
128162
for i in img:
129163
r += f"""\t\t<path d="{i}" />"""
164+
# """
130165
r += """\t</g>
131-
</svg>"""
166+
</svg>"""
132167
return {
133168
"status": 200,
134169
"headers": {
@@ -153,7 +188,8 @@ def get(self, path, query, gameno):
153188
def post(self, path, body, gameno):
154189
if path == "/submit_drawing":
155190
self.history[-1]["image"] = json.loads(body)["p"]
156-
self.history[-1]["imageuser"] = json.loads(body)["user"]
191+
self.history[-1]["imageuser"] = self.activePlayer
192+
self.activePlayer = None
157193
self.status = GameStatus.NEEDS_WORD
158194
return {
159195
"status": 200,
@@ -163,10 +199,11 @@ def post(self, path, body, gameno):
163199
elif path == "/submit_word":
164200
self.history.append({
165201
"word": json.loads(body)["word"],
166-
"worduser": json.loads(body)["user"],
202+
"worduser": self.activePlayer,
167203
"image": [],
168204
"imageuser": ""
169205
})
206+
self.activePlayer = None
170207
self.status = GameStatus.NEEDS_PICTURE
171208
return {
172209
"status": 200,
@@ -182,19 +219,21 @@ def post(self, path, body, gameno):
182219
def can_join(self, name):
183220
# Name is not in the last two entries
184221
if len(self.history) == 0: return True
185-
if self.history[-1]["worduser"] == name: return False
186-
if self.history[-1]["imageuser"] == name: return False
187-
if len(self.history) > 1 and len(users) > 2:
188-
if self.history[-2]["worduser"] == name: return False
189-
if self.history[-2]["imageuser"] == name: return False
222+
if self.history[-1]["imageuser"] == "":
223+
if self.history[-1]["worduser"] == name: return False
224+
if len(self.history) > 1 and len(users) > 2:
225+
if self.history[-2]["imageuser"] == name: return False
226+
else:
227+
if self.history[-1]["imageuser"] == name: return False
228+
if self.history[-1]["worduser"] == name: return False
190229
return True
191230
def resultHTML(self):
192231
entries = []
193232
for i in self.history:
194233
paths = []
195234
for j in i["image"]:
196235
paths.append(f"<path d=\"{j}\" fill=\"none\" stroke=\"black\" stroke-width=\"1px\" />")
197-
entries.append(f"<h1>{i['word']}<span style='font-size: 1rem;'> by {i['worduser']}</span></h1><div>Drawing by {i['imageuser']}:</div><svg viewBox='0 0 520 520'>{''.join(paths)}</svg>")
236+
entries.append(f"<div>Word by {i['worduser']}</div><h1 style='font-size: 1em; border-left: 2px solid black; margin: 1em; padding: 1em;'>{i['word']}</h1><div>Drawing by {i['imageuser']}:</div><svg viewBox='0 0 520 520'>{''.join(paths)}</svg>")
198237
return ''.join(entries)
199238
def __repr__(self) -> str:
200239
entries = []
@@ -256,16 +295,40 @@ def get(path, query: URLQuery):
256295
if query.get("name") not in users:
257296
users.append(query.get("name"))
258297
activeGames.append(Game())
298+
hasAnyActiveGames = False
259299
for g in range(len(activeGames)):
260-
if activeGames[g].can_join(query.get("name")):
261-
if activeGames[g].status in [GameStatus.WAITING_FOR_FIRST_WORD, GameStatus.NEEDS_PICTURE, GameStatus.NEEDS_WORD]:
300+
if activeGames[g].status in [GameStatus.WAITING_FOR_FIRST_WORD, GameStatus.NEEDS_PICTURE, GameStatus.NEEDS_WORD]:
301+
if activeGames[g].can_join(query.get("name")):
262302
return {
263303
"status": 303,
264304
"headers": {
265305
"Location": f"/{g}/check?" + query.orig
266306
},
267307
"content": ""
268308
}
309+
if activeGames[g].status not in [GameStatus.WAITING_TO_START]:
310+
hasAnyActiveGames = True
311+
if not hasAnyActiveGames:
312+
return {
313+
"status": 200,
314+
"headers": {
315+
"Content-Type": "text/html"
316+
},
317+
"content": (f"""<!DOCTYPE html>
318+
<html>
319+
\t<head>
320+
\t\t<title>Waiting</title>
321+
\t\t<script>setTimeout(() => location.reload(), Math.random() * 5000)</script>
322+
\t\t<link href="main.css" rel="stylesheet" type="text/css" />
323+
\t\t<link rel="icon" type="image/x-icon" href="wait.ico">
324+
\t</head>
325+
\t<body>
326+
\t\tWaiting for the game to start...<br><br>
327+
\t\t<button onclick="location.reload()">Refresh</button>
328+
\t\t<br><p>Player list:</p><ul>{''.join(['<li>'+x+'</li>' for x in users])}</ul>
329+
\t</body>
330+
</html>""")
331+
}
269332
# No available games...
270333
return {
271334
"status": 200,
@@ -276,7 +339,7 @@ def get(path, query: URLQuery):
276339
<html>
277340
\t<head>
278341
\t\t<title>Waiting</title>
279-
\t\t<script>setTimeout(() => { location.reload() }, Math.random() * 20000)</script>
342+
\t\t<script>setTimeout(() => { location.reload() }, Math.random() * 5000)</script>
280343
\t\t<link href="main.css" rel="stylesheet" type="text/css" />
281344
\t\t<link rel="icon" type="image/x-icon" href="wait.ico">
282345
\t</head>
@@ -373,6 +436,8 @@ def getChar():
373436
def async_get_chars():
374437
while running:
375438
chars.append(input())
439+
if "x" in [x.lower() for x in chars]:
440+
return;
376441
threading.Thread(target=async_get_chars, name="pygame_get_chars_thread", args=[]).start()
377442
# Main loop
378443
running = True
@@ -381,7 +446,7 @@ def async_get_chars():
381446
res = ""
382447
# LIST OF GAMES
383448
for i in range(len(activeGames)):
384-
res += f"({i + 1} d/i/r) Game {i + 1} status: {activeGames[i].status} ({['Waiting to start', 'Waiting for 1st word', 'Needs picture', 'Creating picture', 'Needs word', 'Creating word'][activeGames[i].status]})\n"
449+
res += f"({i + 1} d/i/r) Game {i + 1} status: {activeGames[i].status} ({['Waiting to start', 'Waiting for 1st word', 'Needs picture', 'Creating picture', 'Needs word', 'Creating word'][activeGames[i].status]}) player: {activeGames[i].activePlayer}\n"
385450
if curchar == str(i + 1) + "d":
386451
activeGames[i].status -= 1
387452
if activeGames[i].status < 0: activeGames[i].status += 4
@@ -407,7 +472,9 @@ def async_get_chars():
407472
if curchar == "u" + str(u + 1):
408473
users.pop(u)
409474
# CLOSE WINDOW MESSAGE
410-
res += f"Press Ctrl-C then Enter to stop the server\n"
475+
res += f"(X) Stop the server\n"
476+
if curchar == "x":
477+
running = False
411478
# CLOSE WINDOW MESSAGE
412479
res += f"(N) New game\n"
413480
if curchar == "n":
@@ -441,7 +508,14 @@ def async_get_chars():
441508
webServer.server_close()
442509
print("Server stopped")
443510
print("Results:")
511+
jsonr = []
444512
for g in range(len(activeGames)):
445513
res = repr(activeGames[g])
446514
print(f"\nGame {g}:{res}")
447-
print("\nPress Enter to exit...")
515+
jsonr.append(activeGames[g].history)
516+
n = 1
517+
while os.path.isfile(f"logs/game_{n}.json"): n += 1
518+
os.system("mkdir -p logs")
519+
f = open(f"logs/game_{n}.json", "w")
520+
f.write(json.dumps(jsonr))
521+
f.close()

public_files/draw.html

Lines changed: 5 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@
1313
flex-direction: column;
1414
}
1515
div.window {
16-
flex-grow: 3;
16+
height: 500px;
1717
display: flex;
1818
}
1919
#theSVG {
@@ -85,7 +85,6 @@
8585
<option selected>Draw</option>
8686
</select>
8787
</span>
88-
<button onclick="location.replace('draw_mobile.html')" id="mobilebutton">Switch to mobile version</button>
8988
<br>Click and drag to draw. Select line mode to draw lines.
9089
</div>
9190
<script>
@@ -141,19 +140,19 @@
141140
x.setRequestHeader("Content-Type", "application/json")
142141
x.addEventListener("loadend", (e) => { location.replace("/" + location.search) })
143142
x.send(JSON.stringify({
144-
p: paths,
145-
user: location.search.split("=")[1]
143+
p: paths/*,
144+
user: decodeURIComponent(location.search.split("=")[1])*/
146145
}))
147146
}
148147
var x = new XMLHttpRequest()
149148
x.open("GET", "last_word")
150149
x.addEventListener("loadend", (e) => { g("#word").textContent = e.target.responseText })
151150
x.send()
152-
if(window.matchMedia("(pointer: none)").matches) {
151+
/* if (window.matchMedia("(pointer: none)").matches) {
153152
if (confirm("You're on a mobile device. Switch to mobile drawing version?")) {
154153
location.replace("draw_mobile.html")
155154
}
156-
}
155+
} */
157156
// Prevent scrolling on mobile
158157
var drawrect = g("#theSVG")
159158
drawrect.addEventListener("touchstart", function(e){

public_files/login.html

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,10 +6,14 @@
66
</head>
77
<body>
88
<h1>Login</h1>
9-
<input type="text" id="word">
9+
<p>Enter your name:</p>
10+
<input type="text" id="word" enterkeyhint="send">
1011
<button onclick="submit()">Submit</button>
1112
<script>
1213
function g(css) { return document.querySelector(css); }
14+
g("#word").addEventListener("keydown", (e) => {
15+
if (e.key == "Enter") submit()
16+
})
1317
function submit() {
1418
location.replace(`/?name=${g("#word").value}`)
1519
}

public_files/main.css

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,10 @@ svg {
22
max-width: 30em;
33
height: auto;
44
}
5+
img {
6+
max-height: 50vh;
7+
width: auto;
8+
}
59
@media screen and (max-width: 600px) {
610
:root {
711
font-size: 5em;

public_files/view.html

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
<!DOCTYPE html>
2+
<html>
3+
<head>
4+
<title>Results</title>
5+
<link href="main.css" rel="stylesheet" type="text/css" />
6+
</head>
7+
<body>
8+
<h1>Result Viewer</h1>
9+
<p><input type="file"><button onclick="this.previousElementSibling.files[0].text().then(addText)">Upload</button></p>
10+
<div id="r"></div>
11+
<script>window.addEventListener("error", (e) => alert(`${e.message}`))</script>
12+
<script>
13+
function addText(t) {
14+
var r = ""
15+
var games = JSON.parse(t)
16+
for (var gameno = 0; gameno < games.length; gameno++) {
17+
var entries = games[gameno]
18+
r += `<h2 style='background:black;color:white;margin:1em;padding:1em;border-radius:1em;'><i>Game #${gameno + 1}</i></h2>`
19+
for (var entryno = 0; entryno < entries.length; entryno++) {
20+
var entry = entries[entryno]
21+
// entry is of type: { word: ..., worduser: ..., image: [...], imageuser: ... }
22+
var paths = []
23+
for (var pathno = 0; pathno < entry.image.length; pathno++) {
24+
paths.push(`<path d="${entry.image[pathno]}" fill="none" stroke="black" stroke-width="1px" />`)
25+
}
26+
r += `<div>Word by ${entry.worduser}</div><h1 style='font-size: 1em; border-left: 2px solid black; margin: 1em; padding: 1em;'>${entry.word}</h1><div>Drawing by ${entry.imageuser}:</div><svg viewBox='0 0 520 520'>${paths.join('')}</svg>`
27+
}
28+
}
29+
document.querySelector("#r").innerHTML = r
30+
}
31+
</script>
32+
</body>
33+
</html>

public_files/word.html

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
<html>
33
<head>
44
<title>Voting</title>
5-
<link href="main.css" rel="stylesheet" type="text/css" />
5+
<link href="/main.css" rel="stylesheet" type="text/css" />
66
<link rel="icon" type="image/x-icon" href="word.ico">
77
</head>
88
<body>
@@ -29,10 +29,13 @@
2929
x.setRequestHeader("Content-Type", "application/json")
3030
x.addEventListener("loadend", (e) => { window.location.replace("/" + location.search) })
3131
x.send(JSON.stringify({
32-
word: g("#word").value,
33-
user: location.search.split("=")[1]
32+
word: g("#word").value/*,
33+
user: decodeURIComponent(location.search.split("=")[1])*/
3434
}))
3535
}
36+
g("#word").addEventListener("keydown", (e) => {
37+
if (e.key == "Enter") submit()
38+
})
3639
</script>
3740
</body>
3841
</html>

0 commit comments

Comments
 (0)