PageSourceSearch

https://elige-grado-fcomunav.netlify.app/app.js?v=1

js elige-grado-fcomunav.netlify.app collected 2026-10-03 10:41:30 UTC 6,316 bytes, 252 lines download raw bytes

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.