class: center, middle, inverse # Diseño en Cuadrado Latino ## De un problema biológico al análisis en R **Diseño de Experimentos · Biología** --- # El problema experimental .pull-left[ Un biólogo desea comparar **cuatro fertilizantes (A, B, C y D)** sobre el crecimiento de plántulas de tomate. El invernadero tiene: - gradiente de **luz** por filas; - gradiente de **humedad** por columnas; - 16 unidades experimentales. ] .pull-right[ .question[ ### Participación 1 **¿Qué problema tendría usar simplemente un DCA?** <button class="choice" data-good="0">A. Ninguno: la aleatorización elimina los gradientes</button> <button class="choice" data-good="1">B. Ambiente y tratamiento podrían confundirse</button> <button class="choice" data-good="0">C. Solo habría un problema de tamaño muestral</button> <div class="feedback"></div> ] ] --- # Construyan el diseño .pull-left[ <div class="latin-builder" id="builder"></div> <div class="center"> <button class="action" onclick="checkLatin()">Verificar</button> <button class="secondary" onclick="resetLatin()">Reiniciar</button> </div> <div id="latinmsg" class="feedback-box"></div> ] .pull-right[ .question[ ### Participación 2 Hagan clic sobre cada celda para cambiar: **A → B → C → D** El objetivo es conseguir que cada tratamiento aparezca **una sola vez por fila y una sola vez por columna**. ] <div class="hidden-answer" id="regla"> Un Cuadrado Latino de orden \(p\) requiere \(p^2\) unidades experimentales. </div> <button class="reveal" onclick="toggleBox('regla')">Revelar regla</button> ] --- # Una solución posible <img src="DCL_Clase_Interactiva_v10_files/figure-html/latin-1.png" alt="" width="88%" style="display: block; margin: auto;" /> .question[ **¿Qué propiedad se conserva en cada fila y en cada columna?** ] --- # Aleatorización .pull-left[ <div class="latin-static" id="baseLatin"></div> ] .pull-right[ <div class="latin-static" id="randomLatin"></div> <div class="center"> <button class="action" onclick="randomizeLatin()">Generar otra aleatorización</button> </div> .question[ ¿Qué cambió? ¿Qué propiedad permanece? ] ] --- # Modelo estadístico <div class="math-display"> <math display="block"> <msub><mi>Y</mi><mrow><mi>i</mi><mi>j</mi><mi>k</mi></mrow></msub> <mo>=</mo><mi>μ</mi><mo>+</mo><msub><mi>α</mi><mi>i</mi></msub> <mo>+</mo><msub><mi>β</mi><mi>j</mi></msub> <mo>+</mo><msub><mi>τ</mi><mi>k</mi></msub> <mo>+</mo><msub><mi>ε</mi><mrow><mi>i</mi><mi>j</mi><mi>k</mi></mrow></msub> <mo>,</mo><mspace width="1em"/> <msub><mi>ε</mi><mrow><mi>i</mi><mi>j</mi><mi>k</mi></mrow></msub> <mover><mo>∼</mo><mtext>iid</mtext></mover> <mi>N</mi><mo>(</mo><mn>0</mn><mo>,</mo><msup><mi>σ</mi><mn>2</mn></msup><mo>)</mo> </math> </div> donde <div class="math-display compact"> <math display="block"> <msub><mi>α</mi><mi>i</mi></msub><mo>=</mo><mtext>efecto de fila</mtext><mo>,</mo> <mspace width="2em"/> <msub><mi>β</mi><mi>j</mi></msub><mo>=</mo><mtext>efecto de columna</mtext><mo>,</mo> <mspace width="2em"/> <msub><mi>τ</mi><mi>k</mi></msub><mo>=</mo><mtext>efecto del tratamiento</mtext><mo>.</mo> </math> </div> **Restricciones de identificabilidad:** <div class="math-display compact"> <math display="block"> <munderover><mo>∑</mo><mrow><mi>i</mi><mo>=</mo><mn>1</mn></mrow><mi>t</mi></munderover> <msub><mi>α</mi><mi>i</mi></msub><mo>=</mo><mn>0</mn><mo>,</mo><mspace width="1.5em"/> <munderover><mo>∑</mo><mrow><mi>j</mi><mo>=</mo><mn>1</mn></mrow><mi>t</mi></munderover> <msub><mi>β</mi><mi>j</mi></msub><mo>=</mo><mn>0</mn><mo>,</mo><mspace width="1.5em"/> <munderover><mo>∑</mo><mrow><mi>k</mi><mo>=</mo><mn>1</mn></mrow><mi>t</mi></munderover> <msub><mi>τ</mi><mi>k</mi></msub><mo>=</mo><mn>0</mn><mo>.</mo> </math> </div> .question[ **Participación 3:** ¿cuál es el factor de interés y cuáles son los dos factores de bloqueo? ] --- # Supuestos: decida antes de revelar .question[ ¿Cuál de estos es especialmente importante en el Cuadrado Latino clásico? <button class="choice" data-good="0">A. Que todos los tratamientos tengan medias iguales</button> <button class="choice" data-good="1">B. Aditividad de los efectos</button> <button class="choice" data-good="0">C. Que filas y columnas no expliquen variabilidad</button> <div class="feedback"></div> ] <div class="hidden-answer" id="adit"> El modelo clásico no permite estimar separadamente las interacciones tratamiento × fila y tratamiento × columna. Por eso la **aditividad** es una consideración estructural importante. </div> <button class="reveal" onclick="toggleBox('adit')">Ampliar explicación</button> --- # Sumas de cuadrados · notación Sea el total general: <div class="math-display"> <math display="block"> <msub><mi>Y</mi><mrow><mo>·</mo><mo>·</mo><mo>·</mo></mrow></msub><mo>=</mo> <munderover><mo>∑</mo><mrow><mi>i</mi><mo>=</mo><mn>1</mn></mrow><mi>t</mi></munderover> <munderover><mo>∑</mo><mrow><mi>j</mi><mo>=</mo><mn>1</mn></mrow><mi>t</mi></munderover> <msub><mi>Y</mi><mrow><mi>i</mi><mi>j</mi></mrow></msub> </math> </div> En consecuencia, los totales marginales se escriben como `\(Y_{i\cdot\cdot}\)` para la fila `\(i\)`, `\(Y_{\cdot j\cdot}\)` para la columna `\(j\)` y `\(Y_{\cdot\cdot k}\)` para el tratamiento `\(k\)`. <div class="math-display"> <math display="block"> <msub><mi>SS</mi><mtext>Total</mtext></msub><mo>=</mo> <munderover><mo>∑</mo><mrow><mi>i</mi><mo>=</mo><mn>1</mn></mrow><mi>t</mi></munderover> <munderover><mo>∑</mo><mrow><mi>j</mi><mo>=</mo><mn>1</mn></mrow><mi>t</mi></munderover> <msubsup><mi>Y</mi><mrow><mi>i</mi><mi>j</mi></mrow><mn>2</mn></msubsup> <mo>−</mo><mfrac><msup><msub><mi>Y</mi><mrow><mo>·</mo><mo>·</mo><mo>·</mo></mrow></msub><mn>2</mn></msup><mi>N</mi></mfrac> </math> </div> .question[ Antes de avanzar: **¿qué componentes debemos retirar de la suma de cuadrados total para obtener el error?** ] --- # Sumas de cuadrados · filas y columnas .pull-left[ ### Filas <div class="math-display small"><math display="block"> <msub><mi>SS</mi><mtext>Filas</mtext></msub><mo>=</mo><mfrac><mn>1</mn><mi>t</mi></mfrac> <munderover><mo>∑</mo><mrow><mi>i</mi><mo>=</mo><mn>1</mn></mrow><mi>t</mi></munderover> <msup><msub><mi>Y</mi><mrow><mi>i</mi><mo>·</mo><mo>·</mo></mrow></msub><mn>2</mn></msup> <mo>−</mo><mfrac><msup><msub><mi>Y</mi><mrow><mo>·</mo><mo>·</mo><mo>·</mo></mrow></msub><mn>2</mn></msup><mi>N</mi></mfrac> </math></div> ] .pull-right[ ### Columnas <div class="math-display small"><math display="block"> <msub><mi>SS</mi><mtext>Columnas</mtext></msub><mo>=</mo><mfrac><mn>1</mn><mi>t</mi></mfrac> <munderover><mo>∑</mo><mrow><mi>j</mi><mo>=</mo><mn>1</mn></mrow><mi>t</mi></munderover> <msup><msub><mi>Y</mi><mrow><mo>·</mo><mi>j</mi><mo>·</mo></mrow></msub><mn>2</mn></msup> <mo>−</mo><mfrac><msup><msub><mi>Y</mi><mrow><mo>·</mo><mo>·</mo><mo>·</mo></mrow></msub><mn>2</mn></msup><mi>N</mi></mfrac> </math></div> ] .question[ ¿Por qué aparece \(1/t\) en ambas expresiones? ] --- # Sumas de cuadrados · tratamientos y error <div class="math-display"> <math display="block"> <msub><mi>SS</mi><mtext>Tratamientos</mtext></msub><mo>=</mo> <mfrac><mn>1</mn><mi>t</mi></mfrac> <munderover><mo>∑</mo><mrow><mi>k</mi><mo>=</mo><mn>1</mn></mrow><mi>t</mi></munderover> <msup><msub><mi>Y</mi><mrow><mo>·</mo><mo>·</mo><mi>k</mi></mrow></msub><mn>2</mn></msup> <mo>−</mo><mfrac><msup><msub><mi>Y</mi><mrow><mo>·</mo><mo>·</mo><mo>·</mo></mrow></msub><mn>2</mn></msup><mi>N</mi></mfrac><mo>.</mo> </math> </div> <div class="math-display"> <math display="block"> <msub><mi>SS</mi><mi>E</mi></msub><mo>=</mo> <msub><mi>SS</mi><mtext>Total</mtext></msub><mo>−</mo> <msub><mi>SS</mi><mtext>Filas</mtext></msub><mo>−</mo> <msub><mi>SS</mi><mtext>Columnas</mtext></msub><mo>−</mo> <msub><mi>SS</mi><mtext>Tratamientos</mtext></msub><mo>.</mo> </math> </div> <div class="decomp"> <span>Total</span><b>=</b><span>Filas</span><b>+</b><span>Columnas</span><b>+</b><span>Tratamientos</span><b>+</b><span>Error</span> </div> --- # Construyamos la tabla ANOVA .question[ ### Participación 4 Para un Cuadrado Latino de orden \(t\), ¿cuáles son los grados de libertad? <button class="reveal" onclick="toggleBox('anova')">Revelar tabla completa</button> ] <div class="hidden-answer" id="anova"> <table class="anova-table"> <thead><tr><th>Fuente</th><th>gl</th><th>SC</th><th>CM</th><th>F</th></tr></thead> <tbody> <tr><td>Filas</td><td><i>t</i> − 1</td><td>SS<sub>F</sub></td><td>SS<sub>F</sub>/(<i>t</i>−1)</td><td>MS<sub>F</sub>/MS<sub>E</sub></td></tr> <tr><td>Columnas</td><td><i>t</i> − 1</td><td>SS<sub>C</sub></td><td>SS<sub>C</sub>/(<i>t</i>−1)</td><td>MS<sub>C</sub>/MS<sub>E</sub></td></tr> <tr><td>Tratamientos</td><td><i>t</i> − 1</td><td>SS<sub>T</sub></td><td>SS<sub>T</sub>/(<i>t</i>−1)</td><td>MS<sub>T</sub>/MS<sub>E</sub></td></tr> <tr><td>Error</td><td>(<i>t</i>−1)(<i>t</i>−2)</td><td>SS<sub>E</sub></td><td>SS<sub>E</sub>/[(<i>t</i>−1)(<i>t</i>−2)]</td><td>—</td></tr> <tr><td>Total</td><td><i>t</i><sup>2</sup> − 1</td><td>SS<sub>Total</sub></td><td>—</td><td>—</td></tr> </tbody> </table> </div> --- # Practiquemos los grados de libertad .question[ ### Participación 4B Seleccione un orden \(t\). La diapositiva genera un ejercicio nuevo automáticamente. ] <div class="p-practice"> <label for="pselect"><b>Orden del Cuadrado Latino:</b></label> <select id="tselect"> <option value="3">t = 3</option> <option value="4" selected>t = 4</option> <option value="5">t = 5</option> <option value="6">t = 6</option> <option value="7">t = 7</option> <option value="8">t = 8</option> </select> </div> <div class="gl-grid"> <div>Filas<br><input id="g1" type="number"></div> <div>Columnas<br><input id="g2" type="number"></div> <div>Tratamientos<br><input id="g3" type="number"></div> <div>Error<br><input id="g4" type="number"></div> <div>Total<br><input id="g5" type="number"></div> </div> <div class="center"> <button class="action" onclick="checkGL()">Comprobar</button> <button class="secondary" onclick="newT()">Otro valor de t</button> </div> <div id="glmsg" class="feedback-box"></div> --- # Ejemplo completo en R .case[ ### Fertilizantes en plántulas de tomate Un biólogo compara los fertilizantes **A, B, C y D** sobre el crecimiento (cm) de plántulas después de seis semanas. El invernadero presenta un gradiente de luz por filas y uno de humedad por columnas. Se utilizan 16 unidades experimentales en un Cuadrado Latino `\((4\times4)\)`. **Objetivos:** determinar si existen diferencias entre fertilizantes a `\((\alpha=0.05)\)`, evaluar los bloqueos, comparar tratamientos cuando corresponda, calcular CV y porcentaje de variabilidad explicada y revisar supuestos. ] .question[ Antes de R: identifique **tratamiento**, **bloques**, **respuesta**, \(N\) y \(gl_E\). ] --- # RStudio · Construcción de los datos <div class="rstudio-label">RStudio · Source · DCL_tomate.R</div> ``` r datos <- data.frame( fila = factor(rep(1:4, each=4)), columna = factor(rep(1:4, times=4)), tratamiento = factor(c( "A","B","C","D", "B","C","D","A", "C","D","A","B", "D","A","B","C")), crecimiento = c( 22.6,24.4,28.0,28.9, 25.0,29.7,30.8,25.2, 27.5,31.4,29.0,28.2, 30.3,28.3,27.9,30.8) ) head(datos) ``` ``` ## fila columna tratamiento crecimiento ## 1 1 1 A 22.6 ## 2 1 2 B 24.4 ## 3 1 3 C 28.0 ## 4 1 4 D 28.9 ## 5 2 1 B 25.0 ## 6 2 2 C 29.7 ``` --- # RStudio · Primero mire los datos .pull-left[ ``` r ggplot(datos, aes(tratamiento, crecimiento)) + geom_boxplot(width=.55, outlier.shape=NA) + geom_jitter(width=.06, size=2.8) + labs(x="Fertilizante", y="Crecimiento (cm)") ``` <img src="DCL_Clase_Interactiva_v10_files/figure-html/grafico-datos-1.png" alt="" width="88%" style="display: block; margin: auto;" /> ] .pull-right[ .question[ ### Participación 5 1. ¿Cuál tratamiento parece tener mayor crecimiento? 2. ¿El gráfico basta para declarar diferencias? 3. ¿Dónde están representados los efectos de fila y columna? ] ] --- # RStudio · Ajuste del modelo .pull-left[ ``` r modelo <- aov( crecimiento ~ fila + columna + tratamiento, data = datos ) summary(modelo) ``` ``` ## Df Sum Sq Mean Sq F value Pr(>F) ## fila 3 28.05 9.350 12.33 0.00563 ** ## columna 3 15.43 5.142 6.78 0.02353 * ## tratamiento 3 48.56 16.185 21.34 0.00133 ** ## Residuals 6 4.55 0.758 ## --- ## Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1 ``` ] .pull-right[ .question[ ### Antes de interpretar ¿Cuál fila de la tabla ANOVA responde directamente a la pregunta científica sobre los fertilizantes? ] <div class="hidden-answer" id="intanova"> La fila **tratamiento**. Filas y columnas permiten evaluar cuánto de la heterogeneidad sistemática fue capturada por el bloqueo. </div> <button class="reveal" onclick="toggleBox('intanova')">Revelar interpretación</button> ] --- # RStudio · Medias ajustadas .pull-left[ ``` r emm <- emmeans(modelo, ~ tratamiento) plot(emm) + labs(x="Media ajustada (cm)", y="Fertilizante") ``` <img src="DCL_Clase_Interactiva_v10_files/figure-html/emmeans-plot-1.png" alt="" width="82%" style="display: block; margin: auto;" /> ] .pull-right[ .question[ ### Participación ¿Por qué es preferible hablar aquí de **medias ajustadas** por el modelo? ] Las medias se estiman controlando estadísticamente los efectos de **fila** y **columna**. ] --- # RStudio · Salida de medias ajustadas <div class="rstudio-label">RStudio · Console</div> ``` r emm ``` ``` ## tratamiento emmean SE df lower.CL upper.CL ## A 26.3 0.435 6 25.2 27.3 ## B 26.4 0.435 6 25.3 27.4 ## C 29.0 0.435 6 27.9 30.1 ## D 30.4 0.435 6 29.3 31.4 ## ## Results are averaged over the levels of: fila, columna ## Confidence level used: 0.95 ``` .question[ Compare las medias ajustadas. ¿Qué patrón descriptivo observa entre A, B, C y D? ] --- # Antes de Tukey: haga una predicción .question[ ### Participación 6 Con base en las medias y el gráfico anterior: **¿qué pares de fertilizantes anticipan que podrían diferir?** Anote las respuestas en el chat antes de ejecutar el código. ] <div class="formula-html"><i>H</i><sub>0</sub>: μ<sub>i</sub> = μ<sub>j</sub> vs. <i>H</i><sub>1</sub>: μ<sub>i</sub> ≠ μ<sub>j</sub></div> --- # RStudio · Comparaciones de Tukey <div class="rstudio-label">RStudio · Console</div> ``` r pairs(emm, adjust="tukey") ``` ``` ## contrast estimate SE df t.ratio p.value ## A - B -0.10 0.616 6 -0.162 0.9983 ## A - C -2.73 0.616 6 -4.425 0.0174 ## A - D -4.08 0.616 6 -6.618 0.0023 ## B - C -2.62 0.616 6 -4.263 0.0206 ## B - D -3.98 0.616 6 -6.455 0.0027 ## C - D -1.35 0.616 6 -2.192 0.2273 ## ## Results are averaged over the levels of: fila, columna ## P value adjustment: tukey method for comparing a family of 4 estimates ``` .question[ Ahora contraste la predicción del grupo con los **p-valores ajustados**. ¿Qué pares presentan evidencia de diferencia? ] --- # RStudio · Residuos vs. ajustados .pull-left[ ``` r diag <- augment(modelo) ggplot(diag, aes(.fitted, .resid)) + geom_hline(yintercept=0, linetype=2) + geom_point(size=2.8) + labs(x="Valores ajustados", y="Residuos") ``` <img src="DCL_Clase_Interactiva_v10_files/figure-html/resid-1.png" alt="" width="88%" style="display: block; margin: auto;" /> ] .pull-right[ .question[ ¿Qué buscaría en este gráfico? <button class="choice" data-good="1">Dispersión sin patrón sistemático</button> <button class="choice" data-good="0">Una línea creciente perfecta</button> <button class="choice" data-good="0">Todos los residuos positivos</button> <div class="feedback"></div> ] ] --- # RStudio · QQ-plot y normalidad .pull-left[ ``` r ggplot(diag, aes(sample=.std.resid)) + stat_qq(size=2.7) + stat_qq_line() + labs(x="Cuantiles teóricos", y="Residuos estandarizados") ``` <img src="DCL_Clase_Interactiva_v10_files/figure-html/qq-1.png" alt="" width="88%" style="display: block; margin: auto;" /> ] .pull-right[ ``` r shapiro.test(residuals(modelo)) ``` ``` ## ## Shapiro-Wilk normality test ## ## data: residuals(modelo) ## W = 0.93997, p-value = 0.3486 ``` .question[ ¿Por qué **no** deberíamos decidir la validez del modelo únicamente con el p-valor de Shapiro–Wilk? ] ] --- # RStudio · Coeficiente de variación <div class="math-display compact"> <math display="block"> <mi>CV</mi><mo>=</mo> <mfrac><msqrt><msub><mi>MS</mi><mi>E</mi></msub></msqrt><mover><mi>Y</mi><mo>¯</mo></mover></mfrac> <mo>×</mo><mn>100</mn><mo>.</mo> </math> </div> .pull-left[ ``` r tab <- anova(modelo) MSE <- tab["Residuals","Mean Sq"] CV <- sqrt(MSE) / mean(datos$crecimiento) * 100 CV ``` ``` ## [1] 3.110083 ``` ] .pull-right[ .question[ ¿Qué información aporta el CV sobre la **precisión experimental** que no aporta directamente el p-valor? ] ] --- # RStudio · ¿Quién explica la variabilidad? <div class="math-display compact"> <math display="block"> <mo>%</mo><msub><mi>V</mi><mi>j</mi></msub><mo>=</mo> <mfrac><msub><mi>SS</mi><mi>j</mi></msub><msub><mi>SS</mi><mtext>Total</mtext></msub></mfrac> <mo>×</mo><mn>100</mn><mo>.</mo> </math> </div> .pull-left[ ``` r pct <- data.frame( Fuente=rownames(tab), Porcentaje=100*tab[,"Sum Sq"]/ sum(tab[,"Sum Sq"]) ) ggplot(pct, aes(reorder(Fuente,Porcentaje), Porcentaje)) + geom_col() + coord_flip() + labs(x=NULL, y="% de variabilidad") ``` <img src="DCL_Clase_Interactiva_v10_files/figure-html/porcentaje-1.png" alt="" width="88%" style="display: block; margin: auto;" /> ] .pull-right[ .question[ Si filas y columnas explican una proporción importante de la variabilidad, ¿eso apoya o contradice la decisión de bloquear? ] ] --- # Detectives del diseño <div class="detective"> <div><b>A.</b> 4 fertilizantes; parcelas homogéneas. <button onclick="showCase(this,'DCA')">Ver</button><span></span></div> <div><b>B.</b> 4 fertilizantes; un gradiente conocido. <button onclick="showCase(this,'DBCA')">Ver</button><span></span></div> <div><b>C.</b> 4 fertilizantes; dos gradientes perpendiculares. <button onclick="showCase(this,'Cuadrado Latino')">Ver</button><span></span></div> <div><b>D.</b> Fertilizante × riego; interesa la interacción. <button onclick="showCase(this,'Factorial')">Ver</button><span></span></div> </div> --- # Reto final .case[ Se comparan **cinco dietas** en una instalación animal. Existe un gradiente térmico norte–sur y otro de ventilación oeste–este. ] En grupos, respondan: 1. ¿Puede utilizarse un Cuadrado Latino? 2. ¿Cuántas unidades experimentales se requieren? 3. ¿Cuántas veces aparece cada dieta? 4. ¿Cuáles son los gl de filas, columnas, tratamientos y error? 5. ¿Qué supuesto estructural es especialmente importante? <button class="reveal" onclick="toggleBox('retofinal')">Revelar solución</button> <div class="hidden-answer" id="retofinal"> <div class="solution-grid"> <div><b>¿Cuadrado Latino?</b><br>Sí: hay 5 tratamientos y dos fuentes de bloqueo.</div> <div><b>Unidades experimentales</b><br>25</div> <div><b>Repeticiones por dieta</b><br>5</div> </div> <div class="math-display compact"> <math display="block"> <msub><mi>gl</mi><mtext>Filas</mtext></msub><mo>=</mo><mn>4</mn><mo>,</mo><mspace width="1.2em"/> <msub><mi>gl</mi><mtext>Columnas</mtext></msub><mo>=</mo><mn>4</mn><mo>,</mo><mspace width="1.2em"/> <msub><mi>gl</mi><mtext>Tratamientos</mtext></msub><mo>=</mo><mn>4</mn><mo>,</mo><mspace width="1.2em"/> <msub><mi>gl</mi><mi>E</mi></msub><mo>=</mo><mo>(</mo><mn>5</mn><mo>−</mo><mn>1</mn><mo>)</mo> <mo>(</mo><mn>5</mn><mo>−</mo><mn>2</mn><mo>)</mo><mo>=</mo><mn>12</mn><mo>.</mo> </math> </div> <p><b>Supuesto estructural clave:</b> aditividad de los efectos; el modelo clásico no estima separadamente interacciones tratamiento × fila o tratamiento × columna.</p> </div> El supuesto estructural clave es la **aditividad**. </div> --- class: center, middle, inverse # Idea central <div class="final-idea">Bloquear es retirar variabilidad sistemática del error</div> ## para comparar tratamientos con mayor precisión. <script> const L=[['A','B','C','D'],['B','C','D','A'],['C','D','A','B'],['D','A','B','C']]; function makeGrid(id,a,editable=false){ const e=document.getElementById(id); if(!e)return; e.innerHTML=''; a.flat().forEach(v=>{ const d=document.createElement('div'); d.className='lcell'; d.textContent=v; if(editable)d.onclick=()=>{const z=['A','B','C','D'];d.textContent=z[(z.indexOf(d.textContent)+1)%4]}; e.appendChild(d); }); } function toggleBox(id){document.getElementById(id).classList.toggle('shown')} function resetLatin(){makeGrid('builder',Array.from({length:4},()=>Array(4).fill('A')),true);document.getElementById('latinmsg').innerHTML=''} function checkLatin(){ const a=[...document.querySelectorAll('#builder .lcell')].map(x=>x.textContent); let ok=true; for(let r=0;r<4;r++) if(new Set(a.slice(4*r,4*r+4)).size!==4)ok=false; for(let c=0;c<4;c++){let q=[];for(let r=0;r<4;r++)q.push(a[4*r+c]);if(new Set(q).size!==4)ok=false} document.getElementById('latinmsg').innerHTML=ok?'✓ Es un Cuadrado Latino válido.':'Todavía no: revise filas y columnas con letras repetidas.'; } function sh(a){a=[...a];for(let i=a.length-1;i>0;i--){let j=Math.floor(Math.random()*(i+1));[a[i],a[j]]=[a[j],a[i]]}return a} function randomizeLatin(){ let rs=sh([0,1,2,3]),cs=sh([0,1,2,3]),labs=sh(['A','B','C','D']),m={A:labs[0],B:labs[1],C:labs[2],D:labs[3]}; makeGrid('randomLatin',rs.map(r=>cs.map(c=>m[L[r][c]]))); } function checkGL(){ const t=+document.getElementById('tselect').value; const ans=[t-1,t-1,t-1,(t-1)*(t-2),t*t-1]; const vals=['g1','g2','g3','g4','g5'].map(x=>+document.getElementById(x).value); const ok=JSON.stringify(vals)===JSON.stringify(ans); document.getElementById('glmsg').innerHTML=ok ?'✓ Correcto para t = '+t+': '+ans[0]+' + '+ans[1]+' + '+ans[2]+' + '+ans[3]+' = '+ans[4]+'.' :'Revise las expresiones: t−1, t−1, t−1, (t−1)(t−2) y t²−1.'; } function clearGL(){ ['g1','g2','g3','g4','g5'].forEach(x=>document.getElementById(x).value=''); document.getElementById('glmsg').innerHTML=''; } function newT(){ const s=document.getElementById('tselect'); const vals=[3,4,5,6,7,8].filter(x=>x!==+s.value); s.value=vals[Math.floor(Math.random()*vals.length)]; clearGL(); } function showCase(b,t){b.nextElementSibling.textContent=' → '+t} document.addEventListener('click',e=>{ if(e.target.classList.contains('choice')){ const box=e.target.parentElement; box.querySelectorAll('.choice').forEach(x=>x.classList.remove('right','wrong')); e.target.classList.add(e.target.dataset.good==='1'?'right':'wrong'); const f=box.querySelector('.feedback'); if(f)f.textContent=e.target.dataset.good==='1'?'Correcto. Justifique la decisión.':'Revise la lógica del bloqueo antes de continuar.'; } }); document.addEventListener('DOMContentLoaded',()=>{ resetLatin();makeGrid('baseLatin',L);randomizeLatin(); const ps=document.getElementById('tselect'); if(ps) ps.addEventListener('change',clearGL); }); </script>