From 8838f963a35ec231ab8ee79e3f260cff5d6ae13c Mon Sep 17 00:00:00 2001 From: Maxim Dolgolyov Date: Wed, 27 May 2026 11:21:33 +0300 Subject: [PATCH] =?UTF-8?q?fix(textbooks):=20=D1=88=D0=BF=D0=B0=D1=80?= =?UTF-8?q?=D0=B3=D0=B0=D0=BB=D0=BA=D0=B0=20=D0=BF=D0=BE=D0=BA=D0=B0=D0=B7?= =?UTF-8?q?=D1=8B=D0=B2=D0=B0=D0=B5=D1=82=20=D1=87=D0=B5=D0=BB=D0=BE=D0=B2?= =?UTF-8?q?=D0=B5=D1=87.=20=D0=BD=D0=B0=D0=B7=D0=B2=D0=B0=D0=BD=D0=B8?= =?UTF-8?q?=D1=8F=20=D0=B4=D0=BE=D1=81=D1=82=D0=B8=D0=B6=D0=B5=D0=BD=D0=B8?= =?UTF-8?q?=D0=B9=20=D0=B2=D0=BC=D0=B5=D1=81=D1=82=D0=BE=20id?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Было: 'ring36', 'start' — внутренние id-ы достижений Стало: 'Начало пути по корням!', 'Нашёл сторону ринга' STATE.achievements теперь Map(id → text). Старый формат массива id-ов читается с обратной совместимостью (id используется как текст). При сохранении пишется как объект. --- frontend/textbooks/algebra_8.html | 20 ++++++++++++++------ 1 file changed, 14 insertions(+), 6 deletions(-) diff --git a/frontend/textbooks/algebra_8.html b/frontend/textbooks/algebra_8.html index ff4460d..2225612 100644 --- a/frontend/textbooks/algebra_8.html +++ b/frontend/textbooks/algebra_8.html @@ -395,7 +395,7 @@ input,select,textarea{font-family:inherit} const STATE = { current: 'p1', progress: { p1: 0, p2: 0, p3: 0, p4: 0, p5: 0, p6: 0, final: 0 }, - achievements: new Set(), + achievements: new Map(), // id → human-readable text squaresBest: Infinity, }; @@ -404,7 +404,15 @@ function loadProgress(){ const s = localStorage.getItem('algebra8_ch1_progress'); if(s){ Object.assign(STATE.progress, JSON.parse(s)); } const a = localStorage.getItem('algebra8_ch1_achievements'); - if(a){ STATE.achievements = new Set(JSON.parse(a)); } + if(a){ + const parsed = JSON.parse(a); + if(Array.isArray(parsed)){ + // старый формат [id, id, ...] — id-ы как текст + parsed.forEach(id => STATE.achievements.set(id, id)); + } else if(parsed && typeof parsed === 'object'){ + STATE.achievements = new Map(Object.entries(parsed)); + } + } const sb = localStorage.getItem('algebra8_ch1_squaresBest'); if(sb) STATE.squaresBest = +sb; }catch(e){} @@ -412,7 +420,7 @@ function loadProgress(){ function saveProgress(){ try{ localStorage.setItem('algebra8_ch1_progress', JSON.stringify(STATE.progress)); - localStorage.setItem('algebra8_ch1_achievements', JSON.stringify([...STATE.achievements])); + localStorage.setItem('algebra8_ch1_achievements', JSON.stringify(Object.fromEntries(STATE.achievements))); if(isFinite(STATE.squaresBest)) localStorage.setItem('algebra8_ch1_squaresBest', String(STATE.squaresBest)); }catch(e){} } @@ -437,7 +445,7 @@ function refreshProgressUI(){ } function achievement(id, text){ if(STATE.achievements.has(id)) return; - STATE.achievements.add(id); + STATE.achievements.set(id, text); saveProgress(); const pop = document.getElementById('ach-popup'); document.getElementById('ach-text').textContent = text; @@ -579,8 +587,8 @@ function buildSidebar(id){ // achievements if(STATE.achievements.size > 0){ html += `

Достижения ${STATE.achievements.size}

`; - [...STATE.achievements].slice(-4).forEach(a=>{ - html += `
✓ ${a}
`; + [...STATE.achievements.values()].slice(-4).forEach(text=>{ + html += `
✓ ${text}
`; }); html += '
'; }