diff --git a/intermedio/ejercicios/79-visor-modelos-3d/resoluciones/maria-montepeque/maria-montepeque.css b/intermedio/ejercicios/79-visor-modelos-3d/resoluciones/maria-montepeque/maria-montepeque.css new file mode 100644 index 0000000..df1afb5 --- /dev/null +++ b/intermedio/ejercicios/79-visor-modelos-3d/resoluciones/maria-montepeque/maria-montepeque.css @@ -0,0 +1,106 @@ +body { + font-family: Arial, Helvetica, sans-serif; + background-color: #181a20; + color: #e6e6f0; + padding: 24px; + max-width: 860px; + margin: 0 auto; +} + +h1 { + margin-bottom: 4px; +} + +#filtros { + display: flex; + gap: 10px; + margin: 12px 0; +} + +#filtros select { + padding: 6px 10px; + border-radius: 4px; + border: 1px solid #3d4152; + background-color: #23262f; + color: #e6e6f0; +} + +#resumen-produccion { + font-weight: bold; + color: #8ecae6; + margin-bottom: 12px; +} + +#lista-assets { + display: grid; + grid-template-columns: repeat(auto-fit, minmax(200px, 1fr)); + gap: 12px; +} + +.asset { + background-color: #23262f; + border: 1px solid #3d4152; + border-radius: 8px; + padding: 12px; +} + +.asset h3 { + margin: 0 0 4px; + font-size: 15px; +} + +.asset p { + margin: 2px 0; + font-size: 13px; + color: #a8adba; +} + +.barra-progreso { + background-color: #3d4152; + border-radius: 4px; + height: 8px; + margin: 6px 0 2px; + overflow: hidden; +} + +.relleno { + background-color: #8ecae6; + height: 100%; +} + +.porcentaje { + font-weight: bold; + color: #e6e6f0 !important; +} + +.asset button { + margin-top: 6px; + padding: 6px 10px; + border: none; + border-radius: 4px; + cursor: pointer; + background-color: #52b788; + color: #0d1b12; + font-weight: bold; +} + +.asset button:disabled { + background-color: #3d4152; + color: #7a7f8c; + cursor: not-allowed; +} + +.sin-resultados { + grid-column: 1 / -1; + color: #e07a7a; + font-style: italic; +} + +.mensaje { + min-height: 18px; + font-weight: bold; +} + +.mensaje.error { + color: #e07a7a; +} diff --git a/intermedio/ejercicios/79-visor-modelos-3d/resoluciones/maria-montepeque/maria-montepeque.html b/intermedio/ejercicios/79-visor-modelos-3d/resoluciones/maria-montepeque/maria-montepeque.html new file mode 100644 index 0000000..511498e --- /dev/null +++ b/intermedio/ejercicios/79-visor-modelos-3d/resoluciones/maria-montepeque/maria-montepeque.html @@ -0,0 +1,36 @@ + + +
+ + +Filtra por etapa y departamento. Solo se aprueba un asset al 100% de progreso.
+ +${asset.departamento} · ${asset.etapa}
+ +${asset.progreso}%
+ `; + + const boton = document.createElement('button'); + boton.type = 'button'; + boton.textContent = asset.aprobado ? 'Aprobado' : 'Marcar como aprobado'; + boton.disabled = asset.aprobado || asset.progreso < 100; + boton.addEventListener('click', () => onAprobar(asset.id)); + tarjeta.appendChild(boton); + + return tarjeta; +} + +function iniciarAplicacionDOM() { + const listaAssets = document.querySelector('#lista-assets'); + const selectorEtapa = document.querySelector('#filtro-etapa'); + const selectorDepartamento = document.querySelector('#filtro-departamento'); + const resumenElemento = document.querySelector('#resumen-produccion'); + const mensajeElemento = document.querySelector('#mensaje-estado'); + + if (!listaAssets || !selectorEtapa || !selectorDepartamento || !resumenElemento || !mensajeElemento) return; + + let assetsActuales = ASSETS_3D; + + function renderizar() { + const filtrados = filtrarAssets(assetsActuales, { etapa: selectorEtapa.value, departamento: selectorDepartamento.value }); + + listaAssets.innerHTML = ''; + if (filtrados.length === 0) { + listaAssets.innerHTML = 'No hay assets con estos filtros.
'; + } else { + filtrados.forEach((asset) => listaAssets.appendChild(crearTarjetaAsset(asset, aprobarAsset))); + } + + const resumen = generarResumenProduccion(assetsActuales); + resumenElemento.textContent = `Total: ${resumen.total} · Aprobados: ${resumen.aprobados} · Progreso promedio: ${resumen.progresoPromedio}%`; + } + + function aprobarAsset(id) { + const resultado = marcarComoAprobado(assetsActuales, id); + if (!resultado.exito) { + mensajeElemento.textContent = resultado.motivo; + mensajeElemento.className = 'mensaje error'; + return; + } + assetsActuales = resultado.assets; + mensajeElemento.textContent = ''; + mensajeElemento.className = 'mensaje'; + renderizar(); + } + + selectorEtapa.addEventListener('change', renderizar); + selectorDepartamento.addEventListener('change', renderizar); + renderizar(); +} + +// --------------------------------------------------------------------------- +// Ejecucion por consola (node maria-montepeque.js) con al menos dos casos de prueba +// --------------------------------------------------------------------------- + +function resolverEjercicio() { + console.log('=== 79. Visor de assets 3D ==='); + mostrarAssetsEnConsola('Catalogo completo', ASSETS_3D); + console.log('Resumen de produccion:', generarResumenProduccion(ASSETS_3D)); + + // Caso 1: filtros combinados por etapa y departamento. + mostrarAssetsEnConsola('Caso 1 - filtro por etapa "texturizado"', filtrarAssets(ASSETS_3D, { etapa: 'texturizado' })); + mostrarAssetsEnConsola('Caso 1 - filtro por departamento "entorno"', filtrarAssets(ASSETS_3D, { departamento: 'entorno' })); + mostrarAssetsEnConsola( + 'Caso 1 - filtro combinado etapa "modelado" + departamento "props"', + filtrarAssets(ASSETS_3D, { etapa: 'modelado', departamento: 'props' }) + ); + + // Caso 2: casos limite - aprobar sin llegar a 100%, subir a 100% y aprobar, + // aprobar algo ya aprobado, aprobar id inexistente y progreso invalido. + console.log('\nCaso 2 - validaciones y casos limite:'); + let assets = ASSETS_3D; + + const aprobarSinTerminar = marcarComoAprobado(assets, 2); + console.log('Aprobar "Escenario bosque" con 40%:', aprobarSinTerminar.exito ? 'aprobado' : aprobarSinTerminar.motivo); + + const subirProgreso = actualizarProgreso(assets, 2, 100); + assets = subirProgreso.assets; + console.log('Subir progreso de "Escenario bosque" a 100%:', subirProgreso.exito ? 'ok' : subirProgreso.motivo); + + const aprobarAhora = marcarComoAprobado(assets, 2); + assets = aprobarAhora.assets; + console.log('Aprobar "Escenario bosque" con 100%:', aprobarAhora.exito ? 'aprobado' : aprobarAhora.motivo); + + const aprobarDeNuevo = marcarComoAprobado(assets, 2); + console.log('Aprobar de nuevo el mismo asset:', aprobarDeNuevo.exito ? 'aprobado' : aprobarDeNuevo.motivo); + + const idInexistente = marcarComoAprobado(assets, 999); + console.log('Aprobar id inexistente:', idInexistente.exito ? 'aprobado' : idInexistente.motivo); + + const progresoInvalido = actualizarProgreso(assets, 3, 150); + console.log('Actualizar progreso a 150:', progresoInvalido.exito ? 'ok' : progresoInvalido.motivo); + + console.log('\nResumen final de produccion:', generarResumenProduccion(assets)); + + return { assetsFinales: assets }; +} + +if (typeof document !== 'undefined') { + document.addEventListener('DOMContentLoaded', iniciarAplicacionDOM); +} else { + resolverEjercicio(); +}