From 4fe2db18a08626b54f6a98aa13a80954fcb27ead Mon Sep 17 00:00:00 2001 From: Cesar Augusto de Carvalho Date: Fri, 2 Aug 2019 10:47:33 -0300 Subject: [PATCH] =?UTF-8?q?Sincroniza=C3=A7=C3=A3o=20de=20cron=C3=B4metros?= =?UTF-8?q?=20em=20diferentes=20m=C3=A1quinas=20(#2894)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Inicia sincronizacao de cronometros no painel do operador * Correção do reset e melhorias de código * Adiciona sincronização no painel eletrônico * Remove código desnecessário * Corrige sincronização no painel do operador --- sapl/base/templatetags/common_tags.py | 7 + .../migrations/0010_auto_20190711_1030.py | 26 ++ .../0011_cronometro_last_stop_duration.py | 20 ++ sapl/painel/models.py | 21 +- sapl/painel/views.py | 44 +++- sapl/sessao/views.py | 7 +- sapl/templates/painel/index.html | 79 +++++-- sapl/templates/sessao/painel.html | 223 +++++++++++++----- 8 files changed, 324 insertions(+), 103 deletions(-) create mode 100644 sapl/painel/migrations/0010_auto_20190711_1030.py create mode 100644 sapl/painel/migrations/0011_cronometro_last_stop_duration.py diff --git a/sapl/base/templatetags/common_tags.py b/sapl/base/templatetags/common_tags.py index 1e09677f7..4c512ed96 100644 --- a/sapl/base/templatetags/common_tags.py +++ b/sapl/base/templatetags/common_tags.py @@ -4,6 +4,7 @@ import re from django import template from django.template.defaultfilters import stringfilter from django.utils.safestring import mark_safe +from django.utils import timezone from webpack_loader import utils from sapl.base.models import AppConfig @@ -271,6 +272,12 @@ def cronometro_to_seconds(value): def duration_to_seconds(cronometro_duration): return cronometro_duration.seconds +@register.filter +def duration_difference(cronometro_duration, last_time): + difference_to_now = timezone.now()-last_time + if difference_to_now < cronometro_duration: + return (cronometro_duration-difference_to_now).seconds + return cronometro_duration.seconds @register.filter def to_list_pk(object_list): diff --git a/sapl/painel/migrations/0010_auto_20190711_1030.py b/sapl/painel/migrations/0010_auto_20190711_1030.py new file mode 100644 index 000000000..23899439b --- /dev/null +++ b/sapl/painel/migrations/0010_auto_20190711_1030.py @@ -0,0 +1,26 @@ +# -*- coding: utf-8 -*- +# Generated by Django 1.11.20 on 2019-07-11 13:30 +from __future__ import unicode_literals + +from django.db import migrations, models +import django.utils.timezone + + +class Migration(migrations.Migration): + + dependencies = [ + ('painel', '0009_painelconfig_mostrar_votos_antecedencia'), + ] + + operations = [ + migrations.AddField( + model_name='cronometro', + name='ultima_alteracao_status', + field=models.DateTimeField(default=django.utils.timezone.now), + ), + migrations.AlterField( + model_name='cronometro', + name='status', + field=models.CharField(choices=[('I', 'Start'), ('R', 'Reset'), ('S', 'Stop'), ('C', 'Increment')], default='R', max_length=1, verbose_name='Status do cronômetro'), + ), + ] diff --git a/sapl/painel/migrations/0011_cronometro_last_stop_duration.py b/sapl/painel/migrations/0011_cronometro_last_stop_duration.py new file mode 100644 index 000000000..d0dce9419 --- /dev/null +++ b/sapl/painel/migrations/0011_cronometro_last_stop_duration.py @@ -0,0 +1,20 @@ +# -*- coding: utf-8 -*- +# Generated by Django 1.11.20 on 2019-07-11 14:30 +from __future__ import unicode_literals + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('painel', '0010_auto_20190711_1030'), + ] + + operations = [ + migrations.AddField( + model_name='cronometro', + name='last_stop_duration', + field=models.DurationField(blank=True, null=True, verbose_name='Última duração salva em stop'), + ), + ] diff --git a/sapl/painel/models.py b/sapl/painel/models.py index 12d5e2d0b..85f97a58d 100644 --- a/sapl/painel/models.py +++ b/sapl/painel/models.py @@ -2,7 +2,7 @@ import reversion from django.db import models from django.utils.translation import ugettext_lazy as _ from sapl.utils import YES_NO_CHOICES - +from django.utils import timezone @reversion.register() class Painel(models.Model): @@ -24,12 +24,6 @@ class Painel(models.Model): @reversion.register() class Cronometro(models.Model): - CRONOMETRO_TYPES = ( - ('A', _('Aparte')), - ('D', _('Discurso')), - ('O', _('Ordem do dia')), - ('C', _('Considerações finais')) - ) CRONOMETRO_STATUS = ( ('I', 'Start'), @@ -42,17 +36,28 @@ class Cronometro(models.Model): max_length=1, verbose_name=_('Status do cronômetro'), choices=CRONOMETRO_STATUS, - default='S') + default='R') + + ultima_alteracao_status = models.DateTimeField(default=timezone.now) + + last_stop_duration = models.DurationField( + blank=True, + null=True, + verbose_name=_("Última duração salva em stop")) + duracao_cronometro = models.DurationField( verbose_name=_('Duração do cronômetro')) + tipo = models.CharField( max_length=100, verbose_name=_('Tipo Cronômetro'), unique=True) + ativo = models.BooleanField( default=False, choices=YES_NO_CHOICES, verbose_name=_('Ativo?')) + ordenacao = models.PositiveIntegerField( blank=True, null=True, diff --git a/sapl/painel/views.py b/sapl/painel/views.py index 4c3a85baf..50da0563b 100644 --- a/sapl/painel/views.py +++ b/sapl/painel/views.py @@ -363,7 +363,28 @@ def switch_painel(request): def verifica_painel(request): sessao = SessaoPlenaria.objects.get(id=request.GET['pk_sessao']) status = sessao.painel_aberto - resposta = JsonResponse(dict(status=status)) + + CRONOMETRO_STATUS = { + 'I': 'start', + 'R': 'reset', + 'S': 'stop', + 'C': 'increment' + } + + dict_status_cronometros = dict(Cronometro.objects.filter(ativo=True).order_by('ordenacao').values_list('id', 'status')) + + for key, value in dict_status_cronometros.items(): + dict_status_cronometros[key] = CRONOMETRO_STATUS[dict_status_cronometros[key]] + + dict_duracao_cronometros = dict(Cronometro.objects.filter(ativo=True).order_by('ordenacao').values_list('id', 'duracao_cronometro')) + + for key, value in dict_duracao_cronometros.items(): + dict_duracao_cronometros[key] = value.seconds + + resposta = JsonResponse(dict(status=status, + cronometros=dict_status_cronometros, + duracao_cronometros=dict_duracao_cronometros) + ) return resposta @@ -395,22 +416,13 @@ def cronometro_painel(request): cronometro_id = request.GET['tipo'].split('cronometro_')[1] cronometro = Cronometro.objects.get(id=cronometro_id) cronometro.status = CRONOMETRO_STATUS[acao] + cronometro.ultima_alteracao_status = timezone.now() + # Caso não seja stop, last_time virá como 0 + cronometro.last_stop_duration = request.GET.get('last_time') cronometro.save() return HttpResponse({}) -def get_cronometro_status(request, name): - logger = logging.getLogger(__name__) - username = request.user.username - try: - logger.debug("user=" + username + ". Tentando obter cronometro.") - cronometro = request.session[name] - except KeyError as e: - logger.error("user=" + username + ". Erro ao obter cronometro. Retornado como vazio. " + str(e)) - cronometro = '' - return cronometro - - def get_materia_aberta(pk): return OrdemDia.objects.filter( sessao_plenaria_id=pk, votacao_aberta=True).last() @@ -607,12 +619,18 @@ def get_dados_painel(request, pk): for key, value in dict_status_cronometros.items(): dict_status_cronometros[key] = CRONOMETRO_STATUS[dict_status_cronometros[key]] + + dict_duracao_cronometros = dict(Cronometro.objects.filter(ativo=True).order_by('ordenacao').values_list('id', 'duracao_cronometro')) + + for key, value in dict_duracao_cronometros.items(): + dict_duracao_cronometros[key] = value.seconds response = { 'sessao_plenaria': str(sessao), 'sessao_plenaria_data': sessao.data_inicio.strftime('%d/%m/%Y'), 'sessao_plenaria_hora_inicio': sessao.hora_inicio, 'cronometros': dict_status_cronometros, + 'duracao_cronometros': dict_duracao_cronometros, 'sessao_solene': sessao.tipo.nome == "Solene", 'sessao_finalizada': sessao.finalizada, 'tema_solene': sessao.tema_solene, diff --git a/sapl/sessao/views.py b/sapl/sessao/views.py index e6f112aab..91fa4930d 100755 --- a/sapl/sessao/views.py +++ b/sapl/sessao/views.py @@ -1055,9 +1055,10 @@ class PainelView(PermissionRequiredForAppCrudMixin, TemplateView): self.template_name = 'painel/index.html' cronometros = Cronometro.objects.filter(ativo=True).order_by('ordenacao') - for cronometro in cronometros: - cronometro.status = 'S' # Stop - cronometro.save() + # for cronometro in cronometros: + # cronometro.status = 'S' # Stop + # cronometro.ultima_alteracao_status = timezone.now() + # cronometro.save() return TemplateView.get(self, request, *args, **kwargs) diff --git a/sapl/templates/painel/index.html b/sapl/templates/painel/index.html index 3de48acd2..0eea79734 100644 --- a/sapl/templates/painel/index.html +++ b/sapl/templates/painel/index.html @@ -170,6 +170,16 @@ audio.play(); } + function convertValueToDuration(value){ + let h = Math.floor((value/1000) / 3600); + h = checkTime(h); + let m = Math.floor((value/1000) % 3600 / 60); + m = checkTime(m); + let s = Math.floor((value/1000) % 3600 % 60); + s = checkTime(s); + return h.toString() + ":" + m.toString() + ":" + s.toString(); + } + $(document).ready(function() { //TODO: replace by a fancy jQuery clock startTime(); @@ -186,23 +196,26 @@ {% for cron in cronometros %} cronometros_previous.push(0); $('#cronometro_' + "{{cron.id}}").runner({ - autostart: false, + autostart: {% if cron.status == "I"%} true {% else %} false {% endif %}, countdown: true, - startAt: parseInt("{{cron.duracao_cronometro|duration_to_seconds}}") * 1000, + startAt: + {% if cron.status == "R"%} + parseInt("{{cron.duracao_cronometro|duration_to_seconds}}") * 1000 + {% elif cron.status == "S"%} + {% if cron.last_stop_duration %} + parseInt("{{cron.last_stop_duration|duration_to_seconds}}") * 1000 + {% else %} + parseInt("{{cron.duracao_cronometro|duration_to_seconds}}") * 1000 + {% endif %} + {% elif cron.status == "I" %} + parseInt("{{cron.duracao_cronometro|duration_difference:cron.ultima_alteracao_status}}") * 1000 + {% endif %}, stopAt: 0, milliseconds: false, - format: function(value) { - let h = Math.floor((value/1000) / 3600); - h = checkTime(h); - let m = Math.floor((value/1000) % 3600 / 60); - m = checkTime(m); - let s = Math.floor((value/1000) % 3600 % 60); - s = checkTime(s); - return h.toString() + ":" + m.toString() + ":" + s.toString(); - } + format: convertValueToDuration }).on('runnerFinish', function(eventObject, info){ playAudioNumVezes(audioAlertFinish, num_vezes_toca_audio); - }) + }); {% endfor %} var tempo_disparo_antecedencia = "{{ painel_config.tempo_disparo_antecedencia }}" @@ -329,27 +342,55 @@ $("#votacao").append('
Não há votação, pois não há nenhuma matéria aberta ou já votada.
'); }; + // obtém todos os ids em uma lista e + // converte os dados do status dos cronômetros de dicionário para uma lista var ids = []; - var status_cronometros = [] + var status_cronometros = []; for (var key in data['cronometros']) { if (data['cronometros'].hasOwnProperty(key)) { ids.push(key); - status_cronometros.push(data['cronometros'][key]) + status_cronometros.push(data['cronometros'][key]); } } + // converte os dados de dicionário para uma lista + var duracao_cronometros = []; + for (let id of ids) { + duracao_cronometros.push(data['duracao_cronometros'][id]); + } + for(let i=0; i