{
  "schemaVersion": 1,
  "slug": "rice-water-ratio-calculator",
  "category": "cooking",
  "kind": "implementation",
  "independentValidation": false,
  "implementationHash": "5676d4a8b1eb181e1d41124bb58a74cde0f5829e18fb5eded226f4fda0fe0511",
  "provenance": "Generated from the calculation contract used by the published page. Publication is not external validation.",
  "sourceFiles": [
    "data/calculators/rice-water-ratio-calculator.json",
    "src/engine.js"
  ],
  "runtimeSource": "/sources/engine.txt",
  "runtimeHash": "5c888d8898afbdee36267bb9977829e1e2ac568f6677c8ee87469c139864645c",
  "scope": "The compute function records implemented equations, constants, lookup tables and custom rules. Inputs record defaults and allowed values; outputs record precision and units. Defaults are examples, not recommendations. General background references are not evidence for this specific algorithm.",
  "publishedFormula": {
    "formula": "water cups = dry rice cups × entered water/rice ratio; water ml = water cups × entered cup ml; cooked yield = dry cups × entered yield factor",
    "vars": [],
    "note": "The initial 2:1 ratio is an example, not a universal recommendation. Cooker fill lines can use different measures; never treat the displayed water depth as a cooker instruction."
  },
  "externalEvidence": {
    "reviewedAt": "2026-10-31",
    "basis": "This is a recipe scaler, not an automatic variety or cooker model. Enter the water-to-dry-rice ratio, measuring-cup volume, cooking time and yield assumption from your package or tested recipe. The variety is context only and does not change those inputs. The initial 2:1 ratio is an example, not a universal recommendation. Cooker fill lines can use different measures; never treat the displayed water depth as a cooker instruction.",
    "limitations": "The initial 2:1 ratio is an example, not a universal recommendation. Cooker fill lines can use different measures; never treat the displayed water depth as a cooker instruction.",
    "implementationHash": "5676d4a8b1eb181e1d41124bb58a74cde0f5829e18fb5eded226f4fda0fe0511",
    "sources": [
      {
        "name": "Tilda — one product-specific recipe example",
        "url": "https://www.tilda.com/en-ca/how-to/how-to-cook-basmati-rice/"
      },
      {
        "name": "Zojirushi — rice-cooker measuring guidance",
        "url": "https://www.zojirushi.com/app/faq/rice-cookers"
      }
    ],
    "referenceRole": "context"
  },
  "contract": {
    "compute": "try{if(((true)&&(!Number.isFinite(cups)||cups<0||cups>100))||((true)&&(!Number.isFinite(servings)||servings<1||servings>200))||((true)&&(!Number.isFinite(potWidth)||potWidth<1||potWidth>100))||((true)&&(!Number.isFinite(waterPerCup)||waterPerCup<0.1||waterPerCup>10))||((true)&&(!Number.isFinite(cupMl)||cupMl<100||cupMl>1000))||((true)&&(!Number.isFinite(yieldFactor)||yieldFactor<1||yieldFactor>10))||((true)&&(!Number.isFinite(cookMinutesInput)||cookMinutesInput<0||cookMinutesInput>240))||((true)&&(!Number.isFinite(restMinutesInput)||restMinutesInput<0||restMinutesInput>120)))throw new Error('inputError');const calculate=function(){const h=(function context() {\n  const DAY=86400000;\n  const own=(o,k)=>Object.prototype.hasOwnProperty.call(o,k);\n  const fail=()=>{throw new Error('inputError');};\n  const num=(v,min=-Infinity,max=Infinity,integer=false)=>{\n    if(!Number.isFinite(v)||v<min||v>max||(integer&&!Number.isInteger(v)))fail();return v;\n  };\n  const choice=(v,values)=>{if(!values.includes(v))fail();return v;};\n  const date=s=>{if(typeof s!=='string'||!/^\\d{4}-\\d{2}-\\d{2}$/.test(s)||s.startsWith('0000'))fail();const d=new Date(s+'T00:00:00Z');if(!Number.isFinite(+d)||d.toISOString().slice(0,10)!==s)fail();return d;};\n  const iso=d=>{if(!Number.isFinite(+d)||d.getUTCFullYear()<1||d.getUTCFullYear()>9999)fail();return d.toISOString().slice(0,10);};\n  const shift=(d,n)=>{const r=new Date(+d+n*DAY);iso(r);return r;};\n  const month=(d,n)=>{const r=new Date(+d);r.setUTCDate(1);r.setUTCMonth(r.getUTCMonth()+n);const end=new Date(+r);end.setUTCMonth(end.getUTCMonth()+1,0);r.setUTCDate(Math.min(d.getUTCDate(),end.getUTCDate()));iso(r);return r;};\n  const weekdays=['Sunday','Monday','Tuesday','Wednesday','Thursday','Friday','Saturday'];\n  const work=(d,count)=>{let n=Math.floor(count/7)*5;for(let k=0;k<count%7;k++){const w=(d.getUTCDay()+k)%7;if(w!==0&&w!==6)n++;}return n;};\n  const wholeMonths=(a,b)=>{let n=(b.getUTCFullYear()-a.getUTCFullYear())*12+b.getUTCMonth()-a.getUTCMonth();if(n>=0&&+month(a,n)>+b)n--;if(n<0&&+month(a,n)<+b)n++;return n;};\n  return {DAY,own,fail,num,choice,date,iso,shift,month,weekdays,work,wholeMonths};\n})();const result=(function(v,h){\n    const {num,choice}=h;choice(v.riceType,['longgrain','long','shortgrain','short','brown','basmati','jasmine','sticky','wild']);num(v.cups,0,100);num(v.waterPerCup,0.1,10);num(v.cupMl,100,1000);num(v.servings,1,200,true);num(v.potWidth,1,100);num(v.yieldFactor,1,10);num(v.cookMinutesInput,0,240);num(v.restMinutesInput,0,120);\n    const waterCups=v.cups*v.waterPerCup,cookedYield=v.cups*v.yieldFactor;\n    return {waterCups,waterMl:waterCups*v.cupMl,ratio:'1 to '+v.waterPerCup,cookedYield,servingSize:cookedYield/v.servings,cookTime:v.cups?v.cookMinutesInput:0,restTime:v.cups?v.restMinutesInput:0,waterDepth:waterCups*v.cupMl/16.387064/(Math.PI*(v.potWidth/2)**2),cookMinutes:v.cups?v.cookMinutesInput:0,servings:v.servings};\n  })({\"cups\":(cups),\"riceType\":(riceType),\"waterPerCup\":(waterPerCup),\"cupMl\":(cupMl),\"servings\":(servings),\"potWidth\":(potWidth),\"yieldFactor\":(yieldFactor),\"cookMinutesInput\":(cookMinutesInput),\"restMinutesInput\":(restMinutesInput)},h);return result;};const out=calculate();return Object.fromEntries([\"waterCups\",\"ratio\",\"cookedYield\",\"servingSize\",\"cookTime\",\"restTime\",\"waterDepth\",\"waterMl\"].map(k=>[k,out[k]??null]).concat(Object.entries(out).filter(([k])=>k.startsWith('__'))));}catch(error){return Object.assign(Object.fromEntries([\"waterCups\",\"ratio\",\"cookedYield\",\"servingSize\",\"cookTime\",\"restTime\",\"waterDepth\",\"waterMl\"].map(k=>[k,null])),{__error:error.message==='openingsExceedWallArea'?'openingsExceedWallArea':'inputError'});}",
    "inputs": [
      {
        "name": "riceType",
        "type": "select",
        "default": "longgrain",
        "options": [
          {
            "value": "longgrain"
          },
          {
            "value": "basmati"
          },
          {
            "value": "jasmine"
          },
          {
            "value": "shortgrain"
          },
          {
            "value": "brown"
          },
          {
            "value": "wild"
          }
        ]
      },
      {
        "name": "cups",
        "type": "number",
        "default": 2,
        "min": 0,
        "max": 100,
        "step": 0.25,
        "slider": true,
        "strictRange": true,
        "requiredValue": true
      },
      {
        "name": "servings",
        "type": "number",
        "default": 4,
        "min": 1,
        "max": 200,
        "step": 1,
        "slider": true,
        "strictRange": true,
        "requiredValue": true
      },
      {
        "name": "potWidth",
        "type": "number",
        "default": 8,
        "min": 1,
        "max": 100,
        "step": 0.01,
        "slider": true,
        "strictRange": true,
        "requiredValue": true
      },
      {
        "type": "number",
        "default": 2,
        "min": 0.1,
        "max": 10,
        "step": 0.01,
        "strictRange": true,
        "requiredValue": true,
        "advanced": false,
        "name": "waterPerCup"
      },
      {
        "type": "number",
        "default": 236.5882365,
        "min": 100,
        "max": 1000,
        "step": 0.01,
        "strictRange": true,
        "requiredValue": true,
        "advanced": true,
        "name": "cupMl"
      },
      {
        "type": "number",
        "default": 3,
        "min": 1,
        "max": 10,
        "step": 0.01,
        "strictRange": true,
        "requiredValue": true,
        "advanced": true,
        "name": "yieldFactor"
      },
      {
        "type": "number",
        "default": 18,
        "min": 0,
        "max": 240,
        "step": 1,
        "strictRange": true,
        "requiredValue": true,
        "advanced": true,
        "name": "cookMinutesInput"
      },
      {
        "type": "number",
        "default": 10,
        "min": 0,
        "max": 120,
        "step": 1,
        "strictRange": true,
        "requiredValue": true,
        "advanced": true,
        "name": "restMinutesInput"
      }
    ],
    "outputs": [
      {
        "name": "waterCups",
        "precision": 2,
        "unit": "cups",
        "notation": "auto"
      },
      {
        "name": "ratio",
        "precision": 0,
        "unit": "",
        "type": "text"
      },
      {
        "name": "cookedYield",
        "precision": 2,
        "unit": "cups",
        "notation": "auto"
      },
      {
        "name": "servingSize",
        "precision": 2,
        "unit": "cups",
        "notation": "auto"
      },
      {
        "name": "cookTime",
        "precision": 0,
        "unit": "minutes",
        "notation": "auto"
      },
      {
        "name": "restTime",
        "precision": 0,
        "unit": "minutes",
        "notation": "auto"
      },
      {
        "name": "waterDepth",
        "precision": 2,
        "unit": "in",
        "notation": "auto"
      },
      {
        "name": "waterMl",
        "precision": 0,
        "unit": "ml",
        "notation": "auto"
      }
    ],
    "interpret": null
  }
}
