|
|
|
@@ -0,0 +1,20 @@
|
|
|
|
|
const S=[
|
|
|
|
|
['req','Requerimientos','Capacidades y restricciones',[['Funcionales identificados, numerados y sin decisiones de implementación','Cada requisito expresa una capacidad observable.'],['No funcionales clasificados','Considerar seguridad, desempeño, usabilidad, portabilidad y disponibilidad.'],['Alcance, actores y glosario acordados','El vocabulario es consistente en todos los artefactos.'],['Cada requisito se vincula con casos de uso','La matriz permite recorrer REQ → CU.'],['Al menos un criterio de aceptación por requisito','Debe ser comprobable y describir el resultado esperado.']]],
|
|
|
|
|
['cu','Casos de uso y especificaciones','Comportamiento desde la mirada del actor',[['Diagrama general con actores, casos y límite del sistema','Cada actor persigue un objetivo claro.'],['include y extend usados con sentido','include es obligatorio reutilizado; extend, opcional o condicionado.'],['Una especificación por caso relevante','Incluye objetivo, actor, precondiciones, disparador y postcondiciones.'],['Curso básico escrito en voz activa','Cada paso muestra actor, acción y respuesta del sistema.'],['Alternativos, excepciones y reglas documentados','Cada desvío tiene condición, respuesta y cierre.'],['Hito RRR revisado con interesados','Casos de uso, dominio y prototipo capturan los requerimientos.']]],
|
|
|
|
|
['dom','Modelo de dominio','Vocabulario conceptual del problema',[['Clases tomadas del lenguaje del negocio','No incluye pantallas, controles ni detalles técnicos.'],['Atributos conceptuales relevantes','Evita claves foráneas y decisiones de persistencia.'],['Relaciones y multiplicidades justificadas','Cada asociación expresa un hecho del dominio.'],['Nombres sin sinónimos ni ambigüedades','El mismo concepto conserva su nombre.'],['Modelo actualizado después de robustez','Todas las entidades descubiertas aparecen en el dominio.']]],
|
|
|
|
|
['ui','Prototipo','Fronteras y recorrido del usuario',[['Pantallas y estados relevantes representados','Incluye formularios, listados, mensajes, confirmaciones y errores.'],['Cada pantalla se vincula con casos y actores','La navegación materializa cursos básicos y alternativos.'],['Controles y datos coinciden con las especificaciones','No hay acciones huérfanas ni entradas faltantes.'],['Prototipo revisado con usuarios','Se registraron observaciones y decisiones.'],['Se usa como especificación, no como producto final','Sirve para desambiguar y descubrir fronteras.']]],
|
|
|
|
|
['arch','Arquitectura','Estructura y decisiones técnicas',[['Vistas funcional, de datos y del sistema separadas','Cada una responde una pregunta arquitectónica.'],['Componentes, capas, responsabilidades e interfaces visibles','Las dependencias respetan el estilo declarado.'],['Despliegue, nodos y tecnologías documentados','Incluye persistencia e integraciones externas.'],['Decisiones justificadas por requerimientos','No se basan sólo en preferencias tecnológicas.'],['Calidad y testing considerados','Contempla cambio, seguridad, rendimiento y comprobabilidad.']]],
|
|
|
|
|
['rob','Diagramas de robustez','Puente entre casos de uso y diseño',[['Un diagrama por caso de uso diseñado','El texto se sigue frase por frase.'],['Actor, Boundary, Control y Entity diferenciados','Fronteras y entidades son sustantivos; controles, acciones.'],['Reglas de comunicación respetadas','Actor↔Boundary; Boundary↔Control; Entity↔Control.'],['Una frontera clara por pantalla o interfaz','Los nombres coinciden con prototipo y texto.'],['Entidades consistentes con el dominio','Toda entidad está en el modelo actualizado.'],['Controles cubren cursos básicos y alternativos','Sin asignar todavía métodos ni algoritmos.'],['Hito PDR aprobado','Texto, robustez, dominio, datos y arquitectura son consistentes.']]],
|
|
|
|
|
['seq','Diagramas de secuencia','Diseño detallado por escenario',[['Un diagrama por caso de uso','Incluye curso básico y alternativos.'],['Participantes derivados de robustez','No aparecen objetos sin responsabilidad explicada.'],['Texto del caso mapeado a mensajes','Orden, retornos, condiciones y ciclos son visibles.'],['Controles asignados a operaciones u objetos','Cada mensaje llega al responsable del comportamiento.'],['Mensajes respetan arquitectura y patrones','El detalle orienta la implementación.'],['Errores y resultados observables representados','Las respuestas regresan a la frontera.']]],
|
|
|
|
|
['class','Diagrama de clases','Modelo estático listo para implementar',[['Clases con responsabilidades, atributos y operaciones','Las operaciones surgen de secuencia.'],['Tipos, visibilidad y firmas especificados','Los contratos permiten comprender la colaboración.'],['Relaciones y multiplicidades correctas','Herencia y composición tienen necesidad demostrable.'],['Alta cohesión y bajo acoplamiento revisados','Cada clase protege un secreto coherente.'],['Interfaces aíslan decisiones que pueden cambiar','Se aplica ocultamiento de información.'],['Consistencia con dominio, secuencias y código','No faltan ni sobran elementos sin trazabilidad.'],['Hito CDR aprobado','Diseño completo, correcto, realizable y alineado.']]],
|
|
|
|
|
['patterns','Patrones de diseño','Problema, decisión y consecuencias',[['Cada patrón resuelve un problema concreto','Se explica contexto y necesidad.'],['Participantes y colaboraciones identificados','Las clases del TP se mapean a roles.'],['Clases reflejan la estructura del patrón','No es sólo un ejemplo genérico copiado.'],['Secuencias reflejan su comportamiento','Los mensajes muestran un escenario real.'],['Alternativas, beneficios y costos documentados','Evalúa acoplamiento, extensión y complejidad.']]],
|
|
|
|
|
['test','Testing estructural','Pruebas derivadas del código',[['Unidad, especificación y dominio de entrada definidos','Cada caso usa valores concretos y salida esperada.'],['Grafo de flujo de control construido','Nodos, decisiones y flechas corresponden al código.'],['Criterio de cobertura declarado','Distingue sentencias, ramas, condiciones y caminos.'],['Conjunto de pruebas satisface el criterio','Vincula entrada, camino, esperado y obtenido.'],['Cobertura medida y evidencia adjunta','Incluye reporte o cálculo verificable.'],['Casos normales, límites y fallas incluidos','La selección busca revelar defectos.'],['Pruebas re-ejecutables y resultado registrado','Documenta ambiente, versión, fecha y estado.'],['Trazabilidad hasta TEST comprobada','Una prueba demuestra cada requisito del alcance.']]]];
|
|
|
|
|
const K='sap-tfi-checklist-v1',root=document.querySelector('#checklist-sections'),index=document.querySelector('#section-index');let st=JSON.parse(localStorage.getItem(K)||'{}'),filter='all',query='';
|
|
|
|
|
const items=S.flatMap(([sid,,,a])=>a.map((x,i)=>[`${sid}-${i}`, ...x]));
|
|
|
|
|
const get=id=>st[id]||{done:false,evidence:''},esc=v=>(v||'').replace(/[&<>"']/g,c=>({'&':'&','<':'<','>':'>','"':'"',"'":'''}[c])),save=()=>localStorage.setItem(K,JSON.stringify(st));
|
|
|
|
|
function match(id,t,h){const x=get(id);return(filter==='all'||(filter==='done'?x.done:!x.done))&&`${t} ${h}`.toLowerCase().includes(query)}
|
|
|
|
|
function render(){root.innerHTML=S.map(([sid,title,sub,a],n)=>{const done=a.filter((_,i)=>get(`${sid}-${i}`).done).length,vis=a.map((x,i)=>[`${sid}-${i}`,...x]).filter(x=>match(...x));return`<article class="check-section open" id="section-${sid}" ${vis.length?'':'hidden'}><button class="section-head" aria-expanded="true"><span class="section-number">${String(n+1).padStart(2,'0')}</span><span><h2>${title}</h2><p>${sub}</p></span><span class="section-progress"><b>${done}/${a.length}</b><small>completos</small></span><span class="chevron">⌃</span></button><div class="section-body">${vis.map(row).join('')}</div></article>`}).join('');if(!root.querySelector('.check-section:not([hidden])'))root.innerHTML='<div class="empty-state">No hay criterios que coincidan con este filtro.</div>';index.innerHTML=S.map(([sid,t,,a])=>`<a href="#section-${sid}"><span>${t}</span><b class="count">${a.filter((_,i)=>get(`${sid}-${i}`).done).length}/${a.length}</b></a>`).join('');bind();total()}
|
|
|
|
|
function row([id,t,h]){const x=get(id);return`<div class="check-item ${x.done?'done':''}" data-id="${id}"><input id="${id}" type="checkbox" ${x.done?'checked':''}><div class="item-copy"><label for="${id}">${t}</label><p>${h}</p><input class="evidence-input" aria-label="Evidencia para ${t}" placeholder="Evidencia: archivo, página, URL, captura o reporte…" value="${esc(x.evidence)}"></div></div>`}
|
|
|
|
|
function bind(){document.querySelectorAll('.section-head').forEach(b=>b.onclick=()=>{const c=b.closest('.check-section');c.classList.toggle('open');b.setAttribute('aria-expanded',c.classList.contains('open'))});document.querySelectorAll('.check-item').forEach(r=>{const id=r.dataset.id,c=r.querySelector('[type=checkbox]'),e=r.querySelector('.evidence-input');c.onchange=()=>{st[id]={done:c.checked,evidence:e.value};save();render()};e.oninput=()=>{st[id]={done:c.checked,evidence:e.value};save()}})}
|
|
|
|
|
function total(){const done=items.filter(([id])=>get(id).done).length;document.querySelector('#total-percent').textContent=`${Math.round(done/items.length*100)}%`;document.querySelector('#total-copy').textContent=`${done} de ${items.length} criterios`}
|
|
|
|
|
document.querySelector('#search').oninput=e=>{query=e.target.value.trim().toLowerCase();render()};document.querySelectorAll('[data-filter]').forEach(b=>b.onclick=()=>{filter=b.dataset.filter;document.querySelectorAll('[data-filter]').forEach(x=>x.classList.toggle('active',x===b));render()});document.querySelector('#expand-all').onclick=e=>{const a=[...document.querySelectorAll('.check-section')],open=a.some(c=>!c.classList.contains('open'));a.forEach(c=>c.classList.toggle('open',open));e.target.textContent=open?'Contraer todo':'Expandir todo'};document.querySelector('#reset-checklist').onclick=()=>{if(confirm('¿Borrar todos los tildes y evidencias?')){st={};save();render()}};render();
|