This commit is contained in:
simon987 2020-01-09 08:54:13 -05:00
commit 20abc7e978
7 changed files with 226 additions and 0 deletions

3
.gitignore vendored Normal file
View File

@ -0,0 +1,3 @@
.idea/
__pychache__
*.pyc

101
app.py Normal file
View File

@ -0,0 +1,101 @@
from threading import Lock
from flask import Flask, request, session
from flask_socketio import Namespace, join_room, leave_room, SocketIO, emit, rooms, close_room, disconnect
from common import config
app = Flask(__name__)
app.config['SECRET_KEY'] = 'secret!'
# TODO: test mode mode "threading", "eventlet" or "gevent"
socketio = SocketIO(app, async_mode=None)
# TODO: wth is that?!
thread = None
thread_lock = Lock()
@app.route("/")
def page_index():
return "Hello, world"
def background_thread():
"""Example of how to send server generated events to clients."""
count = 0
while True:
socketio.sleep(10)
count += 1
socketio.emit('my_response',
{'data': 'Server generated event', 'count': count},
namespace='/test')
# When class-based namespaces are used, any events received by the server are dispatched to a method named as the
# event name with the on_ prefix. For example, event my_event will be handled by a method named on_my_event
class BingoNamespace(Namespace):
def on_my_event(self, message):
session['receive_count'] = session.get('receive_count', 0) + 1
emit('my_response',
{'data': message['data'], 'count': session['receive_count']})
def on_my_broadcast_event(self, message):
session['receive_count'] = session.get('receive_count', 0) + 1
emit('my_response',
{'data': message['data'], 'count': session['receive_count']},
broadcast=True)
def on_join(self, message):
join_room(message['room'])
session['receive_count'] = session.get('receive_count', 0) + 1
emit('my_response',
{'data': 'In rooms: ' + ', '.join(rooms()),
'count': session['receive_count']})
def on_leave(self, message):
leave_room(message['room'])
session['receive_count'] = session.get('receive_count', 0) + 1
emit('my_response',
{'data': 'In rooms: ' + ', '.join(rooms()),
'count': session['receive_count']})
def on_close_room(self, message):
session['receive_count'] = session.get('receive_count', 0) + 1
emit('my_response', {'data': 'Room ' + message['room'] + ' is closing.',
'count': session['receive_count']},
room=message['room'])
close_room(message['room'])
def on_my_room_event(self, message):
session['receive_count'] = session.get('receive_count', 0) + 1
emit('my_response',
{'data': message['data'], 'count': session['receive_count']},
room=message['room'])
def on_disconnect_request(self):
session['receive_count'] = session.get('receive_count', 0) + 1
emit('my_response',
{'data': 'Disconnected!', 'count': session['receive_count']})
disconnect()
def on_my_ping(self):
emit('my_pong')
def on_connect(self):
global thread
with thread_lock:
if thread is None:
thread = socketio.start_background_task(background_thread)
emit('my_response', {'data': 'Connected', 'count': 0})
def on_disconnect(self):
print('Client disconnected', request.sid)
if __name__ == "__main__":
socketio.run(
app=app,
port=config["API_PORT"],
host=config["API_HOST"],
)

9
bingo.iml Normal file
View File

@ -0,0 +1,9 @@
<?xml version="1.0" encoding="UTF-8"?>
<module type="PYTHON_MODULE" version="4">
<component name="NewModuleRootManager" inherit-compiler-output="true">
<exclude-output />
<content url="file://$MODULE_DIR$" />
<orderEntry type="inheritedJdk" />
<orderEntry type="sourceFolder" forTests="false" />
</component>
</module>

7
common.py Normal file
View File

@ -0,0 +1,7 @@
config = {
"API_PORT": 3000,
"API_HOST": "0.0.0.0",
"REDIS_HOST": "localhost",
"REDIS_PORT": 6379,
}

90
models.py Normal file
View File

@ -0,0 +1,90 @@
from uuid import uuid4
import redis
import json
from common import config
class BingoCell:
def __init__(self, text, checked=False, free=False):
self.text = text
self.free = free
self.checked = checked
def serialize(self):
return self.__dict__
@staticmethod
def deserialize(j):
return BingoCell(
text=j["text"],
free=bool(j["free"]),
checked=bool(j["checked"])
)
class Row:
class BingoCard:
def __init__(self, size, cells=None, oid=None):
if cells is None:
self.cells = []
else:
self.cells = cells
if oid is None:
self.oid = uuid4().hex
else:
self.oid = oid
self.size = size
def serialize(self):
return {
"oid": self.oid,
"cells": [c.serialize() for c in self.cells]
}
def __getitem__(self, col):
@staticmethod
def deserialize(text):
j = json.loads(text)
return BingoCard(cells=[
BingoCell.deserialize(c) for c in j["cells"]
])
class DB:
_prefix = "bingo:"
def __init__(self):
self._rdb = redis.Redis(
host=config["REDIS_HOST"],
port=config["REDIS_PORT"]
)
def flush(self):
self._rdb.delete(self._rdb.keys(DB._prefix + "*"))
def _get(self, name):
return self._rdb.get(DB._prefix + name)
def _set(self, name, value):
return self._rdb.set(DB._prefix + name, value)
def get_card(self, oid):
return BingoCard.deserialize(self._get(oid))
def save_card(self, card):
self._set(card.oid, card.serialize())
c = BingoCard(
size=4,
cells=[
BingoCell("test")
])
print(c.serialize())

3
requirements.txt Normal file
View File

@ -0,0 +1,3 @@
flask
flask-socketio
redis

13
web/index.html Normal file
View File

@ -0,0 +1,13 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Test</title>
</head>
<body>
<script>
</script>
</body>
</html>