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