Spaces:
Sleeping
Sleeping
Merge pull request #5 from CascoArcilla/HU9
Browse filesMuestra de palabras por producto para calificar del lado del Catador
- tecnicas/controllers/__init__.py +17 -12
- tecnicas/controllers/calificacion_controller.py +0 -19
- tecnicas/controllers/models_controller/calificacion_controller.py +101 -0
- tecnicas/controllers/models_controller/catador_controller.py +10 -0
- tecnicas/controllers/models_controller/dato_controller.py +16 -0
- tecnicas/controllers/{escala_controller.py → models_controller/escala_controller.py} +30 -2
- tecnicas/controllers/{estilo_palabras_controller.py → models_controller/estilo_palabras_controller.py} +2 -2
- tecnicas/controllers/{ordenes_controller.py → models_controller/ordenes_controller.py} +10 -2
- tecnicas/controllers/models_controller/palabras_controller.py +47 -0
- tecnicas/controllers/models_controller/particiapacion_controller.py +36 -0
- tecnicas/controllers/models_controller/posicion_controller.py +20 -0
- tecnicas/controllers/{presentador_controller.py → models_controller/presentador_controller.py} +2 -2
- tecnicas/controllers/{productos_controller.py → models_controller/productos_controller.py} +16 -2
- tecnicas/controllers/{sesion_controller.py → models_controller/sesion_controller.py} +10 -2
- tecnicas/controllers/{tecnica_controller.py → models_controller/tecnica_controller.py} +2 -2
- tecnicas/controllers/palabras_controller.py +0 -31
- tecnicas/controllers/{detalles_sesion_controller.py → views_controller/detalles_sesion_controller.py} +3 -3
- tecnicas/controllers/{login_tester_controller.py → views_controller/login_tester_controller.py} +3 -3
- tecnicas/controllers/{main_tester_form_controller.py → views_controller/main_tester_form_controller.py} +41 -6
- tecnicas/static/js/created-scale.js +207 -0
- tecnicas/templates/tecnicas/forms_tester/convencional.html +182 -0
- tecnicas/templates/tecnicas/forms_tester/main_tester.html +17 -0
- tecnicas/templates/tecnicas/layouts/base.html +1 -1
- tecnicas/urls.py +8 -0
- tecnicas/views/__init__.py +2 -0
- tecnicas/views/apis/rating_word.py +17 -0
- tecnicas/views/login_tester.py +4 -0
- tecnicas/views/tester_forms/convencional_scales.py +129 -0
- tecnicas/views/tester_forms/main_tester_form.py +30 -13
tecnicas/controllers/__init__.py
CHANGED
|
@@ -1,12 +1,17 @@
|
|
| 1 |
-
from .tecnica_controller import TecnicaController
|
| 2 |
-
from .escala_controller import EscalaController
|
| 3 |
-
from .productos_controller import ProductosController
|
| 4 |
-
from .ordenes_controller import OrdenesController
|
| 5 |
-
from .palabras_controller import PalabrasController
|
| 6 |
-
from .estilo_palabras_controller import EstiloPalabrasController
|
| 7 |
-
from .palabras_controller import PalabrasController
|
| 8 |
-
from .sesion_controller import SesionController
|
| 9 |
-
from .calificacion_controller import CalificacionController
|
| 10 |
-
from .
|
| 11 |
-
from .
|
| 12 |
-
from .
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
from .models_controller.tecnica_controller import TecnicaController
|
| 2 |
+
from .models_controller.escala_controller import EscalaController
|
| 3 |
+
from .models_controller.productos_controller import ProductosController
|
| 4 |
+
from .models_controller.ordenes_controller import OrdenesController
|
| 5 |
+
from .models_controller.palabras_controller import PalabrasController
|
| 6 |
+
from .models_controller.estilo_palabras_controller import EstiloPalabrasController
|
| 7 |
+
from .models_controller.palabras_controller import PalabrasController
|
| 8 |
+
from .models_controller.sesion_controller import SesionController
|
| 9 |
+
from .models_controller.calificacion_controller import CalificacionController
|
| 10 |
+
from .models_controller.catador_controller import CatadorController
|
| 11 |
+
from .models_controller.posicion_controller import PosicionController
|
| 12 |
+
from .models_controller.particiapacion_controller import ParticipacionController
|
| 13 |
+
from .models_controller.dato_controller import DatoController
|
| 14 |
+
|
| 15 |
+
from .views_controller.detalles_sesion_controller import DetallesSesionController
|
| 16 |
+
from .views_controller.login_tester_controller import LoginTesterController
|
| 17 |
+
from .views_controller.main_tester_form_controller import MainTesterFormController
|
tecnicas/controllers/calificacion_controller.py
DELETED
|
@@ -1,19 +0,0 @@
|
|
| 1 |
-
from ..models import Calificacion, Tecnica
|
| 2 |
-
|
| 3 |
-
|
| 4 |
-
class CalificacionController():
|
| 5 |
-
@staticmethod
|
| 6 |
-
def getRatingsByTechnique(technique: Tecnica):
|
| 7 |
-
repetition = technique.repecion
|
| 8 |
-
|
| 9 |
-
if not repetition:
|
| 10 |
-
return {"error": "sin datos calficados aun"}
|
| 11 |
-
|
| 12 |
-
data_rating = {}
|
| 13 |
-
|
| 14 |
-
for i in range(repetition):
|
| 15 |
-
response_data = Calificacion.objects.filter(
|
| 16 |
-
id_tecnica=technique, num_repeticion=i+1)
|
| 17 |
-
data_rating[f"repeticion_{i+1}"] = response_data
|
| 18 |
-
|
| 19 |
-
return data_rating
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
tecnicas/controllers/models_controller/calificacion_controller.py
ADDED
|
@@ -0,0 +1,101 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
from ...models import Calificacion, Tecnica, Posicion, Producto, Catador
|
| 2 |
+
from ...utils import controller_error
|
| 3 |
+
from collections import defaultdict
|
| 4 |
+
|
| 5 |
+
|
| 6 |
+
class CalificacionController():
|
| 7 |
+
@staticmethod
|
| 8 |
+
def getRatingsByTechnique(technique: Tecnica):
|
| 9 |
+
repetition = technique.repecion
|
| 10 |
+
|
| 11 |
+
if not repetition:
|
| 12 |
+
return {"error": "sin datos calficados aun"}
|
| 13 |
+
|
| 14 |
+
data_rating = {}
|
| 15 |
+
|
| 16 |
+
for i in range(repetition):
|
| 17 |
+
response_data = Calificacion.objects.filter(
|
| 18 |
+
id_tecnica=technique, num_repeticion=i+1)
|
| 19 |
+
data_rating[f"repeticion_{i+1}"] = response_data
|
| 20 |
+
|
| 21 |
+
return data_rating
|
| 22 |
+
|
| 23 |
+
@staticmethod
|
| 24 |
+
def getRatings(
|
| 25 |
+
technique: Tecnica = None,
|
| 26 |
+
id_technique: int = None,
|
| 27 |
+
repetition: int = None,
|
| 28 |
+
product: Producto = None,
|
| 29 |
+
id_product: int = None,
|
| 30 |
+
tester: Catador = None,
|
| 31 |
+
id_tester: int = None,
|
| 32 |
+
user_tester: str = None,):
|
| 33 |
+
if repetition is None:
|
| 34 |
+
return controller_error("Es necesario especificar la repetición")
|
| 35 |
+
|
| 36 |
+
filters = {"num_repeticion": repetition}
|
| 37 |
+
|
| 38 |
+
if technique is not None:
|
| 39 |
+
filters["id_tecnica"] = technique
|
| 40 |
+
elif id_technique is not None:
|
| 41 |
+
filters["id_tecnica__id"] = id_technique
|
| 42 |
+
else:
|
| 43 |
+
return controller_error("Es necesario especificar la técnica")
|
| 44 |
+
|
| 45 |
+
if product is not None:
|
| 46 |
+
filters["id_producto"] = product
|
| 47 |
+
elif id_product is not None:
|
| 48 |
+
filters["id_producto__id"] = id_product
|
| 49 |
+
|
| 50 |
+
if tester is not None:
|
| 51 |
+
filters["id_catador"] = tester
|
| 52 |
+
elif id_tester is not None:
|
| 53 |
+
filters["id_catador__id"] = id_tester
|
| 54 |
+
elif user_tester is not None:
|
| 55 |
+
filters["id_catador__usuarioCatador"] = user_tester
|
| 56 |
+
|
| 57 |
+
ratings = list(Calificacion.objects.filter(**filters).select_related(
|
| 58 |
+
"id_producto",
|
| 59 |
+
"id_tecnica",
|
| 60 |
+
"id_catador",
|
| 61 |
+
))
|
| 62 |
+
|
| 63 |
+
return ratings
|
| 64 |
+
|
| 65 |
+
@staticmethod
|
| 66 |
+
def checkProducsWithoutRating(
|
| 67 |
+
positions: list[Posicion] = None,
|
| 68 |
+
user_cata: str = None,
|
| 69 |
+
repetition: int = None,
|
| 70 |
+
technique: Tecnica = None,
|
| 71 |
+
id_technique: int = None,
|
| 72 |
+
num_words: int = None):
|
| 73 |
+
check_products = [position.id_producto for position in positions]
|
| 74 |
+
|
| 75 |
+
filters = {
|
| 76 |
+
"user_tester": user_cata,
|
| 77 |
+
"repetition": repetition
|
| 78 |
+
}
|
| 79 |
+
|
| 80 |
+
if technique is not None:
|
| 81 |
+
filters["technique"] = technique
|
| 82 |
+
elif id_technique is not None:
|
| 83 |
+
filters["id_technique"] = id_technique
|
| 84 |
+
|
| 85 |
+
ratings = CalificacionController.getRatings(**filters)
|
| 86 |
+
|
| 87 |
+
if len(ratings) == 0:
|
| 88 |
+
return positions
|
| 89 |
+
|
| 90 |
+
ratings_dict = defaultdict(list)
|
| 91 |
+
|
| 92 |
+
for rat in ratings:
|
| 93 |
+
ratings_dict[rat.id_producto.id].append(rat)
|
| 94 |
+
|
| 95 |
+
for index, product in enumerate(check_products):
|
| 96 |
+
rating_of_product = ratings_dict.get(product.id, [])
|
| 97 |
+
|
| 98 |
+
if rating_of_product < num_words or len(rating_of_product) == 0:
|
| 99 |
+
return positions[index]
|
| 100 |
+
|
| 101 |
+
return controller_error("Sin productos por calificar")
|
tecnicas/controllers/models_controller/catador_controller.py
ADDED
|
@@ -0,0 +1,10 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
from ...models import Catador
|
| 2 |
+
from ...utils import controller_error
|
| 3 |
+
|
| 4 |
+
class CatadorController:
|
| 5 |
+
def getTesterByUsername(username:str):
|
| 6 |
+
try:
|
| 7 |
+
tester = Catador.objects.get(usuarioCatador=username)
|
| 8 |
+
return tester
|
| 9 |
+
except Catador.DoesNotExist:
|
| 10 |
+
return controller_error("No se encontró el Catador")
|
tecnicas/controllers/models_controller/dato_controller.py
ADDED
|
@@ -0,0 +1,16 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
from ...models import Calificacion, Dato
|
| 2 |
+
from ...utils import controller_error
|
| 3 |
+
|
| 4 |
+
|
| 5 |
+
class DatoController():
|
| 6 |
+
@staticmethod
|
| 7 |
+
def getRerecordedData(ratings: list[Calificacion]):
|
| 8 |
+
if not ratings:
|
| 9 |
+
return []
|
| 10 |
+
|
| 11 |
+
ids_ratings = [rat.id for rat in ratings]
|
| 12 |
+
|
| 13 |
+
recoreded_data = list(Dato.objects.filter(
|
| 14 |
+
id_calificacion_id__in=ids_ratings))
|
| 15 |
+
|
| 16 |
+
return recoreded_data
|
tecnicas/controllers/{escala_controller.py → models_controller/escala_controller.py}
RENAMED
|
@@ -1,6 +1,6 @@
|
|
| 1 |
-
from
|
| 2 |
from django.db import DatabaseError
|
| 3 |
-
from
|
| 4 |
|
| 5 |
|
| 6 |
class EscalaController():
|
|
@@ -68,3 +68,31 @@ class EscalaController():
|
|
| 68 |
except DatabaseError as error:
|
| 69 |
self.deleteRelationshipsWithLabels()
|
| 70 |
return controller_error("error guardar relacion etiqueta escala")
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
from ...models import Etiqueta, EtiquetasEscala, Escala, TipoEscala, Tecnica
|
| 2 |
from django.db import DatabaseError
|
| 3 |
+
from ...utils import controller_error
|
| 4 |
|
| 5 |
|
| 6 |
class EscalaController():
|
|
|
|
| 68 |
except DatabaseError as error:
|
| 69 |
self.deleteRelationshipsWithLabels()
|
| 70 |
return controller_error("error guardar relacion etiqueta escala")
|
| 71 |
+
|
| 72 |
+
@staticmethod
|
| 73 |
+
def getScaleByTechnique(technique: Tecnica = None, id_technique: int = None):
|
| 74 |
+
if technique is not None:
|
| 75 |
+
scale = Escala.objects.select_related("id_tipo_escala").only(
|
| 76 |
+
"id_tipo_escala", "longitud").get(tecnica=technique)
|
| 77 |
+
return scale
|
| 78 |
+
|
| 79 |
+
if id_technique is not None:
|
| 80 |
+
scale = Escala.objects.select_related("id_tipo_escala").only(
|
| 81 |
+
"id_tipo_escala", "longitud").get(tecnica_id=id_technique)
|
| 82 |
+
return scale
|
| 83 |
+
|
| 84 |
+
@staticmethod
|
| 85 |
+
def getRelatedTagsInScale(scale: Escala = None, id_scale: int = None):
|
| 86 |
+
if scale is not None:
|
| 87 |
+
scale_tags = list(EtiquetasEscala.objects.filter(
|
| 88 |
+
id_escala=scale).select_related("id_etiqueta"))
|
| 89 |
+
if len(scale_tags) == 0:
|
| 90 |
+
return controller_error("Imposible obtener las etiquetas")
|
| 91 |
+
return scale_tags
|
| 92 |
+
|
| 93 |
+
if id_scale is not None:
|
| 94 |
+
scale_tags = list(EtiquetasEscala.objects.filter(
|
| 95 |
+
id_escala_id=scale).select_related("id_etiqueta"))
|
| 96 |
+
if len(scale_tags) == 0:
|
| 97 |
+
return controller_error("Imposible obtener las etiquetas")
|
| 98 |
+
return scale_tags
|
tecnicas/controllers/{estilo_palabras_controller.py → models_controller/estilo_palabras_controller.py}
RENAMED
|
@@ -1,6 +1,6 @@
|
|
| 1 |
-
from
|
| 2 |
from django.db import DatabaseError
|
| 3 |
-
from
|
| 4 |
|
| 5 |
|
| 6 |
class EstiloPalabrasController():
|
|
|
|
| 1 |
+
from ...models import EsAtributo, Tecnica, Palabra
|
| 2 |
from django.db import DatabaseError
|
| 3 |
+
from ...utils import controller_error
|
| 4 |
|
| 5 |
|
| 6 |
class EstiloPalabrasController():
|
tecnicas/controllers/{ordenes_controller.py → models_controller/ordenes_controller.py}
RENAMED
|
@@ -1,5 +1,5 @@
|
|
| 1 |
-
from
|
| 2 |
-
from
|
| 3 |
from django.db import DatabaseError
|
| 4 |
|
| 5 |
|
|
@@ -74,3 +74,11 @@ class OrdenesController():
|
|
| 74 |
return self.positions
|
| 75 |
except DatabaseError as error:
|
| 76 |
return controller_error("error al guardar las posiciones")
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
from ...models import Orden, Posicion, Producto, Tecnica
|
| 2 |
+
from ...utils import controller_error
|
| 3 |
from django.db import DatabaseError
|
| 4 |
|
| 5 |
|
|
|
|
| 74 |
return self.positions
|
| 75 |
except DatabaseError as error:
|
| 76 |
return controller_error("error al guardar las posiciones")
|
| 77 |
+
|
| 78 |
+
@staticmethod
|
| 79 |
+
def getOrderById(id: int):
|
| 80 |
+
try:
|
| 81 |
+
order = Orden.objects.get(id=id)
|
| 82 |
+
return order
|
| 83 |
+
except Orden.DoesNotExist:
|
| 84 |
+
return controller_error("No existe orden")
|
tecnicas/controllers/models_controller/palabras_controller.py
ADDED
|
@@ -0,0 +1,47 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
from ...models import Palabra, Tecnica, EsAtributo, EsVocabulario, Dato
|
| 2 |
+
from django.db import DatabaseError
|
| 3 |
+
from ...utils import controller_error
|
| 4 |
+
|
| 5 |
+
|
| 6 |
+
class PalabrasController():
|
| 7 |
+
ids_words: list[int]
|
| 8 |
+
words: list[Palabra]
|
| 9 |
+
|
| 10 |
+
def __init__(self, ids: list[int]):
|
| 11 |
+
self.ids_words = ids
|
| 12 |
+
|
| 13 |
+
def setIdsWords(self, new_ids: list[int]):
|
| 14 |
+
self.ids_words = new_ids
|
| 15 |
+
|
| 16 |
+
def setWords(self):
|
| 17 |
+
self.words = []
|
| 18 |
+
searched_words = list(Palabra.objects.filter(id__in=self.ids_words))
|
| 19 |
+
if not len(searched_words):
|
| 20 |
+
return controller_error("no se han encontrado registros")
|
| 21 |
+
return self.words
|
| 22 |
+
|
| 23 |
+
@staticmethod
|
| 24 |
+
def getWordsInTechnique(technique: Tecnica):
|
| 25 |
+
if technique.id_estilo.nombre_estilo == "atributos":
|
| 26 |
+
es_atribute = EsAtributo.objects.get(id_tecnica=technique)
|
| 27 |
+
words = list(es_atribute.palabras.all())
|
| 28 |
+
return words
|
| 29 |
+
elif technique.id_estilo.nombre_estilo == "vocabulario":
|
| 30 |
+
try:
|
| 31 |
+
palabras = Palabra.objects.filter(
|
| 32 |
+
vocabulario__esvocabulario__id_tecnica=technique
|
| 33 |
+
)
|
| 34 |
+
return list(palabras.distinct()) if palabras.exists() else controller_error("Técnica sin palabras con vocabulario")
|
| 35 |
+
except Exception as e:
|
| 36 |
+
return controller_error("Técnica sin palabras con vocabulario")
|
| 37 |
+
|
| 38 |
+
@staticmethod
|
| 39 |
+
def getWordsWithoutData(recoreded_data: list[Dato], words: list[Palabra]):
|
| 40 |
+
qualified_words = [data.id_palabra for data in recoreded_data]
|
| 41 |
+
|
| 42 |
+
if set(qualified_words) == set(words):
|
| 43 |
+
return controller_error("No hay palabras por usar")
|
| 44 |
+
|
| 45 |
+
words_without_use = list(set(words).difference(set(qualified_words)))
|
| 46 |
+
|
| 47 |
+
return words_without_use
|
tecnicas/controllers/models_controller/particiapacion_controller.py
ADDED
|
@@ -0,0 +1,36 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
from ...models import Participacion
|
| 2 |
+
from ...utils import controller_error
|
| 3 |
+
|
| 4 |
+
|
| 5 |
+
class ParticipacionController():
|
| 6 |
+
@staticmethod
|
| 7 |
+
def enterSession(id_participation: int):
|
| 8 |
+
try:
|
| 9 |
+
participation = Participacion.objects.get(id=id_participation)
|
| 10 |
+
participation.finalizado = False
|
| 11 |
+
participation.activo = True
|
| 12 |
+
participation.save()
|
| 13 |
+
return participation
|
| 14 |
+
except Participacion.DoesNotExist:
|
| 15 |
+
return controller_error("No se ha encontrado la participación")
|
| 16 |
+
|
| 17 |
+
@staticmethod
|
| 18 |
+
def finishSession(id_participation: int):
|
| 19 |
+
try:
|
| 20 |
+
participation = Participacion.objects.get(id=id_participation)
|
| 21 |
+
participation.finalizado = True
|
| 22 |
+
participation.activo = False
|
| 23 |
+
participation.save()
|
| 24 |
+
return participation
|
| 25 |
+
except Participacion.DoesNotExist:
|
| 26 |
+
return controller_error("No se ha encontrado la participación")
|
| 27 |
+
|
| 28 |
+
@staticmethod
|
| 29 |
+
def outSession(id_participation: int):
|
| 30 |
+
try:
|
| 31 |
+
participation = Participacion.objects.get(id=id_participation)
|
| 32 |
+
participation.activo = False
|
| 33 |
+
participation.save()
|
| 34 |
+
return participation
|
| 35 |
+
except Participacion.DoesNotExist:
|
| 36 |
+
return controller_error("No se ha encontrado la participación")
|
tecnicas/controllers/models_controller/posicion_controller.py
ADDED
|
@@ -0,0 +1,20 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
from ...utils import controller_error
|
| 2 |
+
from ...models import Orden, Posicion
|
| 3 |
+
|
| 4 |
+
|
| 5 |
+
class PosicionController():
|
| 6 |
+
@staticmethod
|
| 7 |
+
def getPostionsInOrder(order: Orden = None, id_order: id = None):
|
| 8 |
+
if order is not None:
|
| 9 |
+
positions = list(Posicion.objects.filter(id_orden=order))
|
| 10 |
+
if not positions:
|
| 11 |
+
return controller_error("No existe orden")
|
| 12 |
+
return positions
|
| 13 |
+
|
| 14 |
+
if id_order is not None:
|
| 15 |
+
positions = list(Posicion.objects.filter(id_orden_id=id_order))
|
| 16 |
+
if not positions:
|
| 17 |
+
return controller_error("No existe orden")
|
| 18 |
+
return positions
|
| 19 |
+
|
| 20 |
+
return controller_error("No se define búsqueda")
|
tecnicas/controllers/{presentador_controller.py → models_controller/presentador_controller.py}
RENAMED
|
@@ -1,5 +1,5 @@
|
|
| 1 |
-
from
|
| 2 |
-
from
|
| 3 |
|
| 4 |
|
| 5 |
class PresentadorController():
|
|
|
|
| 1 |
+
from ...models import Presentador
|
| 2 |
+
from ...utils import controller_error
|
| 3 |
|
| 4 |
|
| 5 |
class PresentadorController():
|
tecnicas/controllers/{productos_controller.py → models_controller/productos_controller.py}
RENAMED
|
@@ -1,6 +1,6 @@
|
|
| 1 |
from django.db import DatabaseError
|
| 2 |
-
from
|
| 3 |
-
from
|
| 4 |
|
| 5 |
|
| 6 |
class ProductosController():
|
|
@@ -37,3 +37,17 @@ class ProductosController():
|
|
| 37 |
return self.list_product
|
| 38 |
except DatabaseError as error:
|
| 39 |
return controller_error("error al guardar los productos")
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
from django.db import DatabaseError
|
| 2 |
+
from ...utils import controller_error
|
| 3 |
+
from ...models import Producto, Tecnica
|
| 4 |
|
| 5 |
|
| 6 |
class ProductosController():
|
|
|
|
| 37 |
return self.list_product
|
| 38 |
except DatabaseError as error:
|
| 39 |
return controller_error("error al guardar los productos")
|
| 40 |
+
|
| 41 |
+
@staticmethod
|
| 42 |
+
def getProductsByTechniqe(technique: Tecnica = None, id_technique: int = None):
|
| 43 |
+
if technique is not None:
|
| 44 |
+
products = list(Producto.objects.filter(id_tecnica=technique))
|
| 45 |
+
if not products:
|
| 46 |
+
return controller_error("No existen productos en esta técnica")
|
| 47 |
+
return products
|
| 48 |
+
|
| 49 |
+
if id_technique is not None:
|
| 50 |
+
products = list(Producto.objects.filter(id_tecnica_id=id_technique))
|
| 51 |
+
if not products:
|
| 52 |
+
return controller_error("No existen productos en esta técnica")
|
| 53 |
+
return products
|
tecnicas/controllers/{sesion_controller.py → models_controller/sesion_controller.py}
RENAMED
|
@@ -1,7 +1,7 @@
|
|
| 1 |
from django.db import DatabaseError
|
| 2 |
from django.core.paginator import Paginator, EmptyPage, PageNotAnInteger
|
| 3 |
-
from
|
| 4 |
-
from
|
| 5 |
|
| 6 |
|
| 7 |
class SesionController():
|
|
@@ -91,6 +91,14 @@ class SesionController():
|
|
| 91 |
return session
|
| 92 |
except SesionSensorial.DoesNotExist:
|
| 93 |
return controller_error("La sesión ya no existe")
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 94 |
|
| 95 |
@staticmethod
|
| 96 |
def getNumberSessionsByCreator(user_name: str):
|
|
|
|
| 1 |
from django.db import DatabaseError
|
| 2 |
from django.core.paginator import Paginator, EmptyPage, PageNotAnInteger
|
| 3 |
+
from ...models import Tecnica, Presentador, SesionSensorial
|
| 4 |
+
from ...utils import controller_error
|
| 5 |
|
| 6 |
|
| 7 |
class SesionController():
|
|
|
|
| 91 |
return session
|
| 92 |
except SesionSensorial.DoesNotExist:
|
| 93 |
return controller_error("La sesión ya no existe")
|
| 94 |
+
|
| 95 |
+
@staticmethod
|
| 96 |
+
def getSessionByCode(code: str):
|
| 97 |
+
try:
|
| 98 |
+
session = SesionSensorial.objects.get(codigo_sesion=code)
|
| 99 |
+
return session
|
| 100 |
+
except SesionSensorial.DoesNotExist:
|
| 101 |
+
return controller_error("La sesión ya no existe")
|
| 102 |
|
| 103 |
@staticmethod
|
| 104 |
def getNumberSessionsByCreator(user_name: str):
|
tecnicas/controllers/{tecnica_controller.py → models_controller/tecnica_controller.py}
RENAMED
|
@@ -1,6 +1,6 @@
|
|
| 1 |
-
from
|
| 2 |
from django.db import DatabaseError
|
| 3 |
-
from
|
| 4 |
|
| 5 |
|
| 6 |
class TecnicaController():
|
|
|
|
| 1 |
+
from ...models import TipoTecnica, CategoriaTecnica, Tecnica, EstiloPalabra
|
| 2 |
from django.db import DatabaseError
|
| 3 |
+
from ...utils import controller_error
|
| 4 |
|
| 5 |
|
| 6 |
class TecnicaController():
|
tecnicas/controllers/palabras_controller.py
DELETED
|
@@ -1,31 +0,0 @@
|
|
| 1 |
-
from ..models import Palabra, Tecnica, EsAtributo
|
| 2 |
-
from django.db import DatabaseError
|
| 3 |
-
from ..utils import controller_error
|
| 4 |
-
|
| 5 |
-
|
| 6 |
-
class PalabrasController():
|
| 7 |
-
ids_words: list[int]
|
| 8 |
-
words: list[Palabra]
|
| 9 |
-
|
| 10 |
-
def __init__(self, ids: list[int]):
|
| 11 |
-
self.ids_words = ids
|
| 12 |
-
|
| 13 |
-
def setIdsWords(self, new_ids: list[int]):
|
| 14 |
-
self.ids_words = new_ids
|
| 15 |
-
|
| 16 |
-
def setWords(self):
|
| 17 |
-
self.words = []
|
| 18 |
-
try:
|
| 19 |
-
searched_words = Palabra.objects.filter(id__in=self.ids_words)
|
| 20 |
-
if not len(searched_words):
|
| 21 |
-
return controller_error("no se han encontrado registros")
|
| 22 |
-
self.words = searched_words
|
| 23 |
-
return self.words
|
| 24 |
-
except DatabaseError as error:
|
| 25 |
-
return controller_error("error al guardar buscar palabras")
|
| 26 |
-
|
| 27 |
-
@staticmethod
|
| 28 |
-
def getWordsInTechnique(technique: Tecnica):
|
| 29 |
-
es_atributo = EsAtributo.objects.get(id_tecnica=technique)
|
| 30 |
-
words = es_atributo.palabras.all()
|
| 31 |
-
return words
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
tecnicas/controllers/{detalles_sesion_controller.py → views_controller/detalles_sesion_controller.py}
RENAMED
|
@@ -1,6 +1,6 @@
|
|
| 1 |
-
from
|
| 2 |
-
from
|
| 3 |
-
from
|
| 4 |
|
| 5 |
|
| 6 |
class DetallesSesionController():
|
|
|
|
| 1 |
+
from ...models import SesionSensorial, Presentador, Tecnica
|
| 2 |
+
from .. import CalificacionController, PalabrasController
|
| 3 |
+
from ...utils import controller_error
|
| 4 |
|
| 5 |
|
| 6 |
class DetallesSesionController():
|
tecnicas/controllers/{login_tester_controller.py → views_controller/login_tester_controller.py}
RENAMED
|
@@ -1,5 +1,5 @@
|
|
| 1 |
-
from
|
| 2 |
-
from
|
| 3 |
from django.db import transaction
|
| 4 |
|
| 5 |
|
|
@@ -18,7 +18,7 @@ class LoginTesterController():
|
|
| 18 |
self.session = SesionSensorial.objects.get(
|
| 19 |
codigo_sesion=code_session)
|
| 20 |
|
| 21 |
-
return
|
| 22 |
except (Catador.DoesNotExist, SesionSensorial.DoesNotExist):
|
| 23 |
return controller_error("Credenciales inválidas")
|
| 24 |
|
|
|
|
| 1 |
+
from ...models import Catador, SesionSensorial, Participacion
|
| 2 |
+
from ...utils import controller_error
|
| 3 |
from django.db import transaction
|
| 4 |
|
| 5 |
|
|
|
|
| 18 |
self.session = SesionSensorial.objects.get(
|
| 19 |
codigo_sesion=code_session)
|
| 20 |
|
| 21 |
+
return (self.tester, self.session)
|
| 22 |
except (Catador.DoesNotExist, SesionSensorial.DoesNotExist):
|
| 23 |
return controller_error("Credenciales inválidas")
|
| 24 |
|
tecnicas/controllers/{main_tester_form_controller.py → views_controller/main_tester_form_controller.py}
RENAMED
|
@@ -1,5 +1,5 @@
|
|
| 1 |
-
from
|
| 2 |
-
from
|
| 3 |
from django.db import transaction
|
| 4 |
|
| 5 |
|
|
@@ -18,10 +18,10 @@ class MainTesterFormController():
|
|
| 18 |
|
| 19 |
def assignOrder(self):
|
| 20 |
with transaction.atomic():
|
| 21 |
-
orders_without_tester = Orden.objects.select_for_update().filter(
|
| 22 |
-
id_tecnica=self.session.tecnica, id_catador=None)
|
| 23 |
|
| 24 |
-
if not
|
| 25 |
return controller_error("Las ordenes se han acabado")
|
| 26 |
|
| 27 |
shuffle_orders = shuffleArray(orders_without_tester)
|
|
@@ -35,7 +35,7 @@ class MainTesterFormController():
|
|
| 35 |
def checkAssignOrder(self):
|
| 36 |
if not self.tester or not self.session:
|
| 37 |
return controller_error("Atributos no establecidos")
|
| 38 |
-
|
| 39 |
try:
|
| 40 |
res_order = Orden.objects.get(
|
| 41 |
id_tecnica=self.session.tecnica, id_catador=self.tester)
|
|
@@ -43,3 +43,38 @@ class MainTesterFormController():
|
|
| 43 |
return self.order
|
| 44 |
except Orden.DoesNotExist:
|
| 45 |
return controller_error("Catador sin orden")
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
from ...models import Catador, SesionSensorial, Orden, Participacion, Producto, EsAtributo, Calificacion, EsVocabulario
|
| 2 |
+
from ...utils import controller_error, shuffleArray
|
| 3 |
from django.db import transaction
|
| 4 |
|
| 5 |
|
|
|
|
| 18 |
|
| 19 |
def assignOrder(self):
|
| 20 |
with transaction.atomic():
|
| 21 |
+
orders_without_tester = list(Orden.objects.select_for_update().filter(
|
| 22 |
+
id_tecnica=self.session.tecnica, id_catador=None))
|
| 23 |
|
| 24 |
+
if not orders_without_tester:
|
| 25 |
return controller_error("Las ordenes se han acabado")
|
| 26 |
|
| 27 |
shuffle_orders = shuffleArray(orders_without_tester)
|
|
|
|
| 35 |
def checkAssignOrder(self):
|
| 36 |
if not self.tester or not self.session:
|
| 37 |
return controller_error("Atributos no establecidos")
|
| 38 |
+
|
| 39 |
try:
|
| 40 |
res_order = Orden.objects.get(
|
| 41 |
id_tecnica=self.session.tecnica, id_catador=self.tester)
|
|
|
|
| 43 |
return self.order
|
| 44 |
except Orden.DoesNotExist:
|
| 45 |
return controller_error("Catador sin orden")
|
| 46 |
+
|
| 47 |
+
def isEndedSession(self, id_participation: int, repetition: int):
|
| 48 |
+
if not self.order or not id_participation:
|
| 49 |
+
return controller_error("Se requieren datos para comprobar la finalización")
|
| 50 |
+
|
| 51 |
+
try:
|
| 52 |
+
participation = Participacion.objects.get(id=id_participation)
|
| 53 |
+
|
| 54 |
+
if participation.finalizado:
|
| 55 |
+
num_products = Producto.objects.filter(
|
| 56 |
+
id_tecnica=self.session.tecnica).count()
|
| 57 |
+
|
| 58 |
+
style_words = self.session.tecnica.id_estilo
|
| 59 |
+
|
| 60 |
+
num_words: int
|
| 61 |
+
|
| 62 |
+
if style_words.nombre_estilo == "atributos":
|
| 63 |
+
e_atribues = EsAtributo.objects.get(
|
| 64 |
+
id_tecnica=self.session.tecnica)
|
| 65 |
+
num_words = e_atribues.palabras.count()
|
| 66 |
+
elif style_words.nombre_estilo == "vocabulario":
|
| 67 |
+
e_vocabulary = EsVocabulario.objects.get(
|
| 68 |
+
id_tecnica=self.session.tecnica)
|
| 69 |
+
num_words = e_vocabulary.id_vocabulario.palabras.count()
|
| 70 |
+
|
| 71 |
+
num_ratings_now = Calificacion.objects.filter(
|
| 72 |
+
id_tecnica=self.session.tecnica, id_catador=self.tester, num_repeticion=repetition).count()
|
| 73 |
+
|
| 74 |
+
num_ratings_max_by_tester = num_products * num_words
|
| 75 |
+
|
| 76 |
+
return not num_ratings_now <= num_ratings_max_by_tester
|
| 77 |
+
else:
|
| 78 |
+
return participation.finalizado
|
| 79 |
+
except Participacion.DoesNotExist:
|
| 80 |
+
return controller_error("No se ha encontrado la participación")
|
tecnicas/static/js/created-scale.js
ADDED
|
@@ -0,0 +1,207 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
const BTN_CLASS_STYLE = [
|
| 2 |
+
"text-lg",
|
| 3 |
+
"tracking-wider",
|
| 4 |
+
"font-medium",
|
| 5 |
+
"p-2",
|
| 6 |
+
"px-4",
|
| 7 |
+
"border-b-2",
|
| 8 |
+
"active:border-b-0",
|
| 9 |
+
"active:border-t-2",
|
| 10 |
+
"active:border-blue-500",
|
| 11 |
+
"border-blue-800",
|
| 12 |
+
"transition-all",
|
| 13 |
+
"rounded-xl",
|
| 14 |
+
"bg-blue-500",
|
| 15 |
+
"text-white",
|
| 16 |
+
"w-fit",
|
| 17 |
+
"disabled:bg-amber-600",
|
| 18 |
+
];
|
| 19 |
+
|
| 20 |
+
function checkSendRating(word) {
|
| 21 |
+
const btnCheck = document.querySelector(`.ct-btn-check-${word}`);
|
| 22 |
+
const btnSend = document.querySelector(`.ct-btn-submit-${word}`);
|
| 23 |
+
const btnCancel = document.querySelector(`.ct-btn-cancel-${word}`);
|
| 24 |
+
|
| 25 |
+
btnCheck.classList.add("hidden");
|
| 26 |
+
btnSend.classList.remove("hidden");
|
| 27 |
+
btnCancel.classList.remove("hidden");
|
| 28 |
+
}
|
| 29 |
+
|
| 30 |
+
function cancelSendRating(word) {
|
| 31 |
+
const btnCheck = document.querySelector(`.ct-btn-check-${word}`);
|
| 32 |
+
const btnSend = document.querySelector(`.ct-btn-submit-${word}`);
|
| 33 |
+
const btnCancel = document.querySelector(`.ct-btn-cancel-${word}`);
|
| 34 |
+
|
| 35 |
+
btnCheck.classList.remove("hidden");
|
| 36 |
+
btnSend.classList.add("hidden");
|
| 37 |
+
btnCancel.classList.add("hidden");
|
| 38 |
+
}
|
| 39 |
+
|
| 40 |
+
async function sendRating(word) {
|
| 41 |
+
const containerBtn = document.querySelector(`.actions-${word}`);
|
| 42 |
+
addOrRemoveWaitSpin(containerBtn);
|
| 43 |
+
|
| 44 |
+
const formRatingWord = document.querySelector(`.form-rating-${word}`);
|
| 45 |
+
|
| 46 |
+
const dataForm = new FormData(formRatingWord);
|
| 47 |
+
const url = "/cata/testers/api/ratingword";
|
| 48 |
+
|
| 49 |
+
dataForm.set("name-word", word);
|
| 50 |
+
|
| 51 |
+
try {
|
| 52 |
+
const respone = await fetch(url, {
|
| 53 |
+
method: "POST",
|
| 54 |
+
headers: {
|
| 55 |
+
"X-CSRFToken": dataForm.get("csrfmiddlewaretoken"),
|
| 56 |
+
},
|
| 57 |
+
body: dataForm,
|
| 58 |
+
});
|
| 59 |
+
|
| 60 |
+
const jsonResponse = await respone.json();
|
| 61 |
+
|
| 62 |
+
if (jsonResponse.error) {
|
| 63 |
+
addOrRemoveWaitSpin(containerBtn, false, jsonResponse.error);
|
| 64 |
+
return;
|
| 65 |
+
}
|
| 66 |
+
|
| 67 |
+
remplaceForm(formRatingWord, jsonResponse.message);
|
| 68 |
+
if (isEndedRatingWords()) {
|
| 69 |
+
addBtnNextWord();
|
| 70 |
+
}
|
| 71 |
+
} catch (error) {
|
| 72 |
+
console.log("Error:", error);
|
| 73 |
+
}
|
| 74 |
+
}
|
| 75 |
+
|
| 76 |
+
function remplaceForm(oldForm, message) {
|
| 77 |
+
const articleContainer = document.createElement("article");
|
| 78 |
+
const thankYouMessage = document.createElement("p");
|
| 79 |
+
const messageResponse = document.createElement("p");
|
| 80 |
+
|
| 81 |
+
thankYouMessage.innerHTML =
|
| 82 |
+
"Palabra calificada,<br>gracias por la participación";
|
| 83 |
+
messageResponse.textContent = message;
|
| 84 |
+
|
| 85 |
+
articleContainer.classList.add(
|
| 86 |
+
"bg-gray-200",
|
| 87 |
+
"p-6",
|
| 88 |
+
"rounded-lg",
|
| 89 |
+
"mb-3",
|
| 90 |
+
"text-center"
|
| 91 |
+
);
|
| 92 |
+
thankYouMessage.classList.add("text-2xl", "font-bold");
|
| 93 |
+
messageResponse.classList.add("text-lg");
|
| 94 |
+
|
| 95 |
+
articleContainer.appendChild(thankYouMessage);
|
| 96 |
+
articleContainer.appendChild(messageResponse);
|
| 97 |
+
oldForm.replaceWith(articleContainer);
|
| 98 |
+
}
|
| 99 |
+
|
| 100 |
+
function addBtnNextWord() {
|
| 101 |
+
const thankYouMessage = document.createElement("p");
|
| 102 |
+
thankYouMessage.textContent = "Has finalizado con este producto";
|
| 103 |
+
thankYouMessage.classList.add("text-2xl", "font-bold", "mb-3");
|
| 104 |
+
|
| 105 |
+
const btnNesxtWord = document.createElement("button");
|
| 106 |
+
btnNesxtWord.classList.add(...BTN_CLASS_STYLE, "ct-btn-next-word");
|
| 107 |
+
btnNesxtWord.textContent = "Siguiente palabra";
|
| 108 |
+
btnNesxtWord.addEventListener("click", nextWord);
|
| 109 |
+
|
| 110 |
+
const articleContainer = document.createElement("article");
|
| 111 |
+
articleContainer.classList.add(
|
| 112 |
+
"bg-gray-200",
|
| 113 |
+
"p-6",
|
| 114 |
+
"rounded-lg",
|
| 115 |
+
"mb-3",
|
| 116 |
+
"text-center"
|
| 117 |
+
);
|
| 118 |
+
|
| 119 |
+
articleContainer.appendChild(thankYouMessage);
|
| 120 |
+
articleContainer.appendChild(btnNesxtWord);
|
| 121 |
+
|
| 122 |
+
const scalesContainer = document.querySelector(".scales-container");
|
| 123 |
+
scalesContainer.innerHTML = "";
|
| 124 |
+
scalesContainer.appendChild(articleContainer);
|
| 125 |
+
}
|
| 126 |
+
|
| 127 |
+
function isEndedRatingWords() {
|
| 128 |
+
const currentNumerWords = document.querySelectorAll(
|
| 129 |
+
'form[class*="form-rating-"]'
|
| 130 |
+
).length;
|
| 131 |
+
|
| 132 |
+
return !currentNumerWords;
|
| 133 |
+
}
|
| 134 |
+
|
| 135 |
+
/**
|
| 136 |
+
*
|
| 137 |
+
* @param {Event} e
|
| 138 |
+
*/
|
| 139 |
+
function nextWord(e) {
|
| 140 |
+
location.reload();
|
| 141 |
+
}
|
| 142 |
+
|
| 143 |
+
function createSpinCharge() {
|
| 144 |
+
const divSpin = document.createElement("div");
|
| 145 |
+
|
| 146 |
+
divSpin.classList.add(
|
| 147 |
+
"w-10",
|
| 148 |
+
"h-10",
|
| 149 |
+
"rounded-full",
|
| 150 |
+
"border-4",
|
| 151 |
+
"border-t-4",
|
| 152 |
+
"border-gray-200",
|
| 153 |
+
"border-t-blue-600",
|
| 154 |
+
"animate-spin"
|
| 155 |
+
);
|
| 156 |
+
|
| 157 |
+
return divSpin;
|
| 158 |
+
}
|
| 159 |
+
|
| 160 |
+
/**
|
| 161 |
+
*
|
| 162 |
+
* @param {Element} containerBtn
|
| 163 |
+
*/
|
| 164 |
+
function addOrRemoveWaitSpin(containerBtn, render = true, error = false) {
|
| 165 |
+
const actions = containerBtn.querySelector(`.btns-container`);
|
| 166 |
+
|
| 167 |
+
if (render) {
|
| 168 |
+
containerBtn.innerHTML = "";
|
| 169 |
+
const spin = createSpinCharge();
|
| 170 |
+
actions.classList.add("hidden");
|
| 171 |
+
containerBtn.appendChild(spin);
|
| 172 |
+
containerBtn.appendChild(actions);
|
| 173 |
+
containerBtn.classList.remove("items-end");
|
| 174 |
+
containerBtn.classList.add("items-center");
|
| 175 |
+
}
|
| 176 |
+
|
| 177 |
+
if (!render) {
|
| 178 |
+
containerBtn.innerHTML = "";
|
| 179 |
+
|
| 180 |
+
if (error) {
|
| 181 |
+
containerBtn.appendChild(createErrorSubmit(error));
|
| 182 |
+
}
|
| 183 |
+
|
| 184 |
+
containerBtn.append(actions);
|
| 185 |
+
actions.classList.remove("hidden");
|
| 186 |
+
containerBtn.classList.remove("items-center");
|
| 187 |
+
containerBtn.classList.add("items-end");
|
| 188 |
+
}
|
| 189 |
+
}
|
| 190 |
+
|
| 191 |
+
function createErrorSubmit(errorMessage) {
|
| 192 |
+
const containerError = document.createElement("div");
|
| 193 |
+
containerError.classList.add(
|
| 194 |
+
"w-full",
|
| 195 |
+
"p-2",
|
| 196 |
+
"bg-red-400",
|
| 197 |
+
"font-bold",
|
| 198 |
+
"text-center",
|
| 199 |
+
"rounded-lg"
|
| 200 |
+
);
|
| 201 |
+
|
| 202 |
+
const errorP = document.createElement("p");
|
| 203 |
+
errorP.textContent = errorMessage;
|
| 204 |
+
|
| 205 |
+
containerError.appendChild(errorP);
|
| 206 |
+
return containerError;
|
| 207 |
+
}
|
tecnicas/templates/tecnicas/forms_tester/convencional.html
ADDED
|
@@ -0,0 +1,182 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
{% extends 'tecnicas/layouts/base.html' %}
|
| 2 |
+
|
| 3 |
+
{% load static %}
|
| 4 |
+
|
| 5 |
+
{% block title %}Convencional{% endblock %}
|
| 6 |
+
|
| 7 |
+
{% block extra_css %}
|
| 8 |
+
<style>
|
| 9 |
+
input[type="range"]::-webkit-slider-thumb {
|
| 10 |
+
-webkit-appearance: none;
|
| 11 |
+
appearance: none;
|
| 12 |
+
width: 24px;
|
| 13 |
+
height: 24px;
|
| 14 |
+
border-radius: 50%;
|
| 15 |
+
background: var(--color-blue-500);
|
| 16 |
+
cursor: pointer;
|
| 17 |
+
}
|
| 18 |
+
|
| 19 |
+
input[type="range"]::-moz-range-thumb {
|
| 20 |
+
width: 24px;
|
| 21 |
+
height: 24px;
|
| 22 |
+
border-radius: 50%;
|
| 23 |
+
background: #3b82f6;
|
| 24 |
+
cursor: pointer;
|
| 25 |
+
}
|
| 26 |
+
</style>
|
| 27 |
+
{% endblock %}
|
| 28 |
+
|
| 29 |
+
{% block content %}
|
| 30 |
+
<article class="w-full flex flex-col justify-center items-center bg-gray-600 mt-10 mb-10">
|
| 31 |
+
<article class="flex flex-col gap-8 bg-gray-400 p-10 rounded">
|
| 32 |
+
<header class="text-center flex-row w-full flex justify-around items-center flex-wrap gap-10">
|
| 33 |
+
<h1 class="text-white rounded font-bold text-2xl bg-gray-600 p-4 flex-1">
|
| 34 |
+
Sesión usando técnica Convencional
|
| 35 |
+
</h1>
|
| 36 |
+
</header>
|
| 37 |
+
|
| 38 |
+
{% if error %}
|
| 39 |
+
<hr>
|
| 40 |
+
<article class="bg-red-600 p-4 text-white rounded-xl ct-notification-error">
|
| 41 |
+
<p class="block font-sans text-white text-xl antialiased font-bold uppercase tracking-wider text-center">
|
| 42 |
+
{{ error }}
|
| 43 |
+
</p>
|
| 44 |
+
</article>
|
| 45 |
+
{% endif %}
|
| 46 |
+
|
| 47 |
+
<article class="hidden">
|
| 48 |
+
<ul class="list-words">
|
| 49 |
+
{% for word in words %}
|
| 50 |
+
<li class="item-word">
|
| 51 |
+
<p class="word-id">
|
| 52 |
+
{{ word.id }}
|
| 53 |
+
</p>
|
| 54 |
+
<p class="word-name">
|
| 55 |
+
{{ word.nombre_palabra }}
|
| 56 |
+
</p>
|
| 57 |
+
</li>
|
| 58 |
+
{% endfor %}
|
| 59 |
+
</ul>
|
| 60 |
+
|
| 61 |
+
<ul class="list-tags">
|
| 62 |
+
{% for tag in tags %}
|
| 63 |
+
<li class="item-tag">
|
| 64 |
+
<p class="tag-id">
|
| 65 |
+
{{ tag.posicion }}
|
| 66 |
+
</p>
|
| 67 |
+
<p class="tag-name">
|
| 68 |
+
{{ tag.id_etiqueta }}
|
| 69 |
+
</p>
|
| 70 |
+
</li>
|
| 71 |
+
{% endfor %}
|
| 72 |
+
</ul>
|
| 73 |
+
|
| 74 |
+
<div class="scale-data">
|
| 75 |
+
<p class="scale-type">
|
| 76 |
+
{{ scale.id_tipo_escala }}
|
| 77 |
+
</p>
|
| 78 |
+
<p class="scale-size">
|
| 79 |
+
{{ scale.longitud }}
|
| 80 |
+
</p>
|
| 81 |
+
</div>
|
| 82 |
+
</article>
|
| 83 |
+
|
| 84 |
+
<article class="rounded flex flex-col gap-4">
|
| 85 |
+
<section class="flex items-center justify-center bg-gray-200 p-2 rounded-lg">
|
| 86 |
+
<p class="text-lg font-medium text-center">
|
| 87 |
+
{{ session.tecnica.instrucciones }}
|
| 88 |
+
</p>
|
| 89 |
+
</section>
|
| 90 |
+
<section class="flex items-center justify-center flex-wrap gap-4">
|
| 91 |
+
<div class="bg-gray-200 p-2 rounded-lg flex-1">
|
| 92 |
+
<p class="text-lg font-bold text-center">
|
| 93 |
+
Producto:
|
| 94 |
+
</p>
|
| 95 |
+
<p class="text-2xl font-bold text-center">
|
| 96 |
+
{{ product }}
|
| 97 |
+
</p>
|
| 98 |
+
</div>
|
| 99 |
+
<div class="bg-gray-200 p-2 rounded-lg flex-1">
|
| 100 |
+
<p class="text-lg font-bold text-center">
|
| 101 |
+
Repetición:
|
| 102 |
+
</p>
|
| 103 |
+
<p class="text-2xl font-bold text-center">
|
| 104 |
+
{{ session.tecnica.repecion }}
|
| 105 |
+
</p>
|
| 106 |
+
</div>
|
| 107 |
+
</section>
|
| 108 |
+
</article>
|
| 109 |
+
|
| 110 |
+
<article class="scales-container [&>*:not(:last-child)]:mb-5 flex flex-col items-center justify-center">
|
| 111 |
+
{% if type_scale == "continua" %}
|
| 112 |
+
{% for word in words %}
|
| 113 |
+
<form action="" method="post" class="form-rating-{{word}}">
|
| 114 |
+
{% csrf_token %}
|
| 115 |
+
<article class="bg-gray-200 p-6 rounded-lg mb-3 w-fit">
|
| 116 |
+
<label for="id-range-word-{{word}}"
|
| 117 |
+
class="text-xl font-bold tracking-wide block mb-6 first-letter:uppercase">{{ word }}</label>
|
| 118 |
+
|
| 119 |
+
<section class="block">
|
| 120 |
+
<div class="relative">
|
| 121 |
+
<input id="id-range-word-{{word}}" type="range" min="0" max="1000" value="500"
|
| 122 |
+
name="rating-word"
|
| 123 |
+
class="h-2 bg-gray-400 rounded-lg appearance-none cursor-pointer slider"
|
| 124 |
+
style="width: {{scale.longitud}}cm;">
|
| 125 |
+
|
| 126 |
+
<div class="absolute top-0 left-0 w-0.5 transform -translate-x-1/2 h-full bg-red-500 z-10">
|
| 127 |
+
</div>
|
| 128 |
+
|
| 129 |
+
<div
|
| 130 |
+
class="absolute top-1/5 left-1/2 w-0.5 transform -translate-x-1/2 h-4/5 bg-red-500 z-10">
|
| 131 |
+
</div>
|
| 132 |
+
|
| 133 |
+
<div class="absolute top-0 right-0 w-0.5 transform -translate-x-1/2 h-full bg-red-500 z-10">
|
| 134 |
+
</div>
|
| 135 |
+
</div>
|
| 136 |
+
|
| 137 |
+
<div class="flex justify-between mt-4">
|
| 138 |
+
<div class="flex flex-col items-start text-left w-[100px]">
|
| 139 |
+
<span class="text-xs font-medium text-gray-700 break-words first-letter:capitalize">
|
| 140 |
+
{{ tags.0.id_etiqueta }}
|
| 141 |
+
</span>
|
| 142 |
+
</div>
|
| 143 |
+
<div class="flex flex-col items-start text-center w-[100px]">
|
| 144 |
+
<span class="text-xs font-medium text-gray-700 break-words first-letter:capitalize">
|
| 145 |
+
{{ tags.1.id_etiqueta }}
|
| 146 |
+
</span>
|
| 147 |
+
</div>
|
| 148 |
+
<div class="flex flex-col items-start text-right w-[100px]">
|
| 149 |
+
<span class="text-xs font-medium text-gray-700 break-words first-letter:capitalize">
|
| 150 |
+
{{ tags.2.id_etiqueta }}
|
| 151 |
+
</span>
|
| 152 |
+
</div>
|
| 153 |
+
</div>
|
| 154 |
+
</section>
|
| 155 |
+
</article>
|
| 156 |
+
<article class="flex flex-col justify-center gap-2 items-end actions-{{word}}">
|
| 157 |
+
<section class="flex justify-end items-center gap-2 btns-container">
|
| 158 |
+
<button type="button" onclick="checkSendRating('{{word}}')"
|
| 159 |
+
class="ct-btn-check-{{word}} text-lg tracking-wider font-medium p-2 px-4 border-b-2 active:border-b-0 active:border-t-2 active:border-blue-500 border-blue-800 transition-all rounded-xl bg-blue-500 text-white w-fit disabled:bg-amber-600">
|
| 160 |
+
¿Guardar calificación?
|
| 161 |
+
</button>
|
| 162 |
+
<button type="button" onclick="sendRating('{{word}}')"
|
| 163 |
+
class="ct-btn-submit-{{word}} text-lg tracking-wider font-medium p-2 px-4 border-b-2 active:border-b-0 active:border-t-2 active:border-green-500 border-green-800 transition-all rounded-xl bg-green-500 text-white w-fit disabled:bg-amber-600 hidden">
|
| 164 |
+
Estoy seguro
|
| 165 |
+
</button>
|
| 166 |
+
<button type="button" onclick="cancelSendRating('{{word}}')"
|
| 167 |
+
class="ct-btn-cancel-{{word}} text-lg tracking-wider font-medium p-2 px-4 border-b-2 active:border-b-0 active:border-t-2 active:border-orange-500 border-orange-800 transition-all rounded-xl bg-orange-500 text-white w-fit disabled:bg-amber-600 hidden">
|
| 168 |
+
Cancelar
|
| 169 |
+
</button>
|
| 170 |
+
</section>
|
| 171 |
+
</article>
|
| 172 |
+
</form>
|
| 173 |
+
{% endfor %}
|
| 174 |
+
{% endif %}
|
| 175 |
+
</article>
|
| 176 |
+
</article>
|
| 177 |
+
</article>
|
| 178 |
+
{% endblock %}
|
| 179 |
+
|
| 180 |
+
{% block extra_js %}
|
| 181 |
+
<script src="{% static 'js/created-scale.js' %}"></script>
|
| 182 |
+
{% endblock %}
|
tecnicas/templates/tecnicas/forms_tester/main_tester.html
CHANGED
|
@@ -28,6 +28,16 @@
|
|
| 28 |
</article>
|
| 29 |
{% endif %}
|
| 30 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 31 |
<hr>
|
| 32 |
|
| 33 |
<article
|
|
@@ -88,6 +98,12 @@
|
|
| 88 |
<hr>
|
| 89 |
|
| 90 |
<article class="flex flex-wrap gap-10">
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 91 |
<button
|
| 92 |
class="ct-btn-start-repition flex-1 uppercase text-lg tracking-wider p-4 border-b-2 active:border-b-0 active:border-t-2 active:border-green-500 border-green-800 transition-all rounded-xl bg-green-600 text-white font-bold disabled:bg-amber-600 flex flex-col justify-center items-center gap-2"
|
| 93 |
onclick="startTest()">
|
|
@@ -96,6 +112,7 @@
|
|
| 96 |
<img src="{% static 'img/check.svg' %}" alt="flechas girando" class="invert">
|
| 97 |
</figure>
|
| 98 |
</button>
|
|
|
|
| 99 |
<button
|
| 100 |
class="flex-1 uppercase text-lg tracking-wider p-4 border-b-2 active:border-b-0 active:border-t-2 active:border-red-500 border-red-800 transition-all rounded-xl bg-red-600 text-white font-bold disabled:bg-amber-600 flex flex-col justify-center items-center gap-2">
|
| 101 |
Salir se la sesión
|
|
|
|
| 28 |
</article>
|
| 29 |
{% endif %}
|
| 30 |
|
| 31 |
+
{% if message %}
|
| 32 |
+
<hr>
|
| 33 |
+
|
| 34 |
+
<article class="bg-blue-600 p-4 text-white rounded-xl ct-notification-error">
|
| 35 |
+
<p class="block font-sans text-white text-xl antialiased font-bold uppercase tracking-wider text-center">
|
| 36 |
+
{{ message }}
|
| 37 |
+
</p>
|
| 38 |
+
</article>
|
| 39 |
+
{% endif %}
|
| 40 |
+
|
| 41 |
<hr>
|
| 42 |
|
| 43 |
<article
|
|
|
|
| 98 |
<hr>
|
| 99 |
|
| 100 |
<article class="flex flex-wrap gap-10">
|
| 101 |
+
{% if has_ended %}
|
| 102 |
+
<button
|
| 103 |
+
class="ct-btn-start-repition flex-1 uppercase text-lg tracking-wider p-4 border-b-2 active:border-b-0 active:border-t-2 active:border-green-500 border-green-800 transition-all rounded-xl bg-green-600 text-white font-bold disabled:bg-amber-600 flex flex-col justify-center items-center gap-2" disabled>
|
| 104 |
+
Finalizaste la sesión
|
| 105 |
+
</button>
|
| 106 |
+
{% else %}
|
| 107 |
<button
|
| 108 |
class="ct-btn-start-repition flex-1 uppercase text-lg tracking-wider p-4 border-b-2 active:border-b-0 active:border-t-2 active:border-green-500 border-green-800 transition-all rounded-xl bg-green-600 text-white font-bold disabled:bg-amber-600 flex flex-col justify-center items-center gap-2"
|
| 109 |
onclick="startTest()">
|
|
|
|
| 112 |
<img src="{% static 'img/check.svg' %}" alt="flechas girando" class="invert">
|
| 113 |
</figure>
|
| 114 |
</button>
|
| 115 |
+
{% endif %}
|
| 116 |
<button
|
| 117 |
class="flex-1 uppercase text-lg tracking-wider p-4 border-b-2 active:border-b-0 active:border-t-2 active:border-red-500 border-red-800 transition-all rounded-xl bg-red-600 text-white font-bold disabled:bg-amber-600 flex flex-col justify-center items-center gap-2">
|
| 118 |
Salir se la sesión
|
tecnicas/templates/tecnicas/layouts/base.html
CHANGED
|
@@ -18,7 +18,7 @@
|
|
| 18 |
</head>
|
| 19 |
|
| 20 |
<body>
|
| 21 |
-
<main class="flex flex-col w-screen h-screen overflow-x-hidden overflow-y-scroll bg-gray-600">
|
| 22 |
{% block content %}{% endblock %}
|
| 23 |
</main>
|
| 24 |
|
|
|
|
| 18 |
</head>
|
| 19 |
|
| 20 |
<body>
|
| 21 |
+
<main class="flex flex-col w-screen max-sm:w-full h-screen overflow-x-hidden max-xs:overflow-x-scroll overflow-y-scroll bg-gray-600">
|
| 22 |
{% block content %}{% endblock %}
|
| 23 |
</main>
|
| 24 |
|
tecnicas/urls.py
CHANGED
|
@@ -72,6 +72,10 @@ urlpatterns = [
|
|
| 72 |
views.mainTesterForm,
|
| 73 |
name="catador_main"),
|
| 74 |
|
|
|
|
|
|
|
|
|
|
|
|
|
| 75 |
# APIs
|
| 76 |
path("nueva-etiqueta",
|
| 77 |
views.newTag,
|
|
@@ -80,4 +84,8 @@ urlpatterns = [
|
|
| 80 |
path("api/palabras",
|
| 81 |
views.words,
|
| 82 |
name="api_palabras"),
|
|
|
|
|
|
|
|
|
|
|
|
|
| 83 |
]
|
|
|
|
| 72 |
views.mainTesterForm,
|
| 73 |
name="catador_main"),
|
| 74 |
|
| 75 |
+
path("testers/en-session/convencional",
|
| 76 |
+
views.convencionalScales,
|
| 77 |
+
name="session_convencional"),
|
| 78 |
+
|
| 79 |
# APIs
|
| 80 |
path("nueva-etiqueta",
|
| 81 |
views.newTag,
|
|
|
|
| 84 |
path("api/palabras",
|
| 85 |
views.words,
|
| 86 |
name="api_palabras"),
|
| 87 |
+
|
| 88 |
+
path("testers/api/ratingword",
|
| 89 |
+
views.reatingWord,
|
| 90 |
+
name="api_rating_word"),
|
| 91 |
]
|
tecnicas/views/__init__.py
CHANGED
|
@@ -18,5 +18,7 @@ from .tester_management.tester_search import testerSearch
|
|
| 18 |
|
| 19 |
from .apis.api_tag import newTag
|
| 20 |
from .apis.api_words import words
|
|
|
|
| 21 |
|
| 22 |
from .tester_forms.main_tester_form import mainTesterForm
|
|
|
|
|
|
| 18 |
|
| 19 |
from .apis.api_tag import newTag
|
| 20 |
from .apis.api_words import words
|
| 21 |
+
from .apis.rating_word import reatingWord
|
| 22 |
|
| 23 |
from .tester_forms.main_tester_form import mainTesterForm
|
| 24 |
+
from .tester_forms.convencional_scales import convencionalScales
|
tecnicas/views/apis/rating_word.py
ADDED
|
@@ -0,0 +1,17 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
from django.http import HttpRequest, JsonResponse
|
| 2 |
+
|
| 3 |
+
|
| 4 |
+
def reatingWord(req: HttpRequest):
|
| 5 |
+
if req.method == "POST":
|
| 6 |
+
if not req.POST["rating-word"]:
|
| 7 |
+
return JsonResponse({"error": "No se ha reconocido valor para la calificacion"})
|
| 8 |
+
rating = req.POST["rating-word"]
|
| 9 |
+
word = req.POST["name-word"]
|
| 10 |
+
return JsonResponse({
|
| 11 |
+
"message": "Ok",
|
| 12 |
+
"data": {
|
| 13 |
+
"word": word,
|
| 14 |
+
"rating": rating,
|
| 15 |
+
"cata_ser": req.session["cata_username"]
|
| 16 |
+
}
|
| 17 |
+
})
|
tecnicas/views/login_tester.py
CHANGED
|
@@ -21,6 +21,8 @@ def testerLogin(req: HttpRequest):
|
|
| 21 |
if isinstance(existCredentials, dict):
|
| 22 |
context = {"error": existCredentials["error"]}
|
| 23 |
return render(req, "tecnicas/cata-login.html", context)
|
|
|
|
|
|
|
| 24 |
|
| 25 |
taster_participation = login_controller.validateEntry()
|
| 26 |
if isinstance(taster_participation, dict):
|
|
@@ -29,6 +31,8 @@ def testerLogin(req: HttpRequest):
|
|
| 29 |
|
| 30 |
req.session["cata_username"] = tester_user
|
| 31 |
req.session["code_session"] = session_code
|
|
|
|
|
|
|
| 32 |
|
| 33 |
req.session.set_expiry(20*60)
|
| 34 |
return redirect(reverse("cata_system:catador_main"))
|
|
|
|
| 21 |
if isinstance(existCredentials, dict):
|
| 22 |
context = {"error": existCredentials["error"]}
|
| 23 |
return render(req, "tecnicas/cata-login.html", context)
|
| 24 |
+
|
| 25 |
+
session = existCredentials[1]
|
| 26 |
|
| 27 |
taster_participation = login_controller.validateEntry()
|
| 28 |
if isinstance(taster_participation, dict):
|
|
|
|
| 31 |
|
| 32 |
req.session["cata_username"] = tester_user
|
| 33 |
req.session["code_session"] = session_code
|
| 34 |
+
req.session["id_techniqe"] = session.tecnica.id
|
| 35 |
+
req.session["id_participation"] = taster_participation.id
|
| 36 |
|
| 37 |
req.session.set_expiry(20*60)
|
| 38 |
return redirect(reverse("cata_system:catador_main"))
|
tecnicas/views/tester_forms/convencional_scales.py
ADDED
|
@@ -0,0 +1,129 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
from django.http import HttpRequest
|
| 2 |
+
from django.shortcuts import redirect, render
|
| 3 |
+
from django.urls import reverse
|
| 4 |
+
from ...controllers import SesionController, PosicionController, CalificacionController, ParticipacionController, PalabrasController, EscalaController, DatoController
|
| 5 |
+
|
| 6 |
+
'''
|
| 7 |
+
**** Esta vista para sesion con tecnica convencional de escalas, al entrar debe:
|
| 8 |
+
**** ****
|
| 9 |
+
|
| 10 |
+
++++ Por el lado del servidor
|
| 11 |
+
++++ ++++
|
| 12 |
+
* Obtner los productos que se evaluan en la tecnica
|
| 13 |
+
* Ordenar los productos segun la Poscion en que se encuentre en el Orden ya establecidos
|
| 14 |
+
* Obtner las palabras para evaluar
|
| 15 |
+
- Revisar que estilo usan
|
| 16 |
+
- Obtner las palabras si el estilo es atributos
|
| 17 |
+
- Obtner las palabras si el estilo es Vocabulario
|
| 18 |
+
- El Catador plasma sus resultados para las palabras sin importar el estilo
|
| 19 |
+
* Comprobar que productos se han calificado
|
| 20 |
+
- Revisar el numero de palabras
|
| 21 |
+
- Comenzar con el primer producto e ir revisando uno a uno
|
| 22 |
+
- Revisar el numero de calificaciones del producto
|
| 23 |
+
- Numero de calificaciones del producto == 0
|
| 24 |
+
- Continuar con la evaluacion o comezar con este producto
|
| 25 |
+
- Numero de calificaciones del producto < numero de palabras
|
| 26 |
+
- Continuar con la evaluacion
|
| 27 |
+
- Numero de calificacion == numero de palabras
|
| 28 |
+
- Pasar con el siguiente producto
|
| 29 |
+
* Si no quedan mas productos por revisar
|
| 30 |
+
- Participacion.finalizado = True
|
| 31 |
+
- Participacion.activo = False
|
| 32 |
+
- Redirigir a "catador_main"
|
| 33 |
+
* Optner la siguiente palabra sin calificar
|
| 34 |
+
- Obtener las calificaiones de producto
|
| 35 |
+
- Obtener los datos de las calificaciones
|
| 36 |
+
- Comprobar que palabras no estan tienen dato
|
| 37 |
+
- Mandar palabras para el usuario
|
| 38 |
+
* Obtener informacion de la escala para mandar
|
| 39 |
+
|
| 40 |
+
++++ Por el lado del cliente
|
| 41 |
+
++++ ++++
|
| 42 |
+
+ Mostrar en todo momento las instrucciones en la parte superior de la pagina
|
| 43 |
+
+ Mostrar la repeticion en la que esta
|
| 44 |
+
+ Mostrar el producto que esta calificando
|
| 45 |
+
+ Desglozar las palabras para calificar
|
| 46 |
+
- Cada palabra debe contar con su input segun el tipo
|
| 47 |
+
- Para cada input se debe poder guardar la calificacion
|
| 48 |
+
- Anstes de guardar la calificacion preguntar por la confirmacion a la hora de guardar el dato
|
| 49 |
+
- Especficar las etiquetas por debajo del input de ripo rango
|
| 50 |
+
- Para las escalas de tipo continua
|
| 51 |
+
- La longitud de la barra de la escala debe ser igual al tamaño que se especifico en la configuracion
|
| 52 |
+
- Contar con un input de tipo range
|
| 53 |
+
- Contar con etiqueta en el inicio de la barra, en el medio y al final
|
| 54 |
+
- La escala debe terner marcas al inicio, medio y final
|
| 55 |
+
- El rango de la barra debe ir de 0 a 1000
|
| 56 |
+
- Para las escalas de tipo estructurada
|
| 57 |
+
- Su longitud sera tan largo como el contendor que lo aloja
|
| 58 |
+
- La barra se divide segun el numero de etiquetas que estas posean
|
| 59 |
+
- Cata longitud debe poser una marca y solo estas seran las unicas posibles respuestas
|
| 60 |
+
- Cata segmento en el que se divide debe tener la etiqueda correspondiente por debajo
|
| 61 |
+
'''
|
| 62 |
+
|
| 63 |
+
|
| 64 |
+
def convencionalScales(req: HttpRequest):
|
| 65 |
+
if not "id_order" in req.session:
|
| 66 |
+
return redirect(reverse("cata_system:catador_main"))
|
| 67 |
+
|
| 68 |
+
session = SesionController.getSessionByCode(req.session["code_session"])
|
| 69 |
+
technique = session.tecnica
|
| 70 |
+
|
| 71 |
+
context = {
|
| 72 |
+
"session": session
|
| 73 |
+
}
|
| 74 |
+
|
| 75 |
+
if req.method == "GET":
|
| 76 |
+
positions = PosicionController.getPostionsInOrder(
|
| 77 |
+
id_order=req.session["id_order"])
|
| 78 |
+
|
| 79 |
+
sorted_positions = sorted(positions, key=lambda posi: posi.posicion)
|
| 80 |
+
|
| 81 |
+
words = PalabrasController.getWordsInTechnique(technique=technique)
|
| 82 |
+
|
| 83 |
+
next_position = CalificacionController.checkProducsWithoutRating(
|
| 84 |
+
positions=sorted_positions,
|
| 85 |
+
user_cata=req.session["cata_username"],
|
| 86 |
+
id_technique=req.session["id_techniqe"],
|
| 87 |
+
repetition=session.tecnica.repecion,
|
| 88 |
+
technique=technique,
|
| 89 |
+
num_words=len(words)
|
| 90 |
+
)
|
| 91 |
+
|
| 92 |
+
if isinstance(next_position, dict):
|
| 93 |
+
updated_participation = ParticipacionController.finishSession(
|
| 94 |
+
req.session["id_participation"])
|
| 95 |
+
return redirect(reverse("cata_system:catador_main"))
|
| 96 |
+
|
| 97 |
+
if isinstance(next_position, list):
|
| 98 |
+
next_position = next_position[0]
|
| 99 |
+
|
| 100 |
+
context["product"] = next_position.id_producto
|
| 101 |
+
|
| 102 |
+
ratings_product = CalificacionController.getRatings(
|
| 103 |
+
technique=technique,
|
| 104 |
+
product=next_position.id_producto,
|
| 105 |
+
repetition=technique.repecion,
|
| 106 |
+
user_tester=req.session["cata_username"]
|
| 107 |
+
)
|
| 108 |
+
|
| 109 |
+
if isinstance(ratings_product, dict):
|
| 110 |
+
context["error"] = ratings_product["error"]
|
| 111 |
+
return render(req, "tecnicas/forms_tester/convencional.html", context)
|
| 112 |
+
elif not ratings_product:
|
| 113 |
+
context["words"] = words
|
| 114 |
+
else:
|
| 115 |
+
recoreded_data = DatoController.getRerecordedData(ratings=ratings_product)
|
| 116 |
+
if not recoreded_data:
|
| 117 |
+
context["words"] = words
|
| 118 |
+
|
| 119 |
+
words_to_use = PalabrasController.getWordsWithoutData(recoreded_data=recoreded_data, words=words)
|
| 120 |
+
context["words"] = words_to_use
|
| 121 |
+
|
| 122 |
+
scale = EscalaController.getScaleByTechnique(technique=technique)
|
| 123 |
+
context["scale"] = scale
|
| 124 |
+
context["type_scale"] = scale.id_tipo_escala.nombre_escala
|
| 125 |
+
|
| 126 |
+
use_tags = EscalaController.getRelatedTagsInScale(scale=scale)
|
| 127 |
+
context["tags"] = use_tags
|
| 128 |
+
|
| 129 |
+
return render(req, "tecnicas/forms_tester/convencional.html", context)
|
tecnicas/views/tester_forms/main_tester_form.py
CHANGED
|
@@ -1,7 +1,7 @@
|
|
| 1 |
from django.http import HttpRequest, JsonResponse
|
| 2 |
-
from django.shortcuts import render
|
| 3 |
-
from
|
| 4 |
-
from ...
|
| 5 |
|
| 6 |
|
| 7 |
def mainTesterForm(req: HttpRequest):
|
|
@@ -12,28 +12,45 @@ def mainTesterForm(req: HttpRequest):
|
|
| 12 |
"session": session
|
| 13 |
}
|
| 14 |
|
|
|
|
|
|
|
|
|
|
| 15 |
if req.method == "GET":
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 16 |
return render(req, "tecnicas/forms_tester/main_tester.html", context)
|
| 17 |
elif req.method == "POST":
|
| 18 |
if req.POST["action"] == "start_posting":
|
| 19 |
-
|
| 20 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
| 21 |
|
| 22 |
-
|
| 23 |
-
if not isinstance(order, dict):
|
| 24 |
-
req.session["id_order"] = order.id
|
| 25 |
-
context["error"] = "Catador tiene orden"
|
| 26 |
-
return render(req, "tecnicas/forms_tester/main_tester.html", context)
|
| 27 |
|
| 28 |
order = view_controller.assignOrder()
|
| 29 |
if isinstance(order, dict):
|
| 30 |
context["error"] = order["error"]
|
| 31 |
return render(req, "tecnicas/forms_tester/main_tester.html", context)
|
| 32 |
|
| 33 |
-
|
| 34 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 35 |
elif req.POST["action"] == "close_session":
|
| 36 |
-
|
|
|
|
| 37 |
else:
|
| 38 |
context["error"] = "Acción sin especificar"
|
| 39 |
return render(req, "tecnicas/forms_tester/main_tester.html", context)
|
|
|
|
| 1 |
from django.http import HttpRequest, JsonResponse
|
| 2 |
+
from django.shortcuts import render, redirect
|
| 3 |
+
from django.urls import reverse
|
| 4 |
+
from ...controllers import SesionController, MainTesterFormController, ParticipacionController
|
| 5 |
|
| 6 |
|
| 7 |
def mainTesterForm(req: HttpRequest):
|
|
|
|
| 12 |
"session": session
|
| 13 |
}
|
| 14 |
|
| 15 |
+
view_controller = MainTesterFormController(
|
| 16 |
+
req.session["code_session"], req.session["cata_username"])
|
| 17 |
+
|
| 18 |
if req.method == "GET":
|
| 19 |
+
order = view_controller.checkAssignOrder()
|
| 20 |
+
|
| 21 |
+
if not isinstance(order, dict):
|
| 22 |
+
req.session["id_order"] = order.id
|
| 23 |
+
if view_controller.isEndedSession(id_participation=req.session["id_participation"], repetition=session.tecnica.repecion):
|
| 24 |
+
context["message"] = "El catador ha terminado de realizar su evaluación, espere instrucciones del presentador"
|
| 25 |
+
context["has_ended"] = True
|
| 26 |
+
|
| 27 |
return render(req, "tecnicas/forms_tester/main_tester.html", context)
|
| 28 |
elif req.method == "POST":
|
| 29 |
if req.POST["action"] == "start_posting":
|
| 30 |
+
if "id_order" in req.session:
|
| 31 |
+
update_participation = ParticipacionController.enterSession(
|
| 32 |
+
id_participation=req.session["id_participation"])
|
| 33 |
+
if isinstance(update_participation, dict):
|
| 34 |
+
context["error"] = update_participation["error"]
|
| 35 |
+
return render(req, "tecnicas/forms_tester/main_tester.html", context)
|
| 36 |
|
| 37 |
+
return redirect(reverse("cata_system:session_convencional"))
|
|
|
|
|
|
|
|
|
|
|
|
|
| 38 |
|
| 39 |
order = view_controller.assignOrder()
|
| 40 |
if isinstance(order, dict):
|
| 41 |
context["error"] = order["error"]
|
| 42 |
return render(req, "tecnicas/forms_tester/main_tester.html", context)
|
| 43 |
|
| 44 |
+
update_participation = ParticipacionController.enterSession(
|
| 45 |
+
id_participation=req.session["id_participation"])
|
| 46 |
+
if isinstance(update_participation, dict):
|
| 47 |
+
context["error"] = update_participation["error"]
|
| 48 |
+
return render(req, "tecnicas/forms_tester/main_tester.html", context)
|
| 49 |
+
|
| 50 |
+
return redirect(reverse("cata_system:session_convencional"))
|
| 51 |
elif req.POST["action"] == "close_session":
|
| 52 |
+
req.session.flush()
|
| 53 |
+
return redirect(reverse("cata_system:catador_login"))
|
| 54 |
else:
|
| 55 |
context["error"] = "Acción sin especificar"
|
| 56 |
return render(req, "tecnicas/forms_tester/main_tester.html", context)
|