5 from datetime
import date
8 # Create a Socket.IO server (CORS arg required on server, not locally)
9 sio
= socketio
.Server()
10 #sio = socketio.Server(cors_allowed_origins='URL or *')
12 RPSLS_PATH
= './' #edit if launched from elsewhere
13 DB_PATH
= RPSLS_PATH
+ 'db/rpsls.sqlite'
15 searching
= {} #someone seeks a game? (uid + sid)
16 connected
= {} #map uid --> sid (seek stage)
20 """ Triggered at page reload or tab close """
21 global connected
, searching
23 key_idx
= list(connected
.values()).index(sid
)
24 del connected
[list(connected
.keys())[key_idx
]]
26 # If the user didn't seek, no key to find
28 if searching
and searching
["sid"] == sid
:
33 """ When user sends name from /login page """
34 if not re
.match(r
"^[a-zA-Z]{3,}$", data
):
35 sio
.emit("login", {"err": "Name: letters only"}
, room
=sid
)
37 con
= sqlite3
.connect(DB_PATH
)
41 # Always try to insert (new) Users row
42 cur
.execute("insert into Users (name) values (?)", (data
,))
44 except sqlite3
.IntegrityError
as err
:
45 # If fails: user already exists, find its ID
46 if str(err
) == "UNIQUE constraint failed: Users.name":
47 cur
.execute("select id from Users where name = ?", (data
,))
48 uid
= cur
.fetchone()[0]
53 sio
.emit("login", {"name": data, "uid": uid}
, room
=sid
)
57 """ When user click on 'Play' button """
58 global connected
, searching
59 connected
[data
["uid"]] = sid
61 searching
= {"uid": data["uid"], "sid": sid, "name": data["name"]}
63 # Active seek pending: create game
66 con
= sqlite3
.connect(DB_PATH
)
68 today
= (date
.today(),)
69 cur
.execute("insert into Games (created) values (?)", today
)
71 # To room == sid, opponent is me. To my room, it's him/her
73 {"gid":gid, "oppid":opponent["uid"], "oppname":opponent["name"]}
,
76 {"gid":gid, "oppid":data["uid"], "oppname":data["name"]}
,
78 id_list
= [(data
["uid"],gid
), (opponent
["uid"],gid
)]
79 cur
.executemany("insert into Players (uid,gid) values (?,?)", id_list
)
85 """ New move to DB + transmit to opponent """
86 sio
.emit("move", data
, room
=connected
[data
["oppid"]])
87 con
= sqlite3
.connect(DB_PATH
)
89 cur
.execute("insert into Moves (uid,gid,choice,mnum) values (?,?,?,?)",
90 (data
["uid"],data
["gid"],data
["choice"],data
["mnum"]))
95 def inc_pts(sid
, data
):
96 """ Add a point to the player (who won last round) """
97 con
= sqlite3
.connect(DB_PATH
)
99 cur
.execute("update Players set points=points+1 where uid=? and gid=?",
100 (data
["uid"],data
["gid"]))
105 '/': RPSLS_PATH
+ 'index.html',
106 '/rpsls.js': RPSLS_PATH
+ 'rpsls.js',
107 '/favicon.ico': RPSLS_PATH
+ 'favicon.ico',
108 '/assets': RPSLS_PATH
+ 'assets'
111 PORT
= os
.getenv('RPSLS_PORT')
116 # Wrap with a WSGI application
117 app
= socketio
.WSGIApp(sio
, static_files
=static_files
)
118 eventlet
.wsgi
.server(eventlet
.listen(('127.0.0.1', PORT
)), app
)