diff --git a/frontend/js/bmr.js b/frontend/js/bmr.js index ee89dde..e9d9d9e 100644 --- a/frontend/js/bmr.js +++ b/frontend/js/bmr.js @@ -27,35 +27,36 @@ function estimateRealBmr(weights, foodTotals) { return realExpend > 500 ? Math.round(realExpend) : null; // sanity: < 500 kcal/day is wrong data } -// Russian daily recommended intake (РСП) per ТР ТС 022/2011 -const RDI = { - vit_a_mcg: 800, // ретиноловый эквивалент - vit_c_mg: 60, - vit_e_mg: 10, // токофероловый эквивалент - vit_b1_mg: 1.4, - vit_b2_mg: 1.6, - vit_b3_mg: 18, // ниацин - vit_b5_mg: 6, // пантотеновая - vit_b6_mg: 2, - vit_b7_mcg: 50, // биотин - folate_mcg: 200, // фолиевая (= 0.2 мг = 200 мкг), в БД как folate_mcg - vit_b12_mcg: 1, - vit_d_mcg: 5, - vit_k_mcg: 120, - calcium_mg: 1000, - magnesium_mg: 400, - zinc_mg: 15, - iron_mg: 14, - iodine_mg: 0.15, - selenium_mcg: 70, - molybdenum_mcg: 70, - manganese_mg: 2, - copper_mg: 1, - chromium_mg: 0.05, - phosphorus_mg: 800, - potassium_mg: 3500, - sodium_mg: 2400, - // carotene_mcg removed — auto-converted to vit_a_mcg (carotene/12) +// RDI loaded from DB (rdi_standards + rdi_values tables). +// Fallback hardcoded RU values used until DB is ready. +let RDI = { + vit_a_mcg: 800, vit_c_mg: 60, vit_e_mg: 10, vit_b1_mg: 1.4, vit_b2_mg: 1.6, + vit_b3_mg: 18, vit_b5_mg: 6, vit_b6_mg: 2, vit_b7_mcg: 50, folate_mcg: 200, + vit_b12_mcg: 1, vit_d_mcg: 5, vit_k_mcg: 120, calcium_mg: 1000, magnesium_mg: 400, + zinc_mg: 15, iron_mg: 14, iodine_mg: 0.15, selenium_mcg: 70, molybdenum_mcg: 70, + manganese_mg: 2, copper_mg: 1, chromium_mg: 0.05, phosphorus_mg: 800, + potassium_mg: 3500, sodium_mg: 2400, }; -window.BMR = { calculateBmr, getAge, estimateRealBmr, RDI }; +// Load RDI from DB for selected standard. Called after DB ready. +async function loadRDI(standardCode) { + try { + const std = await window.__TAURI__.core.invoke("plugin:sql|select", { + db: "sqlite:baldav.db", + query: "SELECT id FROM rdi_standards WHERE code = ?1", + values: [standardCode || "RU"], + }); + if (!std.length) return; + const vals = await window.__TAURI__.core.invoke("plugin:sql|select", { + db: "sqlite:baldav.db", + query: "SELECT nutrient_key, value FROM rdi_values WHERE standard_id = ?1", + values: [std[0].id], + }); + const loaded = {}; + for (const v of vals) loaded[v.nutrient_key] = v.value; + if (Object.keys(loaded).length > 0) RDI = loaded; + } catch (e) { console.error("[BMR] loadRDI error:", e); } +} + +window.BMR = { calculateBmr, getAge, estimateRealBmr, RDI, loadRDI, + get rdi() { return RDI; } }; diff --git a/frontend/js/db.js b/frontend/js/db.js index a90f4fd..14cf8d6 100644 --- a/frontend/js/db.js +++ b/frontend/js/db.js @@ -1155,6 +1155,64 @@ async function runMigrations() { // Product dedup handled in Rust import_seed_products (UNIQUE INDEX on name_lower+source+store_id) + // RDI standards tables + await execute(`CREATE TABLE IF NOT EXISTS rdi_standards ( + id INTEGER PRIMARY KEY, + code TEXT NOT NULL UNIQUE, + name TEXT NOT NULL + )`); + await execute(`CREATE TABLE IF NOT EXISTS rdi_values ( + id INTEGER PRIMARY KEY, + standard_id INTEGER NOT NULL REFERENCES rdi_standards(id), + nutrient_key TEXT NOT NULL, + value REAL NOT NULL, + UNIQUE(standard_id, nutrient_key) + )`); + + // Seed RDI standards if empty + const rdiCount = await select("SELECT COUNT(*) as cnt FROM rdi_standards"); + if (rdiCount[0].cnt === 0) { + await execute("INSERT INTO rdi_standards (id, code, name) VALUES (1, 'RU', 'РФ (ТР ТС 022/2011)')"); + await execute("INSERT INTO rdi_standards (id, code, name) VALUES (2, 'EU', 'ЕС (EU RDA)')"); + await execute("INSERT INTO rdi_standards (id, code, name) VALUES (3, 'US', 'США (US DV)')"); + + const standards = { + // nutrient_key: [RU, EU, US] + vit_a_mcg: [800, 800, 900], + vit_c_mg: [60, 80, 90], + vit_e_mg: [10, 12, 15], + vit_b1_mg: [1.4, 1.1, 1.2], + vit_b2_mg: [1.6, 1.4, 1.3], + vit_b3_mg: [18, 16, 16], + vit_b5_mg: [6, 6, 5], + vit_b6_mg: [2, 1.4, 1.7], + vit_b7_mcg: [50, 50, 30], + folate_mcg: [200, 200, 400], + vit_b12_mcg: [1, 2.5, 2.4], + vit_d_mcg: [5, 15, 15], + vit_k_mcg: [120, 75, 120], + calcium_mg: [1000, 800, 1000], + magnesium_mg: [400, 375, 420], + zinc_mg: [15, 10, 11], + iron_mg: [14, 14, 18], + iodine_mg: [0.15, 0.15, 0.15], + selenium_mcg: [70, 55, 55], + molybdenum_mcg: [70, 50, 45], + manganese_mg: [2, 2, 2.3], + copper_mg: [1, 1, 0.9], + chromium_mg: [0.05, 0.04, 0.035], + phosphorus_mg: [800, 700, 700], + potassium_mg: [3500, 2000, 2600], + sodium_mg: [2400, 2400, 2300], + }; + for (const [key, vals] of Object.entries(standards)) { + for (let i = 0; i < 3; i++) { + await execute("INSERT INTO rdi_values (standard_id, nutrient_key, value) VALUES (?1, ?2, ?3)", [i + 1, key, vals[i]]); + } + } + console.log("[db.js] Seeded 3 RDI standards (RU/EU/US)"); + } + console.log("[db.js] recipe migrations done, checking seq repair..."); // Repair old tracks: assign seq to points where it's NULL, ordered by timestamp. diff --git a/frontend/js/main.js b/frontend/js/main.js index 8e60c2c..4bf6b21 100644 --- a/frontend/js/main.js +++ b/frontend/js/main.js @@ -75,6 +75,12 @@ async function init() { // Recover any orphaned GPS recording session try { await GPS.recoverSession(); } catch (e) { /* ignore */ } + // Load RDI standard from profile (default: RU) + try { + const rdiCode = (await DB.getProfileValue("rdi_standard")) || "RU"; + await BMR.loadRDI(rdiCode); + } catch (e) { /* RDI stays at fallback RU values */ } + // Import seed products if needed — show progress only if actually importing try { let unlisten = null; @@ -3681,6 +3687,21 @@ async function renderSettings(container) { +