Add Redis Channel Layer for the drawing system
Signed-off-by: Emmy D'Anello <emmy.danello@animath.fr>
This commit is contained in:
parent
0e7a275a28
commit
8245ba0063
|
@ -176,7 +176,15 @@ class DrawConsumer(AsyncJsonWebsocketConsumer):
|
|||
await TeamDraw.objects.acreate(participation=participation, round=r)
|
||||
# Send to clients the different pools
|
||||
await self.channel_layer.group_send(f"tournament-{self.tournament.id}",
|
||||
{'type': 'draw.send_poules', 'round': r})
|
||||
{'type': 'draw.send_poules',
|
||||
'round': r.number,
|
||||
'poules': [
|
||||
{
|
||||
'letter': pool.get_letter_display(),
|
||||
'teams': await pool.atrigrams(),
|
||||
}
|
||||
async for pool in r.pool_set.order_by('letter').all()
|
||||
]})
|
||||
|
||||
draw.current_round = r1
|
||||
await draw.asave()
|
||||
|
@ -191,9 +199,10 @@ class DrawConsumer(AsyncJsonWebsocketConsumer):
|
|||
await self.channel_layer.group_send(f"tournament-{self.tournament.id}",
|
||||
{'type': 'draw.start', 'fmt': fmt, 'draw': draw})
|
||||
await self.channel_layer.group_send(f"tournament-{self.tournament.id}",
|
||||
{'type': 'draw.set_info', 'draw': draw})
|
||||
{'type': 'draw.set_info',
|
||||
'info': await self.tournament.draw.ainformation()})
|
||||
await self.channel_layer.group_send(f"tournament-{self.tournament.id}",
|
||||
{'type': 'draw.set_active', 'draw': self.tournament.draw})
|
||||
{'type': 'draw.set_active', 'round': 1})
|
||||
|
||||
# Send notification to everyone
|
||||
await self.channel_layer.group_send(f"tournament-{self.tournament.id}",
|
||||
|
@ -457,25 +466,44 @@ class DrawConsumer(AsyncJsonWebsocketConsumer):
|
|||
{'type': 'draw.dice_visibility', 'visible': True})
|
||||
|
||||
# First send the second pool to have the good team order
|
||||
r2 = await self.tournament.draw.round_set.filter(number=2).aget()
|
||||
await self.channel_layer.group_send(f"tournament-{self.tournament.id}",
|
||||
{'type': 'draw.send_poules',
|
||||
'round': await self.tournament.draw.round_set.filter(number=2).aget()})
|
||||
'round': r2.number,
|
||||
'poules': [
|
||||
{
|
||||
'letter': pool.get_letter_display(),
|
||||
'teams': await pool.atrigrams(),
|
||||
}
|
||||
async for pool in r2.pool_set.order_by('letter').all()
|
||||
]})
|
||||
await self.channel_layer.group_send(f"tournament-{self.tournament.id}",
|
||||
{'type': 'draw.send_poules',
|
||||
'round': self.tournament.draw.current_round})
|
||||
'round': r.number,
|
||||
'poules': [
|
||||
{
|
||||
'letter': pool.get_letter_display(),
|
||||
'teams': await pool.atrigrams(),
|
||||
}
|
||||
async for pool in r.pool_set.order_by('letter').all()
|
||||
]})
|
||||
|
||||
# Update information header and the active team on the recap menu
|
||||
await self.channel_layer.group_send(f"tournament-{self.tournament.id}",
|
||||
{'type': 'draw.set_info', 'draw': self.tournament.draw})
|
||||
{'type': 'draw.set_info',
|
||||
'info': await self.tournament.draw.ainformation()})
|
||||
await self.channel_layer.group_send(f"tournament-{self.tournament.id}",
|
||||
{'type': 'draw.set_active', 'draw': self.tournament.draw})
|
||||
{'type': 'draw.set_active',
|
||||
'round': r.number,
|
||||
'pool': pool.get_letter_display()})
|
||||
|
||||
async def process_dice_order_poule(self):
|
||||
"""
|
||||
Called when all teams of the current launched their dice to determine the choice order.
|
||||
Place teams into pools and order their passage.
|
||||
"""
|
||||
pool = self.tournament.draw.current_round.current_pool
|
||||
r = self.tournament.draw.current_round
|
||||
pool = r.current_pool
|
||||
|
||||
tds = [td async for td in TeamDraw.objects.filter(pool=pool).prefetch_related('participation__team')]
|
||||
# Order teams by decreasing dice score
|
||||
|
@ -493,9 +521,13 @@ class DrawConsumer(AsyncJsonWebsocketConsumer):
|
|||
|
||||
# Update information header
|
||||
await self.channel_layer.group_send(f"tournament-{self.tournament.id}",
|
||||
{'type': 'draw.set_info', 'draw': self.tournament.draw})
|
||||
{'type': 'draw.set_info',
|
||||
'info': await self.tournament.draw.ainformation()})
|
||||
await self.channel_layer.group_send(f"tournament-{self.tournament.id}",
|
||||
{'type': 'draw.set_active', 'draw': self.tournament.draw})
|
||||
{'type': 'draw.set_active',
|
||||
'round': r.number,
|
||||
'pool': pool.get_letter_display(),
|
||||
'team': pool.current_team.participation.team.trigram})
|
||||
|
||||
# Hide dice button to everyone
|
||||
await self.channel_layer.group_send(f"tournament-{self.tournament.id}",
|
||||
|
@ -566,7 +598,8 @@ class DrawConsumer(AsyncJsonWebsocketConsumer):
|
|||
self.tournament.draw.last_message = ""
|
||||
await self.tournament.draw.asave()
|
||||
await self.channel_layer.group_send(f"tournament-{self.tournament.id}",
|
||||
{'type': 'draw.set_info', 'draw': self.tournament.draw})
|
||||
{'type': 'draw.set_info',
|
||||
'info': await self.tournament.draw.ainformation()})
|
||||
|
||||
async def accept_problem(self, **kwargs):
|
||||
"""
|
||||
|
@ -637,11 +670,18 @@ class DrawConsumer(AsyncJsonWebsocketConsumer):
|
|||
else:
|
||||
# Pool is ended
|
||||
await self.end_pool(pool)
|
||||
r = self.tournament.draw.current_round
|
||||
pool = r.current_pool
|
||||
|
||||
await self.channel_layer.group_send(f"tournament-{self.tournament.id}",
|
||||
{'type': 'draw.set_info', 'draw': self.tournament.draw})
|
||||
{'type': 'draw.set_info',
|
||||
'info': await self.tournament.draw.ainformation()})
|
||||
await self.channel_layer.group_send(f"tournament-{self.tournament.id}",
|
||||
{'type': 'draw.set_active', 'draw': self.tournament.draw})
|
||||
{'type': 'draw.set_active',
|
||||
'round': r.number,
|
||||
'pool': pool.get_letter_display(),
|
||||
'team': pool.current_team.participation.team.trigram
|
||||
if pool.current_team else None})
|
||||
|
||||
async def end_pool(self, pool: Pool) -> None:
|
||||
"""
|
||||
|
@ -736,7 +776,14 @@ class DrawConsumer(AsyncJsonWebsocketConsumer):
|
|||
# Reorder dices
|
||||
await self.channel_layer.group_send(f"tournament-{self.tournament.id}",
|
||||
{'type': 'draw.send_poules',
|
||||
'round': r2})
|
||||
'round': r2.number,
|
||||
'poules': [
|
||||
{
|
||||
'letter': pool.get_letter_display(),
|
||||
'teams': await pool.atrigrams(),
|
||||
}
|
||||
async for pool in r2.pool_set.order_by('letter').all()
|
||||
]})
|
||||
|
||||
# The passage order for the second round is already determined by the first round
|
||||
# Start the first pool of the second round
|
||||
|
@ -831,9 +878,13 @@ class DrawConsumer(AsyncJsonWebsocketConsumer):
|
|||
{'type': 'draw.box_visibility', 'visible': True})
|
||||
|
||||
await self.channel_layer.group_send(f"tournament-{self.tournament.id}",
|
||||
{'type': 'draw.set_info', 'draw': self.tournament.draw})
|
||||
{'type': 'draw.set_info',
|
||||
'info': await self.tournament.draw.ainformation()})
|
||||
await self.channel_layer.group_send(f"tournament-{self.tournament.id}",
|
||||
{'type': 'draw.set_active', 'draw': self.tournament.draw})
|
||||
{'type': 'draw.set_active',
|
||||
'round': r.number,
|
||||
'pool': pool.get_letter_display(),
|
||||
'team': new_trigram})
|
||||
|
||||
# Notify the team that it can draw a problem
|
||||
await self.channel_layer.group_send(f"team-{new_trigram}",
|
||||
|
@ -900,7 +951,15 @@ class DrawConsumer(AsyncJsonWebsocketConsumer):
|
|||
|
||||
# Send pools to users
|
||||
await self.channel_layer.group_send(f"tournament-{self.tournament.id}",
|
||||
{'type': 'draw.send_poules', 'round': r2})
|
||||
{'type': 'draw.send_poules',
|
||||
'round': r2.number,
|
||||
'poules': [
|
||||
{
|
||||
'letter': pool.get_letter_display(),
|
||||
'teams': await pool.atrigrams(),
|
||||
}
|
||||
async for pool in r2.pool_set.order_by('letter').all()
|
||||
]})
|
||||
|
||||
# Reset dices and update interface
|
||||
for participation in self.participations:
|
||||
|
@ -923,9 +982,12 @@ class DrawConsumer(AsyncJsonWebsocketConsumer):
|
|||
{'type': 'draw.continue_visibility', 'visible': False})
|
||||
|
||||
await self.channel_layer.group_send(f"tournament-{self.tournament.id}",
|
||||
{'type': 'draw.set_info', 'draw': self.tournament.draw})
|
||||
{'type': 'draw.set_info',
|
||||
'info': await self.tournament.draw.ainformation()})
|
||||
await self.channel_layer.group_send(f"tournament-{self.tournament.id}",
|
||||
{'type': 'draw.set_active', 'draw': self.tournament.draw})
|
||||
{'type': 'draw.set_active',
|
||||
'round': r2.number,
|
||||
'pool': r2.current_pool.get_letter_display()})
|
||||
|
||||
@ensure_orga
|
||||
async def cancel_last_step(self, **kwargs):
|
||||
|
@ -952,9 +1014,16 @@ class DrawConsumer(AsyncJsonWebsocketConsumer):
|
|||
await self.undo_order_dice()
|
||||
|
||||
await self.channel_layer.group_send(f"tournament-{self.tournament.id}",
|
||||
{'type': 'draw.set_info', 'draw': self.tournament.draw})
|
||||
{'type': 'draw.set_info',
|
||||
'info': await self.tournament.draw.ainformation()})
|
||||
r = self.tournament.draw.current_round
|
||||
p = r.current_pool
|
||||
await self.channel_layer.group_send(f"tournament-{self.tournament.id}",
|
||||
{'type': 'draw.set_active', 'draw': self.tournament.draw})
|
||||
{'type': 'draw.set_active',
|
||||
'round': r.number,
|
||||
'pool': p.get_letter_display() if p else None,
|
||||
'team': p.current_team.participation.team.trigram
|
||||
if p and p.current_team else None})
|
||||
|
||||
async def undo_end_draw(self) -> None:
|
||||
"""
|
||||
|
@ -1194,7 +1263,15 @@ class DrawConsumer(AsyncJsonWebsocketConsumer):
|
|||
'result': td.choice_dice})
|
||||
|
||||
await self.channel_layer.group_send(f"tournament-{self.tournament.id}",
|
||||
{'type': 'draw.send_poules', 'round': r1})
|
||||
{'type': 'draw.send_poules',
|
||||
'round': r1.number,
|
||||
'poules': [
|
||||
{
|
||||
'letter': pool.get_letter_display(),
|
||||
'teams': await pool.atrigrams(),
|
||||
}
|
||||
async for pool in r1.pool_set.order_by('letter').all()
|
||||
]})
|
||||
|
||||
previous_pool = r1.current_pool
|
||||
|
||||
|
@ -1339,7 +1416,7 @@ class DrawConsumer(AsyncJsonWebsocketConsumer):
|
|||
"""
|
||||
Set the information banner to the current user.
|
||||
"""
|
||||
await self.send_json({'type': 'set_info', 'information': await content['draw'].ainformation()})
|
||||
await self.send_json({'type': 'set_info', 'information': content['info']})
|
||||
|
||||
async def draw_dice(self, content):
|
||||
"""
|
||||
|
@ -1381,21 +1458,18 @@ class DrawConsumer(AsyncJsonWebsocketConsumer):
|
|||
"""
|
||||
Send the pools and the teams to the current user to update the interface.
|
||||
"""
|
||||
await self.send_json({'type': 'set_poules', 'round': content['round'].number,
|
||||
'poules': [{'letter': pool.get_letter_display(), 'teams': await pool.atrigrams()}
|
||||
async for pool in content['round'].pool_set.order_by('letter').all()]})
|
||||
await self.send_json({'type': 'set_poules', 'round': content['round'],
|
||||
'poules': content['poules']})
|
||||
|
||||
async def draw_set_active(self, content):
|
||||
"""
|
||||
Update the user interface to highlight the current team.
|
||||
"""
|
||||
r = content['draw'].current_round
|
||||
await self.send_json({
|
||||
'type': 'set_active',
|
||||
'round': r.number,
|
||||
'poule': r.current_pool.get_letter_display() if r.current_pool else None,
|
||||
'team': r.current_pool.current_team.participation.team.trigram
|
||||
if r.current_pool and r.current_pool.current_team else None,
|
||||
'round': content.get('round', None),
|
||||
'poule': content.get('pool', None),
|
||||
'team': content.get('team', None),
|
||||
})
|
||||
|
||||
async def draw_set_problem(self, content):
|
||||
|
|
|
@ -24,7 +24,7 @@ from django.utils.crypto import get_random_string
|
|||
from django.utils.translation import gettext_lazy as _
|
||||
from django.views.generic import CreateView, DetailView, FormView, RedirectView, TemplateView, UpdateView, View
|
||||
from django.views.generic.edit import FormMixin, ProcessFormView
|
||||
from django_tables2 import SingleTableView, MultiTableMixin
|
||||
from django_tables2 import MultiTableMixin, SingleTableView
|
||||
from magic import Magic
|
||||
from odf.opendocument import OpenDocumentSpreadsheet
|
||||
from odf.style import Style, TableCellProperties, TableColumnProperties, TextProperties
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
channels[daphne]~=4.0.0
|
||||
channels-redis~=4.0.0
|
||||
crispy-bootstrap5~=0.7
|
||||
Django>=4.1,<5.0
|
||||
django-cas-server~=2.0
|
||||
|
|
|
@ -79,6 +79,11 @@ if "test" not in sys.argv: # pragma: no cover
|
|||
'mailer',
|
||||
]
|
||||
|
||||
if os.getenv("TFJM_STAGE", "dev") == "prod": # pragma: no cover
|
||||
INSTALLED_APPS += [
|
||||
'channels_redis',
|
||||
]
|
||||
|
||||
MIDDLEWARE = [
|
||||
'django.middleware.security.SecurityMiddleware',
|
||||
'django.contrib.sessions.middleware.SessionMiddleware',
|
||||
|
@ -268,7 +273,6 @@ FORBIDDEN_TRIGRAMS = [
|
|||
"SEX",
|
||||
]
|
||||
|
||||
# TODO: Use a redis server in production
|
||||
CHANNEL_LAYERS = {
|
||||
"default": {
|
||||
"BACKEND": "channels.layers.InMemoryChannelLayer"
|
||||
|
|
|
@ -30,3 +30,12 @@ CSRF_COOKIE_SECURE = False
|
|||
CSRF_COOKIE_HTTPONLY = False
|
||||
X_FRAME_OPTIONS = 'DENY'
|
||||
SESSION_COOKIE_AGE = 60 * 60 * 3
|
||||
|
||||
CHANNEL_LAYERS = {
|
||||
"default": {
|
||||
"BACKEND": "channels_redis.core.RedisChannelLayer",
|
||||
"CONFIG": {
|
||||
"hosts": [(os.getenv('REDIS_SERVER_HOST', 'localhost'), os.getenv('REDIS_SERVER_PORT', 6379))],
|
||||
},
|
||||
},
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue