3
3
import time
4
4
import os
5
5
import json
6
+ from urllib .parse import unquote
6
7
7
8
hostName = "0.0.0.0"
8
9
serverPort = 11112
@@ -33,6 +34,7 @@ class Game:
33
34
def __init__ (self ):
34
35
self .history = []
35
36
self .status = GameStatus .WAITING_TO_START
37
+ self .activePlayer = None
36
38
def get (self , path , query , gameno ):
37
39
if path == "/check" :
38
40
# Check for game status openings
@@ -63,12 +65,14 @@ def get(self, path, query, gameno):
63
65
return {
64
66
"status" : 303 ,
65
67
"headers" : {
66
- "Location" : f"/"
68
+ "Location" : f"/?" + query . orig
67
69
},
68
70
"content" : ""
69
71
}
70
72
elif path == "/draw" :
71
73
if self .status == GameStatus .NEEDS_PICTURE :
74
+ if self .activePlayer == None :
75
+ self .activePlayer = unquote (query .orig .split ("=" )[- 1 ])
72
76
self .status = GameStatus .CREATING_PICTURE
73
77
return {
74
78
"status" : 200 ,
@@ -77,6 +81,15 @@ def get(self, path, query, gameno):
77
81
},
78
82
"content" : read_file ("public_files/draw.html" )
79
83
}
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
+ }
80
93
return {
81
94
"status" : 303 ,
82
95
"headers" : {
@@ -86,6 +99,8 @@ def get(self, path, query, gameno):
86
99
}
87
100
elif path == "/word" :
88
101
if self .status == GameStatus .NEEDS_WORD :
102
+ if self .activePlayer == None :
103
+ self .activePlayer = unquote (query .orig .split ("=" )[- 1 ])
89
104
self .status = GameStatus .CREATING_WORD
90
105
return {
91
106
"status" : 200 ,
@@ -94,7 +109,9 @@ def get(self, path, query, gameno):
94
109
},
95
110
"content" : read_file ("public_files/word.html" )
96
111
}
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 ])
98
115
self .status = GameStatus .CREATING_WORD
99
116
return {
100
117
"status" : 200 ,
@@ -103,6 +120,23 @@ def get(self, path, query, gameno):
103
120
},
104
121
"content" : read_file ("public_files/word.html" ).replace ("/*X" , "" )
105
122
}
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
+ }
106
140
return {
107
141
"status" : 303 ,
108
142
"headers" : {
@@ -121,14 +155,15 @@ def get(self, path, query, gameno):
121
155
elif path == "/last_photo.svg" :
122
156
try :
123
157
r = """<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 520 520">
124
- \t <style>
125
- \t \t path{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 \t path{fill:none;stroke:black;stroke-width:1px;stroke-linecap:round;stroke-linejoin:round;}</style>
160
+ \t <g style="transform: translate(10px, 10px);">"""
127
161
img = self .history [- 1 ]["image" ]
128
162
for i in img :
129
163
r += f"""\t \t <path d="{ i } " />"""
164
+ # """
130
165
r += """\t </g>
131
- </svg>"""
166
+ </svg>"""
132
167
return {
133
168
"status" : 200 ,
134
169
"headers" : {
@@ -153,7 +188,8 @@ def get(self, path, query, gameno):
153
188
def post (self , path , body , gameno ):
154
189
if path == "/submit_drawing" :
155
190
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
157
193
self .status = GameStatus .NEEDS_WORD
158
194
return {
159
195
"status" : 200 ,
@@ -163,10 +199,11 @@ def post(self, path, body, gameno):
163
199
elif path == "/submit_word" :
164
200
self .history .append ({
165
201
"word" : json .loads (body )["word" ],
166
- "worduser" : json . loads ( body )[ "user" ] ,
202
+ "worduser" : self . activePlayer ,
167
203
"image" : [],
168
204
"imageuser" : ""
169
205
})
206
+ self .activePlayer = None
170
207
self .status = GameStatus .NEEDS_PICTURE
171
208
return {
172
209
"status" : 200 ,
@@ -182,19 +219,21 @@ def post(self, path, body, gameno):
182
219
def can_join (self , name ):
183
220
# Name is not in the last two entries
184
221
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
190
229
return True
191
230
def resultHTML (self ):
192
231
entries = []
193
232
for i in self .history :
194
233
paths = []
195
234
for j in i ["image" ]:
196
235
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>" )
198
237
return '' .join (entries )
199
238
def __repr__ (self ) -> str :
200
239
entries = []
@@ -256,16 +295,40 @@ def get(path, query: URLQuery):
256
295
if query .get ("name" ) not in users :
257
296
users .append (query .get ("name" ))
258
297
activeGames .append (Game ())
298
+ hasAnyActiveGames = False
259
299
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" )) :
262
302
return {
263
303
"status" : 303 ,
264
304
"headers" : {
265
305
"Location" : f"/{ g } /check?" + query .orig
266
306
},
267
307
"content" : ""
268
308
}
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 \t Waiting 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
+ }
269
332
# No available games...
270
333
return {
271
334
"status" : 200 ,
@@ -276,7 +339,7 @@ def get(path, query: URLQuery):
276
339
<html>
277
340
\t <head>
278
341
\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>
280
343
\t \t <link href="main.css" rel="stylesheet" type="text/css" />
281
344
\t \t <link rel="icon" type="image/x-icon" href="wait.ico">
282
345
\t </head>
@@ -373,6 +436,8 @@ def getChar():
373
436
def async_get_chars ():
374
437
while running :
375
438
chars .append (input ())
439
+ if "x" in [x .lower () for x in chars ]:
440
+ return ;
376
441
threading .Thread (target = async_get_chars , name = "pygame_get_chars_thread" , args = []).start ()
377
442
# Main loop
378
443
running = True
@@ -381,7 +446,7 @@ def async_get_chars():
381
446
res = ""
382
447
# LIST OF GAMES
383
448
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 "
385
450
if curchar == str (i + 1 ) + "d" :
386
451
activeGames [i ].status -= 1
387
452
if activeGames [i ].status < 0 : activeGames [i ].status += 4
@@ -407,7 +472,9 @@ def async_get_chars():
407
472
if curchar == "u" + str (u + 1 ):
408
473
users .pop (u )
409
474
# 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
411
478
# CLOSE WINDOW MESSAGE
412
479
res += f"(N) New game\n "
413
480
if curchar == "n" :
@@ -441,7 +508,14 @@ def async_get_chars():
441
508
webServer .server_close ()
442
509
print ("Server stopped" )
443
510
print ("Results:" )
511
+ jsonr = []
444
512
for g in range (len (activeGames )):
445
513
res = repr (activeGames [g ])
446
514
print (f"\n Game { g } :{ res } " )
447
- print ("\n Press 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 ()
0 commit comments