1const root = document.getElementById("testInner"); 2 3let q, r; 4let page = 0; 5let answers = {}; 6 7const WORDS = ["", "nada", "poco", "normal", "bastante", "mucho"]; 8 9/* ====================== 10 ARRANQUE 11====================== */ 12 13window.addEventListener("DOMContentLoaded", async () => { 14 try { 15 q = await fetch("./questions.json").then(r => r.json()); 16 r = await fetch("./results.json").then(r => r.json()); 17 start(); 18 } catch (err) { 19 root.innerHTML = "<p>Error cargando datos</p>"; 20 console.error(err); 21 } 22}); 23 24/* ====================== 25 TEST 26====================== */ 27 28function start() { 29 page = 0; 30 answers = {}; 31 renderQuestion(); 32} 33 34function renderQuestion() { 35 const pct = Math.round( 36 (Object.keys(answers).length / q.questions.length) * 100 37 ); 38 const qu = q.questions[page]; 39 40 root.innerHTML = ` 41 <div class="progress-row"> 42 <div class="progress-track"> 43 <div class="progress-bar" style="width:${pct}%"></div> 44 </div> 45 46 <span class="progress-pct">${pct}%</span> 47 48 <button class="progress-close" onclick="closeFromIframe()">â</button> 49 </div> 50 51 <div class="card"> 52 <p class="q-text"> 53 <span class="q-number">${page + 1}/${q.questions.length}.</span> 54 ${qu.text} 55 </p> 56 57 <div class="options"> 58 ${[1,2,3,4,5].map(v => ` 59 <label data-v="${v}"> 60 <span class="num">${v}</span> 61 <span class="word">${WORDS[v]}</span> 62 </label> 63 `).join("")} 64 </div> 65 </div> 66 `; 67 68 document.querySelectorAll(".options label").forEach(lbl => { 69 lbl.onclick = () => { 70 answers[qu.id] = Number(lbl.dataset.v); 71 72 if (page === q.questions.length - 1) { 73 renderResults(); 74 } else { 75 page++; 76 renderQuestion(); 77 } 78 }; 79 }); 80} 81 82/* ====================== 83 RESULTADOS 84====================== */ 85 86function renderResults() { 87 88 /* cálculo dimensiones */ 89 const dimensionResults = {}; 90 q.meta.dimensions.forEach(d => { 91 dimensionResults[d.id] = { raw: 0, count: 0 }; 92 }); 93 94 q.questions.forEach(qu => { 95 const v = answers[qu.id]; 96 if (v == null) return; 97 98 dimensionResults[qu.dimension].raw += (v - 3) * (qu.direction || 1); 99 dimensionResults[qu.dimension].count++; 100 }); 101 102 q.meta.dimensions.forEach(d => { 103 const raw = dimensionResults[d.id].raw; 104 const count = dimensionResults[d.id].count; 105 const maxAbs = count * 2; 106 107 dimensionResults[d.id].pct = 108 maxAbs === 0 ? 0 : Math.round((raw / maxAbs) * 100); 109 }); 110 111 let code = ""; 112 const badgeCode = q.meta.dimensions.map(d => { 113 const pct = dimensionResults[d.id].pct; 114 const letter = pct >= 0 ? d.positive : d.negative; 115 code += letter; 116 return letter[0]; 117 }).join(""); 118 119 const type = r.types.find(t => t.code === code) || r.fallback; 120 121 /* CTA grado */ 122 const degreeMap = { 123 IN: { 124 name: "Creación Audiovisual", 125 url: "https://www.unav.edu/web/grado-en-creacion-audiovisual" 126 }, 127 IE: { 128 name: "Marketing", 129 url: "https://www.unav.edu/web/grado-en-marketing" 130 }, 131 ON: { 132 name: "Periodismo", 133 url: "https://www.unav.edu/web/grado-en-periodismo" 134 }, 135 OE: { 136 name: "Comunicación Corporativa", 137 url: "https://www.unav.edu/web/grado-en-comunicacion-corporativa" 138 } 139 }; 140 141 const degree = degreeMap[badgeCode.slice(0, 2)]; 142 143 /* ====================== 144 DETALLE DIMENSIONES 145 ====================== */ 146 147 const dimsHTML = q.meta.dimensions.map(d => { 148 const { raw, pct } = dimensionResults[d.id]; 149 const strength = Math.abs(pct); 150 151 return ` 152 <div style="margin-bottom:14px"> 153 <strong>${d.labelNegative} â ${d.labelPositive}</strong> 154 <div style="margin:6px 0"> 155 <div style="width:${strength}%; background:#ff0000; height:10px; border-radius:6px;"></div> 156 </div> 157 <small>Puntuación: ${raw.toFixed(2)}</small> 158 </div> 159 `; 160 }).join(""); 161 162 /* ====================== 163 COMPATIBILIDAD (ARREGLADO) 164 ====================== */ 165 166 const programs = { 167 "Creación Audiovisual": { rol: "I", enf: "N" }, 168 "Marketing": { rol: "I", enf: "E" }, 169 "Periodismo": { rol: "O", enf: "N" }, 170 "Comunicación Corporativa": { rol: "O", enf: "E" } 171 }; 172 173 const affinityHTML = Object.entries(programs).map(([name, pref]) => { 174 let score = 0; 175 176 if (pref.rol === badgeCode[0]) score++; 177 if (pref.enf === badgeCode[1]) score++; 178 179 const pct = score === 2 ? 100 : score === 1 ? 50 : 0; 180 181 return ` 182 <div style="margin-bottom:12px"> 183 <strong>${name}</strong> 184 <div style="margin:6px 0"> 185 <div style="width:${pct}%; background:#ff0000; height:10px; border-radius:6px;"></div> 186 </div> 187 <small>Afinidad: ${pct}%</small> 188 </div> 189 `; 190 }).join(""); 191 192 /* ====================== 193 RENDER FINAL 194 ====================== */ 195 196 root.innerHTML = ` 197 <div class="result-card"> 198 199 <div class="result-header"> 200 <div class="result-badge">${badgeCode}</div> 201 <div> 202 <h3>Tu resultado</h3> 203 <p><strong>${type.title || ""}</strong></p> 204 </div> 205 </div> 206 207 <div class="reco-block"> 208 <p class="reco-title">Recomendación</p> 209 <p class="reco-text">${type.description}</p> 210 211 ${degree ? ` 212 <div class="degree-cta"> 213 214 <a href="https://www.unav.edu/web/facultad-de-comunicacion/solicitud-de-informacion" 215 target="_top" 216 class="btn"> 217 Quiero más información 218 </a> 219 220 <a href="${degree.url}" target="_top" 221 class="btn btn-outline"> 222 Ir a la web de ${degree.name} 223 </a> 224 225 </div> 226 ` : ""} 227 </div> 228 229 <h4>Detalle por dimensión</h4> 230 ${dimsHTML} 231 232 <h4>Compatibilidad por programa</h4> 233 ${affinityHTML} 234 235 <div class="result-actions"> 236 <button class="btn secondary" onclick="start()">Volver a empezar</button> 237 <button class="btn" onclick="closeFromIframe()">Cerrar</button> 238 </div> 239 240 </div> 241 `; 242} 243 244/* ====================== 245 CIERRE DESDE IFRAME 246====================== */ 247 248function closeFromIframe() { 249 if (window.parent && window.parent !== window) { 250 window.parent.postMessage({ action: "CLOSE_OVERLAY" }, "*"); 251 } 252}
Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.