{"mappings":";ACEA,IAAA;AASA,IAAA;AAIA,IAAA;;ACfA,MAAM,wCAAkB;AACxB,MAAM,uCAAiB;AACvB,MAAM,kCAAY;AAElB,MAAM,uCAAiB;IACrB,KAAK;QACH;YACE,MAAM;YACN,OAAO;YACP,QAAQ;YACR,MAAM;YACN,KAAK;YACL,KAAK;YACL,MAAM;QACR;QACA;YACE,MAAM;YACN,OAAO;YACP,QAAQ;YACR,MAAM;YACN,KAAK;YACL,KAAK;YACL,MAAM;QACR;QACA;YACE,MAAM;YACN,OAAO;YACP,QAAQ;YACR,MAAM;YACN,KAAK;YACL,KAAK;YACL,MAAM;QACR;QACA;YACE,MAAM;YACN,OAAO;YACP,QAAQ;YACR,MAAM;YACN,KAAK;YACL,KAAK;YACL,MAAM;QACR;QACA;YACE,MAAM;YACN,OAAO;YACP,QAAQ;YACR,MAAM;YACN,KAAK;YACL,KAAK;YACL,MAAM;QACR;QACA;YACE,MAAM;YACN,OAAO;YACP,QAAQ;YACR,MAAM;YACN,KAAK;YACL,KAAK;YACL,MAAM;QACR;QACA;YACE,MAAM;YACN,OAAO;YACP,QAAQ;YACR,MAAM;YACN,KAAK;YACL,KAAK;YACL,MAAM;QACR;QACA;YACE,MAAM;YACN,OAAO;YACP,QAAQ;YACR,MAAM;YACN,KAAK;YACL,KAAK;YACL,MAAM;QACR;QACA;YACE,MAAM;YACN,OAAO;YACP,QAAQ;YACR,MAAM;YACN,KAAK;YACL,KAAK;YACL,MAAM;QACR;KACD;IACD,SAAS;QACP;YACE,MAAM;YACN,OAAO;YACP,QAAQ;YACR,MAAM;YACN,KAAK;YACL,KAAK;YACL,MAAM;QACR;QACA;YACE,MAAM;YACN,OAAO;YACP,QAAQ;YACR,MAAM;YACN,KAAK;YACL,KAAK;YACL,MAAM;QACR;QACA;YACE,MAAM;YACN,OAAO;YACP,QAAQ;YACR,MAAM;YACN,KAAK;YACL,KAAK;YACL,MAAM;QACR;QACA;YACE,MAAM;YACN,OAAO;YACP,QAAQ;YACR,MAAM;YACN,KAAK;YACL,KAAK;YACL,MAAM;QACR;QACA;YACE,MAAM;YACN,OAAO;YACP,QA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","sources":["index.js","lib.js","constant.js"],"sourcesContent":["const lib = require(\"./lib\");\nconst {\n ENERGY_BASELINE,\n SCALING_FACTOR,\n RANGE_PROFILES,\n RANGE_PROFILE_KEY,\n LIMITS_PER_KCAL,\n} = require(\"./constant\");\n\n/**\n * Calculate score based on a dictionary with amounts for each nutrient\n *\n * @param {array} amounts [{\"nutrient\": amount}, {}, {}]\n * @returns {number}\n */\nmodule.exports = function ({\n amounts,\n validateNutrition = true,\n scalingFactor = SCALING_FACTOR,\n marketCode = null,\n}) {\n // get range profiles specific for the country or default to MMIQv1\n const rangeProfiles =\n RANGE_PROFILES[RANGE_PROFILE_KEY[marketCode] || \"default\"];\n const requiredFields = rangeProfiles.map((a) => a.name).concat(\"kcal\");\n const totalAmount = lib.sumValues(amounts, requiredFields);\n if (totalAmount.kcal <= 0) throw Error(\"Value for kcal must be > 0\");\n\n // validate data\n if (validateNutrition) {\n const errors = [];\n if (totalAmount.kcal < 100)\n errors.push(\"Energy (kcal) must be at least 100 kcals.\");\n if (totalAmount.fatSaturatedGrams > totalAmount.fatTotalGrams)\n errors.push(\n \"Value for saturated fat cannot be higher than value for total fat.\"\n );\n for (const [nutrient, upperLimit] of Object.entries(LIMITS_PER_KCAL)) {\n if (nutrient in totalAmount) {\n if (totalAmount[nutrient] / totalAmount.kcal > upperLimit)\n errors.push(`${nutrient} is too high.`);\n }\n }\n\n if (errors.length > 0) throw Error(errors.join(\"\\n\"));\n }\n\n let score = 0;\n let totalWeight = 0;\n rangeProfiles.forEach((rp) => {\n const amt =\n (parseFloat(totalAmount[rp.name]) * ENERGY_BASELINE) /\n parseFloat(totalAmount.kcal);\n let nutScore = 0;\n if (rp.lhr0 < amt && amt < rp.lhr) {\n nutScore = (amt - rp.lhr0) / (rp.lhr - rp.lhr0);\n } else if (rp.lhr <= amt && amt <= rp.uhr) {\n nutScore = 1;\n } else if (rp.uhr < amt && amt < rp.uhr0) {\n nutScore = (rp.uhr0 - amt) / (rp.uhr0 - rp.uhr);\n }\n\n score += nutScore * rp.weight;\n totalWeight += rp.weight;\n });\n\n return lib.scaleRoundTo5((score / totalWeight) * 100, scalingFactor);\n};\n","const { SCALING_FACTOR, SCORE_MAX } = require(\"./constant\");\n\nexports.arrayEquals = function (a, b) {\n return (\n Array.isArray(a) &&\n Array.isArray(b) &&\n a.length === b.length &&\n a.every((v) => b.indexOf(v) >= 0)\n );\n};\n\nexports.scaleRoundTo5 = function (x, scalingFactor = SCALING_FACTOR) {\n return parseInt(Math.round(Math.min(x / scalingFactor, SCORE_MAX) / 5) * 5);\n};\n\nexports.sumValues = (objects, requiredKeys) => {\n const result = {};\n objects.forEach((obj, idx) => {\n for (let key of requiredKeys) {\n const value = obj.hasOwnProperty(key) ? obj[key] : null;\n if (typeof value === \"number\") {\n if (result.hasOwnProperty(key)) {\n result[key] += value;\n } else {\n result[key] = value;\n }\n } else {\n throw Error(\n `Value for ${key} must be a number (In amounts array at index = ${idx}).`\n );\n }\n }\n });\n return result;\n};\n","const ENERGY_BASELINE = 2000;\nconst SCALING_FACTOR = 0.8;\nconst SCORE_MAX = 100;\n\nconst RANGE_PROFILES = {\n SEA: [\n {\n name: \"addedSugarsTeaSpoons\",\n units: \"tsp\",\n weight: 1,\n lhr0: 0.0,\n lhr: 0.0,\n uhr: 11.9047619,\n uhr0: 17.85714286,\n },\n {\n name: \"calciumMilligrams\",\n units: \"mg\",\n weight: 1,\n lhr0: 325.0,\n lhr: 750.0,\n uhr: 1500.0,\n uhr0: 1875.0,\n },\n {\n name: \"fatSaturatedGrams\",\n units: \"g\",\n weight: 2,\n lhr0: 0.0,\n lhr: 0.0,\n uhr: 22.22222222,\n uhr0: 33.33333333,\n },\n {\n name: \"fatTotalGrams\",\n units: \"g\",\n weight: 1,\n lhr0: 22.22222222,\n lhr: 44.44444444,\n uhr: 77.77777778,\n uhr0: 100.0,\n },\n {\n name: \"fiberGrams\",\n units: \"g\",\n weight: 1,\n lhr0: 10.0,\n lhr: 20.0,\n uhr: 40.0,\n uhr0: 50.0,\n },\n {\n name: \"ironMilligrams\",\n units: \"mg\",\n weight: 1,\n lhr0: 6.0,\n lhr: 12.0,\n uhr: 24.0,\n uhr0: 30.0,\n },\n {\n name: \"potassiumMilligrams\",\n units: \"mg\",\n weight: 2,\n lhr0: 1000.0,\n lhr: 2000.0,\n uhr: 4000.0,\n uhr0: 6000.0,\n },\n {\n name: \"proteinGrams\",\n units: \"g\",\n weight: 1,\n lhr0: 25.0,\n lhr: 50.0,\n uhr: 75.0,\n uhr0: 100.0,\n },\n {\n name: \"sodiumMilligrams\",\n units: \"mg\",\n weight: 1,\n lhr0: 0.0,\n lhr: 0.0,\n uhr: 2000.0,\n uhr0: 3000.0,\n },\n ],\n default: [\n {\n name: \"addedSugarsTeaSpoons\",\n units: \"tsp\",\n weight: 1,\n lhr0: 0,\n lhr: 0,\n uhr: 11.9047619,\n uhr0: 17.85714286,\n },\n {\n name: \"calciumMilligrams\",\n units: \"mg\",\n weight: 1,\n lhr0: 500,\n lhr: 1000,\n uhr: 2000,\n uhr0: 2500,\n },\n {\n name: \"fatSaturatedGrams\",\n units: \"g\",\n weight: 2,\n lhr0: 0,\n lhr: 0,\n uhr: 22.22222222,\n uhr0: 33.33333333,\n },\n {\n name: \"fatTotalGrams\",\n units: \"g\",\n weight: 1,\n lhr0: 22.22222222,\n lhr: 44.44444444,\n uhr: 77.77777778,\n uhr0: 100,\n },\n {\n name: \"fiberGrams\",\n units: \"g\",\n weight: 1,\n lhr0: 12.5,\n lhr: 25,\n uhr: 50,\n uhr0: 62.5,\n },\n {\n name: \"ironMilligrams\",\n units: \"mg\",\n weight: 1,\n lhr0: 9,\n lhr: 18,\n uhr: 36,\n uhr0: 45,\n },\n {\n name: \"potassiumMilligrams\",\n units: \"mg\",\n weight: 2,\n lhr0: 1750,\n lhr: 3500,\n uhr: 7000,\n uhr0: 8750,\n },\n {\n name: \"proteinGrams\",\n units: \"g\",\n weight: 1,\n lhr0: 25,\n lhr: 50,\n uhr: 175,\n uhr0: 200,\n },\n {\n name: \"sodiumMilligrams\",\n units: \"mg\",\n weight: 1,\n lhr0: 0,\n lhr: 0,\n uhr: 2000,\n uhr0: 3000,\n },\n ],\n};\nconst RANGE_PROFILE_KEY = {\n PHL: \"SEA\",\n VNM: \"SEA\",\n IDN: \"SEA\",\n MYS: \"SEA\",\n};\n\nconst LIMITS_PER_KCAL = {\n sodiumMilligrams: 150,\n calciumMilligrams: 100,\n fatTotalGrams: 0.1,\n ironMilligrams: 0.45,\n potassiumMilligrams: 75,\n proteinGrams: 0.25,\n};\n\nmodule.exports = {\n ENERGY_BASELINE,\n SCALING_FACTOR,\n SCORE_MAX,\n RANGE_PROFILES,\n LIMITS_PER_KCAL,\n RANGE_PROFILE_KEY,\n};\n"],"names":[],"version":3,"file":"module.js.map"}