(function (window) { 'use strict'; var STUDY_VERSION = 'S-2026.2'; var CONSENT_VERSION = 'research-consent-2026-10-17-v2'; var API_ROOT = '/api/research-v2'; function cleanSession(value) { return /^[A-Za-z0-9_.:-]{1,100}$/.test(value || '') ? value : 'public-self-guided'; } function sessionId() { var params = new URLSearchParams(window.location.search); var explicit = params.get('session') || params.get('game_session_id'); if (explicit) { var selected = cleanSession(explicit); try { window.localStorage.setItem('makigra_research_active_session:' + STUDY_VERSION, selected); } catch (error) {} return selected; } try { return cleanSession(window.localStorage.getItem('makigra_research_active_session:' + STUDY_VERSION) || 'public-self-guided'); } catch (error) { return 'public-self-guided'; } } function storageKey() { return 'makigra_research_case_token:' + STUDY_VERSION + ':' + sessionId(); } function randomToken() { var bytes = new Uint8Array(32); window.crypto.getRandomValues(bytes); return Array.prototype.map.call(bytes, function (byte) { return byte.toString(16).padStart(2, '0'); }).join(''); } function existingToken() { try { var token = window.localStorage.getItem(storageKey()) || ''; return /^[a-f0-9]{64}$/.test(token) ? token : ''; } catch (error) { return ''; } } function token(create) { var value = existingToken(); if (!value && create) { value = randomToken(); try { window.localStorage.setItem(storageKey(), value); } catch (error) { throw new Error('Браузер не разрешил сохранить исследовательскую сессию. Разрешите локальное хранилище и повторите.'); } } return value; } function submissionToken() { return randomToken(); } async function request(path, body) { var controller = new window.AbortController(); var timer = window.setTimeout(function () { controller.abort(); }, 20000); var response; try { response = await window.fetch(API_ROOT + path, { method: 'POST', credentials: 'same-origin', headers: { 'Content-Type': 'application/json', 'Accept': 'application/json' }, body: JSON.stringify(body), signal: controller.signal }); } catch (error) { throw new Error(error.name === 'AbortError' ? 'Сервер не ответил вовремя. Проверьте соединение и повторите отправку: сохранённые ответы не продублируются.' : 'Нет связи с сервером. Проверьте интернет и повторите отправку.'); } finally { window.clearTimeout(timer); } var result; try { result = await response.json(); } catch (error) { throw new Error('Сервер вернул некорректный ответ.'); } if (!response.ok || !result.ok) { throw new Error(result.error || 'Сервис исследования временно недоступен.'); } return result; } async function status() { var value = token(false); if (!value) { return { ok: true, has_case: false, status: { T0: null, T1: null, T2: null } }; } return request('/status.php', { browser_token: value, game_session_id: sessionId(), study_version: STUDY_VERSION }); } async function submit(wave, formVersion, answers, source) { return request('/submit.php', { browser_token: token(wave === 'T0'), submission_token: submissionToken(), game_session_id: sessionId(), study_version: STUDY_VERSION, form_version: formVersion, wave: wave, answers: answers, source: source || 'public', research_consent: true, consent_version: CONSENT_VERSION, website: '' }); } function withSession(path) { var separator = path.indexOf('?') === -1 ? '?' : '&'; return path + separator + 'session=' + encodeURIComponent(sessionId()); } window.MakigraResearch = { studyVersion: STUDY_VERSION, consentVersion: CONSENT_VERSION, sessionId: sessionId, hasLocalCase: function () { return !!existingToken(); }, startNew: function () { window.localStorage.removeItem(storageKey()); }, status: status, submit: submit, withSession: withSession }; }(window));