Feat: Implementar SCAA Score y conversión bidireccional
All checks were successful
build-and-deploy / build-and-deploy (push) Successful in 1m7s
All checks were successful
build-and-deploy / build-and-deploy (push) Successful in 1m7s
CAMBIOS PRINCIPALES: 1. Nueva fórmula de SCAA Score: - S = 0.65625 × Σhᵢ + 52.75 - 2u - 4d - Donde hᵢ = puntaje afectivo (1-9) - u = tazas no uniformes, d = tazas defectuosas 2. Funciones de cálculo (catacion.ts): - calcularSumatoriaAfectiva(): suma de valores afectivos - calcularSCAA(): calcula SCAA Score con penalizaciones - scaaASumatoriaAfectiva(): conversión inversa (sin penalizaciones) - sumatoriaAfectivaASCAA(): conversión directa (sin penalizaciones) 3. FormularioMuestra.vue: - Mostrar ambos scores en el acordeón - "Sumatoria Afectiva" (entero, suma de afectivos) - "SCAA Score" (decimal, con 2 decimales) 4. ModalAsignacionRapida.vue: - Doble input: Sumatoria Afectiva + SCAA Score - Sincronización bidireccional automática - Al modificar Sumatoria → actualiza SCAA - Al modificar SCAA → calcula Sumatoria más cercana - Validación y redondeo para mantener enteros válidos - Rango: Sumatoria 9-90, SCAA 58.65-112.00 NOTAS: - En asignación rápida no se toman en cuenta penalizaciones - SCAA Score acepta decimales, Sumatoria solo enteros - Múltiples SCAA Scores pueden apuntar al mismo entero
This commit is contained in:
@@ -801,16 +801,22 @@
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Puntaje Final (solo lectura) -->
|
||||
<div class="global-section p-4 cata-outline-box rounded-lg">
|
||||
<div class="puntaje-final">
|
||||
<!-- Puntajes (solo lectura) -->
|
||||
<div class="global-section p-4 cata-outline-box rounded-lg space-y-4">
|
||||
<!-- Sumatoria Afectiva -->
|
||||
<div class="puntaje-item">
|
||||
<div class="flex items-baseline justify-between">
|
||||
<span class="text-sm cata-text opacity-75">Puntaje Final:</span>
|
||||
<span class="text-3xl font-bold cata-text">{{ muestra.puntajeFinal }}</span>
|
||||
<span class="text-sm cata-text opacity-75">Sumatoria Afectiva:</span>
|
||||
<span class="text-2xl font-bold cata-text">{{ sumatoriaAfectiva }}</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- SCAA Score -->
|
||||
<div class="puntaje-item">
|
||||
<div class="flex items-baseline justify-between">
|
||||
<span class="text-sm cata-text opacity-75">SCAA Score:</span>
|
||||
<span class="text-3xl font-bold cata-text">{{ scaaScore.toFixed(2) }}</span>
|
||||
</div>
|
||||
<p class="text-xs cata-text opacity-60 mt-1">
|
||||
Suma de valores afectivos
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@@ -820,7 +826,7 @@
|
||||
<script setup lang="ts">
|
||||
import type { Muestra, NotaSeleccionada, TipoDefecto, SensacionBoca, GustoPredominante } from '~/types/catacion'
|
||||
import type { TabCatacion, Subcategoria } from '~/composables/useCatacion'
|
||||
import { SENSACIONES_BOCA, GUSTOS_PREDOMINANTES, TIPOS_DEFECTOS } from '~/types/catacion'
|
||||
import { SENSACIONES_BOCA, GUSTOS_PREDOMINANTES, TIPOS_DEFECTOS, calcularSumatoriaAfectiva, calcularSCAA } from '~/types/catacion'
|
||||
|
||||
interface FormularioMuestraProps {
|
||||
/** Muestra a editar */
|
||||
@@ -858,6 +864,10 @@ const sensacionesBoca = SENSACIONES_BOCA
|
||||
const gustosPredominantes = GUSTOS_PREDOMINANTES
|
||||
const tiposDefectos = TIPOS_DEFECTOS
|
||||
|
||||
// Cálculos de puntajes
|
||||
const sumatoriaAfectiva = computed(() => calcularSumatoriaAfectiva(props.muestra))
|
||||
const scaaScore = computed(() => calcularSCAA(props.muestra))
|
||||
|
||||
// Helpers para filtrado por subcategorías
|
||||
const deberMostrarSeccion = (subcategorias: Subcategoria[]): boolean => {
|
||||
// Si no hay filtros activos, mostrar todo
|
||||
|
||||
@@ -22,15 +22,40 @@
|
||||
<template #body>
|
||||
<div class="space-y-4">
|
||||
<!-- Paso 1: Ingresar puntaje total deseado -->
|
||||
<div v-if="paso === 1">
|
||||
<input
|
||||
v-model.number="puntajeDeseado"
|
||||
type="number"
|
||||
:min="9"
|
||||
:max="90"
|
||||
placeholder="Puntaje Total (9-90)"
|
||||
class="cata-input w-full px-3 py-2 rounded-md text-center text-lg"
|
||||
/>
|
||||
<div v-if="paso === 1" class="space-y-3">
|
||||
<!-- Input de Sumatoria Afectiva -->
|
||||
<div>
|
||||
<label class="block text-xs cata-text opacity-75 mb-1 text-center">
|
||||
Sumatoria Afectiva
|
||||
</label>
|
||||
<input
|
||||
v-model.number="puntajeDeseado"
|
||||
type="number"
|
||||
:min="9"
|
||||
:max="90"
|
||||
step="1"
|
||||
placeholder="9-90"
|
||||
class="cata-input w-full px-3 py-2 rounded-md text-center text-lg"
|
||||
@input="onSumatoriaChange"
|
||||
/>
|
||||
</div>
|
||||
|
||||
<!-- Input de SCAA Score -->
|
||||
<div>
|
||||
<label class="block text-xs cata-text opacity-75 mb-1 text-center">
|
||||
SCAA Score
|
||||
</label>
|
||||
<input
|
||||
v-model.number="scaaDeseado"
|
||||
type="number"
|
||||
:min="scaaMin"
|
||||
:max="scaaMax"
|
||||
step="0.01"
|
||||
placeholder="58.65-112.00"
|
||||
class="cata-input w-full px-3 py-2 rounded-md text-center text-lg"
|
||||
@input="onScaaChange"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Paso 2: Seleccionar categorías que sobresalen o palidecen -->
|
||||
@@ -121,6 +146,7 @@
|
||||
|
||||
<script setup lang="ts">
|
||||
import type { Muestra } from '~/types/catacion'
|
||||
import { scaaASumatoriaAfectiva, sumatoriaAfectivaASCAA } from '~/types/catacion'
|
||||
|
||||
interface Props {
|
||||
modelValue: boolean
|
||||
@@ -155,17 +181,70 @@ const isOpen = computed({
|
||||
// Estado del formulario
|
||||
const paso = ref(1)
|
||||
const puntajeDeseado = ref<number>(45)
|
||||
const scaaDeseado = ref<number>(sumatoriaAfectivaASCAA(45))
|
||||
const categoriasSeleccionadas = ref<string[]>([])
|
||||
|
||||
// Flag para evitar loops infinitos en la sincronización
|
||||
const actualizandoInput = ref(false)
|
||||
|
||||
// Límites de SCAA Score (basados en sumatoria afectiva 9-90)
|
||||
const scaaMin = sumatoriaAfectivaASCAA(9)
|
||||
const scaaMax = sumatoriaAfectivaASCAA(90)
|
||||
|
||||
// Resetear estado cuando el modal se abre
|
||||
watch(isOpen, (newValue) => {
|
||||
if (newValue) {
|
||||
paso.value = 1
|
||||
puntajeDeseado.value = 45
|
||||
scaaDeseado.value = sumatoriaAfectivaASCAA(45)
|
||||
categoriasSeleccionadas.value = []
|
||||
}
|
||||
})
|
||||
|
||||
// Handler para cuando se modifica Sumatoria Afectiva
|
||||
const onSumatoriaChange = () => {
|
||||
if (actualizandoInput.value) return
|
||||
|
||||
actualizandoInput.value = true
|
||||
|
||||
// Validar rango
|
||||
if (puntajeDeseado.value < 9) puntajeDeseado.value = 9
|
||||
if (puntajeDeseado.value > 90) puntajeDeseado.value = 90
|
||||
|
||||
// Redondear a entero
|
||||
puntajeDeseado.value = Math.round(puntajeDeseado.value)
|
||||
|
||||
// Actualizar SCAA Score
|
||||
scaaDeseado.value = sumatoriaAfectivaASCAA(puntajeDeseado.value)
|
||||
|
||||
actualizandoInput.value = false
|
||||
}
|
||||
|
||||
// Handler para cuando se modifica SCAA Score
|
||||
const onScaaChange = () => {
|
||||
if (actualizandoInput.value) return
|
||||
|
||||
actualizandoInput.value = true
|
||||
|
||||
// Validar rango
|
||||
if (scaaDeseado.value < scaaMin) scaaDeseado.value = scaaMin
|
||||
if (scaaDeseado.value > scaaMax) scaaDeseado.value = scaaMax
|
||||
|
||||
// Convertir a Sumatoria Afectiva
|
||||
const sumatoriaCalculada = scaaASumatoriaAfectiva(scaaDeseado.value)
|
||||
|
||||
// Redondear al entero más cercano (sumatoria afectiva debe ser entero)
|
||||
const sumatoriaRedondeada = Math.round(sumatoriaCalculada)
|
||||
|
||||
// Asegurar rango válido
|
||||
puntajeDeseado.value = Math.max(9, Math.min(90, sumatoriaRedondeada))
|
||||
|
||||
// Recalcular SCAA Score con el valor redondeado
|
||||
scaaDeseado.value = sumatoriaAfectivaASCAA(puntajeDeseado.value)
|
||||
|
||||
actualizandoInput.value = false
|
||||
}
|
||||
|
||||
// Cálculos
|
||||
const puntajeValido = computed(() => {
|
||||
return puntajeDeseado.value >= 9 && puntajeDeseado.value <= 90
|
||||
|
||||
Reference in New Issue
Block a user