Spaces:
Running
Running
| <html lang="en"> | |
| <head> | |
| <meta charset="UTF-8"> | |
| <meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=yes"> | |
| <title>Eco — 1:1:1:1 Exact Equality Meal Planner</title> | |
| <style> | |
| :root { | |
| --primary: #2563eb; | |
| --primary-dark: #1d4ed8; | |
| --accent: #eab308; | |
| --success: #22c55e; | |
| --bg-gradient: linear-gradient(135deg, #1e40af 0%, #2563eb 100%); | |
| --card-bg: #ffffff; | |
| --text-main: #1e293b; | |
| --text-sub: #475569; | |
| --border-radius: 24px; | |
| } | |
| * { box-sizing: border-box; transition: all 0.2s ease; } | |
| body { | |
| background: var(--bg-gradient); | |
| font-family: 'Segoe UI', Roboto, 'Helvetica Neue', sans-serif; | |
| margin: 0; | |
| padding: 24px 16px; | |
| min-height: 100vh; | |
| color: var(--text-main); | |
| } | |
| .container { | |
| max-width: 1400px; | |
| margin: 0 auto; | |
| background: var(--card-bg); | |
| border-radius: var(--border-radius); | |
| box-shadow: 0 30px 50px -12px rgba(0, 0, 0, 0.4); | |
| overflow: hidden; | |
| display: flex; | |
| flex-direction: column; | |
| } | |
| header { | |
| padding: 24px 32px; | |
| border-bottom: 1px solid #e2e8f0; | |
| background: #f8fafc; | |
| } | |
| h1 { font-size: 1.8rem; margin: 0; color: var(--text-main); display: flex; align-items: center; gap: 12px; } | |
| h1 small { font-size: 0.85rem; font-weight: normal; color: var(--text-sub); text-transform: uppercase; letter-spacing: 1px; } | |
| .footer-link { | |
| margin-left: auto; | |
| font-size: 0.75rem; | |
| color: var(--text-sub); | |
| text-decoration: none; | |
| font-weight: 600; | |
| } | |
| .footer-link:hover { color: var(--primary); text-decoration: underline; } | |
| .main-content { | |
| display: grid; | |
| grid-template-columns: 380px 1fr; | |
| gap: 0; | |
| min-height: 600px; | |
| } | |
| /* Sidebar Inputs */ | |
| .sidebar { | |
| background: #f1f5f9; | |
| padding: 24px; | |
| border-right: 1px solid #e2e8f0; | |
| overflow-y: auto; | |
| height: 100%; | |
| } | |
| .input-group { margin-bottom: 20px; } | |
| .input-group h3 { font-size: 0.85rem; text-transform: uppercase; color: var(--text-sub); margin-bottom: 12px; letter-spacing: 0.5px; } | |
| .control-row { margin-bottom: 16px; } | |
| label { display: block; font-size: 0.8rem; font-weight: 700; margin-bottom: 6px; color: var(--text-main); } | |
| input[type="number"], select { | |
| width: 100%; | |
| padding: 10px 12px; | |
| border: 1px solid #cbd5e1; | |
| border-radius: 12px; | |
| font-size: 0.9rem; | |
| background: white; | |
| outline: none; | |
| } | |
| input[type="number"]:focus, select:focus { border-color: var(--primary); box-shadow: 0 0 0 3px rgba(37,99,235,0.1); } | |
| .checkbox-wrapper { display: flex; align-items: center; gap: 10px; margin-top: 8px; cursor: pointer; } | |
| .checkbox-wrapper input { width: auto; accent-color: var(--primary); transform: scale(1.2); } | |
| .checkbox-wrapper span { font-size: 0.85rem; color: var(--text-sub); } | |
| .btn-group { display: flex; flex-direction: column; gap: 12px; margin-top: 30px; border-top: 2px solid #e2e8f0; padding-top: 20px; } | |
| button { | |
| width: 100%; | |
| padding: 14px; | |
| border: none; | |
| border-radius: 14px; | |
| font-weight: 700; | |
| font-size: 0.95rem; | |
| cursor: pointer; | |
| display: flex; | |
| align-items: center; | |
| justify-content: center; | |
| gap: 8px; | |
| transition: transform 0.1s, box-shadow 0.2s; | |
| } | |
| .btn-primary { background: var(--primary); color: white; box-shadow: 0 4px 12px rgba(37,99,235,0.3); } | |
| .btn-primary:hover { background: var(--primary-dark); transform: translateY(-1px); } | |
| .btn-secondary { background: white; color: var(--text-main); border: 2px solid #cbd5e1; } | |
| .btn-secondary:hover { background: #f1f5f9; border-color: var(--text-sub); } | |
| .btn-success { background: var(--success); color: white; box-shadow: 0 4px 12px rgba(34,197,94,0.3); } | |
| .btn-success:hover { background: #16a34a; transform: translateY(-1px); } | |
| /* Main Results Area */ | |
| .dashboard { | |
| padding: 32px; | |
| display: flex; | |
| flex-direction: column; | |
| gap: 24px; | |
| } | |
| .stats-bar { | |
| display: grid; | |
| grid-template-columns: repeat(4, 1fr); | |
| gap: 16px; | |
| background: #fff; | |
| padding: 20px; | |
| border-radius: 20px; | |
| border: 1px solid #e2e8f0; | |
| text-align: center; | |
| } | |
| .stat-box h4 { font-size: 0.75rem; text-transform: uppercase; color: var(--text-sub); margin: 0; } | |
| .stat-box .val { font-size: 2rem; font-weight: 800; margin: 8px 0; } | |
| .stat-carbs { color: #ef4444; border-bottom: 3px solid #ef4444; } | |
| .stat-protein { color: #f97316; border-bottom: 3px solid #f97316; } | |
| .stat-fat { color: #eab308; border-bottom: 3px solid #eab308; } | |
| .stat-vitamins { color: #22c55e; border-bottom: 3px solid #22c55e; } | |
| .chart-section { | |
| display: grid; | |
| grid-template-columns: 1fr 1fr; | |
| gap: 24px; | |
| align-items: center; | |
| } | |
| .chart-panel { | |
| background: white; | |
| padding: 20px; | |
| border-radius: 24px; | |
| box-shadow: 0 4px 6px -1px rgba(0,0,0,0.05); | |
| text-align: center; | |
| } | |
| .chart-title { font-weight: 700; margin-bottom: 16px; color: var(--text-main); } | |
| canvas { max-width: 100%; height: auto; } | |
| .meal-planner { | |
| background: #fefce8; | |
| border: 2px solid #fde047; | |
| border-radius: 24px; | |
| padding: 24px; | |
| position: relative; | |
| } | |
| .meal-planner::before { | |
| content: "🎯 OPTIMAL 1:1:1:1 MEAL PLAN"; | |
| position: absolute; | |
| top: -16px; | |
| left: 20px; | |
| background: #fde047; | |
| padding: 0 12px; | |
| font-weight: 800; | |
| font-size: 0.8rem; | |
| color: #854d0e; | |
| border-radius: 12px; | |
| } | |
| .meal-list { | |
| display: flex; | |
| flex-direction: column; | |
| gap: 12px; | |
| max-height: 300px; | |
| overflow-y: auto; | |
| padding-right: 8px; | |
| } | |
| .meal-item { | |
| background: white; | |
| padding: 12px 16px; | |
| border-radius: 16px; | |
| display: flex; | |
| justify-content: space-between; | |
| align-items: center; | |
| border-left: 4px solid var(--primary); | |
| box-shadow: 0 2px 4px rgba(0,0,0,0.05); | |
| } | |
| .meal-details { display: flex; flex-direction: column; gap: 4px; } | |
| .meal-name { font-weight: 700; font-size: 1.1rem; color: var(--text-main); } | |
| .meal-nutrients { font-size: 0.8rem; font-family: monospace; color: var(--text-sub); } | |
| .meal-count { font-weight: 700; background: var(--primary); color: white; padding: 4px 10px; border-radius: 20px; font-size: 0.85rem; } | |
| .math-note { | |
| background: #eef2ff; | |
| padding: 16px; | |
| border-radius: 16px; | |
| font-family: 'Courier New', monospace; | |
| font-size: 0.9rem; | |
| color: #3730a3; | |
| margin-top: 10px; | |
| border-left: 5px solid var(--primary); | |
| } | |
| .math-note strong { color: var(--primary-dark); } | |
| /* Food Selector Panel */ | |
| .food-panel { | |
| position: sticky; | |
| bottom: 0; | |
| left: 0; | |
| width: 100%; | |
| background: white; | |
| border-top: 1px solid #cbd5e1; | |
| padding: 16px; | |
| display: none; /* Hidden by default */ | |
| animation: slideUp 0.3s ease; | |
| } | |
| .food-panel.active { display: block; } | |
| @keyframes slideUp { from { transform: translateY(100%); } to { transform: translateY(0); } } | |
| .food-header { display: flex; justify-content: space-between; margin-bottom: 12px; } | |
| .food-search { display: flex; gap: 10px; margin-bottom: 12px; } | |
| .food-list { display: grid; grid-template-columns: repeat(auto-fill, minmax(200px, 1fr)); gap: 8px; max-height: 200px; overflow-y: auto; padding: 8px; background: #f8fafc; border-radius: 12px; } | |
| .food-item { display: flex; align-items: center; gap: 8px; padding: 6px; background: white; border-radius: 8px; border: 1px solid #e2e8f0; font-size: 0.8rem; } | |
| .food-item input { width: auto; margin: 0; } | |
| @media (max-width: 900px) { | |
| .main-content { grid-template-columns: 1fr; } | |
| .sidebar { border-right: none; border-bottom: 1px solid #e2e8f0; } | |
| .stats-bar { grid-template-columns: 1fr 1fr; } | |
| .chart-section { grid-template-columns: 1fr; } | |
| } | |
| </style> | |
| </head> | |
| <body> | |
| <div class="container"> | |
| <header> | |
| <h1> | |
| 🌾 ECO Planner | |
| <small>1:1:1:1 Exact Equality Engine</small> | |
| </h1> | |
| <a href="https://huggingface.co/spaces/akhaliq/anycoder" target="_blank" class="footer-link">Built with anycoder</a> | |
| </header> | |
| <div class="main-content"> | |
| <!-- Sidebar Controls --> | |
| <aside class="sidebar"> | |
| <div class="input-group"> | |
| <h3>👤 Player Status</h3> | |
| <div class="control-row"> | |
| <label>Current Calories</label> | |
| <input type="number" id="curCalories" value="1200" min="0"> | |
| </div> | |
| <div class="control-row"> | |
| <label>Max Calories Capacity</label> | |
| <input type="number" id="maxCalories" value="3000" min="1000"> | |
| </div> | |
| <div class="checkbox-wrapper"> | |
| <input type="checkbox" id="ignoreCalorieLimit"> | |
| <span>Ignore Calorie Limit (Unlimited Mode)</span> | |
| </div> | |
| </div> | |
| <div class="input-group"> | |
| <h3>⚖️ Current Nutrients (Base)</h3> | |
| <div class="control-row"> | |
| <label>🍞 Carbs (C)</label> | |
| <input type="number" id="carbs" value="8" step="1"> | |
| </div> | |
| <div class="control-row"> | |
| <label>🍗 Protein (P)</label> | |
| <input type="number" id="protein" value="12" step="1"> | |
| </div> | |
| <div class="control-row"> | |
| <label>🧈 Fat (F)</label> | |
| <input type="number" id="fat" value="6" step="1"> | |
| </div> | |
| <div class="control-row"> | |
| <label>🥕 Vitamins (V)</label> | |
| <input type="number" id="vitamins" value="14" step="1"> | |
| </div> | |
| </div> | |
| <div class="input-group"> | |
| <h3>🍽️ Filters</h3> | |
| <div class="control-row"> | |
| <label>Player Tier / Skill</label> | |
| <select id="tier"> | |
| <option value="all">🌟 All Foods Available</option> | |
| <option value="starter">🌱 Starter (Easy)</option> | |
| <option value="campfire">🔥 Campfire Cook</option> | |
| <option value="gatherer">🍄 Gatherer (Raw/Basic)</option> | |
| <option value="baked">🍞 Baked Specialist</option> | |
| <option value="cooked">🍲 Cooked Specialist</option> | |
| <option value="advanced">🏆 Advanced Chef</option> | |
| </select> | |
| </div> | |
| <div class="control-row"> | |
| <label>Preferred Biome</label> | |
| <select id="biomeFilter"> | |
| <option value="all">🌍 Any Biome</option> | |
| <option value="forest">🌲 Forest</option> | |
| <option value="grassland">🌾 Grassland</option> | |
| <option value="desert">🏜️ Desert</option> | |
| <option value="rainforest">🌧️ Rainforest</option> | |
| <option value="aquatic">💧 Aquatic</option> | |
| </select> | |
| </div> | |
| <div class="checkbox-wrapper"> | |
| <input type="checkbox" id="disableTierFilter" checked> | |
| <span>Disable Tier Filter</span> | |
| </div> | |
| <div class="checkbox-wrapper"> | |
| <input type="checkbox" id="disableBiomeFilter" checked> | |
| <span>Disable Biome Filter</span> | |
| </div> | |
| </div> | |
| <div class="btn-group"> | |
| <button id="toggleFoodPanelBtn" class="btn-secondary">📋 Edit Food Database</button> | |
| <button id="randomizeBtn" class="btn-secondary">🎲 Random Balanced Plan</button> | |
| <button id="calculateBtn" class="btn-primary">⚖️ CALCULATE PERFECT BALANCE</button> | |
| </div> | |
| </aside> | |
| <!-- Main Dashboard --> | |
| <main class="dashboard"> | |
| <!-- Current Stats Header --> | |
| <div class="stats-bar"> | |
| <div class="stat-box stat-carbs"> | |
| <h4>Current Carbs</h4> | |
| <div class="val" id="dispCurC">8</div> | |
| </div> | |
| <div class="stat-box stat-protein"> | |
| <h4>Current Protein</h4> | |
| <div class="val" id="dispCurP">12</div> | |
| </div> | |
| <div class="stat-box stat-fat"> | |
| <h4>Current Fat</h4> | |
| <div class="val" id="dispCurF">6</div> | |
| </div> | |
| <div class="stat-box stat-vitamins"> | |
| <h4>Current Vitamins</h4> | |
| <div class="val" id="dispCurV">14</div> | |
| </div> | |
| </div> | |
| <!-- Charts Section --> | |
| <div class="chart-section"> | |
| <div class="chart-panel"> | |
| <div class="chart-title">Current Nutrient Status</div> | |
| <canvas id="beforeChart" width="300" height="300"></canvas> | |
| </div> | |
| <div class="chart-panel"> | |
| <div class="chart-title">Target: 1:1:1:1 Equality</div> | |
| <canvas id="afterChart" width="300" height="300"></canvas> | |
| </div> | |
| </div> | |
| <!-- Meal Plan Output --> | |
| <div class="meal-planner"> | |
| <h3 style="margin-top:0; font-size:1.2rem;">Generated Meal Plan</h3> | |
| <div id="mealListContainer" class="meal-list"> | |
| <div style="text-align:center; padding: 40px 0; color: #94a3b8;"> | |
| Click "Calculate Perfect Balance" to generate a meal plan that equalizes all nutrients exactly. | |
| </div> | |
| </div> | |
| <div id="mathNote" class="math-note"> | |
| <strong>🧮 ALGORITHM STATUS:</strong> <br> | |
| Waiting for calculation... | |
| </div> | |
| <div style="display:flex; justify-content:space-between; margin-top:10px; font-size:0.9rem; color:var(--text-sub);"> | |
| <span id="calorieSummary">Calorie Budget: 1200 / 3000</span> | |
| <span id="planCounter" style="font-weight:bold; color:var(--primary);">Plan 1 of 1</span> | |
| </div> | |
| </div> | |
| </main> | |
| </div> | |
| <!-- Food Selector Panel --> | |
| <div id="foodPanel" class="food-panel"> | |
| <div class="food-header"> | |
| <h3>🍽️ Active Food Database</h3> | |
| <button onclick="document.getElementById('foodPanel').classList.remove('active')" style="padding: 4px 12px; font-size: 0.8rem;">Close</button> | |
| </div> | |
| <div class="food-search"> | |
| <input type="text" id="foodSearch" placeholder="Search food by name..." style="flex:1;"> | |
| <button id="selectAllBtn" style="padding: 8px 16px; font-size: 0.8rem; background: #cbd5e1;">Select All</button> | |
| </div> | |
| <div id="foodListContainer" class="food-list"> | |
| <!-- Food items injected here --> | |
| </div> | |
| </div> | |
| </div> | |
| <script> | |
| // ==================== DATA & CONSTANTS ==================== | |
| const RAW_FOODS = [ | |
| { name: "Heart Of Palm", carbs:4, protein:2, fat:0, vitamins:2, cal:100, tier:"gatherer", biomes:["rainforest","forest"] }, | |
| { name: "Bolete Mushrooms", carbs:2, protein:4, fat:1, vitamins:1, cal:200, tier:"gatherer", biomes:["forest"] }, | |
| { name: "Leavened Dough", carbs:6, protein:18, fat:13, vitamins:5, cal:10, tier:"advanced", biomes:["any"] }, | |
| { name: "Charred Taro", carbs:10, protein:1, fat:0, vitamins:1, cal:350, tier:"campfire", biomes:["rainforest","forest"] }, | |
| { name: "Taro Root", carbs:6, protein:1, fat:0, vitamins:1, cal:250, tier:"gatherer", biomes:["rainforest","forest"] }, | |
| { name: "Baked Agave", carbs:14, protein:2, fat:4, vitamins:8, cal:700, tier:"baked", biomes:["desert"] }, | |
| { name: "Huckleberries", carbs:2, protein:0, fat:0, vitamins:6, cal:150, tier:"gatherer", biomes:["forest"] }, | |
| { name: "Pupusas", carbs:6, protein:11, fat:9, vitamins:14, cal:900, tier:"advanced", biomes:["any"] }, | |
| { name: "Vegetable Medley", carbs:8, protein:4, fat:7, vitamins:17, cal:900, tier:"cooked", biomes:["any"] }, | |
| { name: "Huckleberry Fritter", carbs:16, protein:0, fat:20, vitamins:8, cal:900, tier:"baked", biomes:["forest"] }, | |
| { name: "Baked Heart Of Palm", carbs:12, protein:6, fat:4, vitamins:6, cal:700, tier:"baked", biomes:["rainforest"] }, | |
| { name: "Camas Bulb Bake", carbs:12, protein:7, fat:5, vitamins:4, cal:700, tier:"baked", biomes:["grassland"] }, | |
| { name: "Pineapple", carbs:6, protein:0, fat:0, vitamins:2, cal:200, tier:"gatherer", biomes:["rainforest"] }, | |
| { name: "Basic Salad", carbs:18, protein:6, fat:4, vitamins:10, cal:800, tier:"starter", biomes:["any"] }, | |
| { name: "Scrap Meat", carbs:0, protein:5, fat:5, vitamins:0, cal:50, tier:"starter", biomes:["any"] }, | |
| { name: "Charred Sausage", carbs:0, protein:10, fat:14, vitamins:0, cal:700, tier:"campfire", biomes:["any"] }, | |
| { name: "Clam Chowder", carbs:16, protein:15, fat:3, vitamins:11, cal:800, tier:"cooked", biomes:["aquatic"] }, | |
| { name: "Wild Stew", carbs:10, protein:2, fat:6, vitamins:12, cal:1100, tier:"cooked", biomes:["forest"] }, | |
| { name: "Fried Vegetables", carbs:11, protein:3, fat:8, vitamins:2, cal:560, tier:"cooked", biomes:["any"] }, | |
| { name: "Tasty Tropical Pizza", carbs:21, protein:6, fat:12, vitamins:11, cal:1200, tier:"advanced", biomes:["rainforest"] }, | |
| { name: "Meat Pie", carbs:18, protein:4, fat:20, vitamins:2, cal:1300, tier:"baked", biomes:["any"] }, | |
| { name: "Fireweed Shoots", carbs:3, protein:1, fat:0, vitamins:4, cal:150, tier:"gatherer", biomes:["grassland"] }, | |
| { name: "Crimson Salad", carbs:13, protein:7, fat:8, vitamins:28, cal:1200, tier:"advanced", biomes:["any"] }, | |
| { name: "Baked Tomato", carbs:16, protein:1, fat:5, vitamins:6, cal:700, tier:"baked", biomes:["grassland"] }, | |
| { name: "Corn Fritters", carbs:13, protein:4, fat:22, vitamins:8, cal:500, tier:"cooked", biomes:["grassland"] }, | |
| { name: "Baked Meat", carbs:0, protein:17, fat:13, vitamins:0, cal:700, tier:"baked", biomes:["any"] }, | |
| { name: "Bison Chow Fun", carbs:16, protein:13, fat:20, vitamins:8, cal:1450, tier:"advanced", biomes:["grassland"] }, | |
| { name: "Pineapple Friend Rice", carbs:20, protein:9, fat:12, vitamins:12, cal:720, tier:"cooked", biomes:["rainforest"] }, | |
| { name: "Baked Roast", carbs:4, protein:16, fat:10, vitamins:4, cal:1000, tier:"baked", biomes:["any"] }, | |
| { name: "Camas Bread", carbs:13, protein:5, fat:11, vitamins:7, cal:800, tier:"baked", biomes:["grassland"] }, | |
| { name: "Elk Taco", carbs:15, protein:8, fat:22, vitamins:6, cal:700, tier:"cooked", biomes:["forest"] }, | |
| { name: "Flaxseed Oil", carbs:0, protein:0, fat:15, vitamins:0, cal:120, tier:"starter", biomes:["grassland"] }, | |
| { name: "Sugar", carbs:15, protein:0, fat:0, vitamins:0, cal:50, tier:"starter", biomes:["any"] }, | |
| { name: "Papaya", carbs:2, protein:1, fat:0, vitamins:5, cal:200, tier:"gatherer", biomes:["rainforest"] }, | |
| { name: "Infused Oil", carbs:0, protein:0, fat:12, vitamins:3, cal:120, tier:"advanced", biomes:["any"] }, | |
| { name: "Wilted Fiddleheads", carbs:4, protein:1, fat:0, vitamins:7, cal:350, tier:"gatherer", biomes:["forest"] }, | |
| { name: "Wild Mix", carbs:15, protein:6, fat:4, vitamins:21, cal:800, tier:"cooked", biomes:["any"] }, | |
| { name: "Elk Wellington", carbs:10, protein:26, fat:22, vitamins:4, cal:1450, tier:"advanced", biomes:["forest"] }, | |
| { name: "Wheat", carbs:6, protein:2, fat:0, vitamins:0, cal:150, tier:"gatherer", biomes:["grassland"] }, | |
| { name: "Bear S U P R E M E", carbs:6, protein:22, fat:23, vitamins:9, cal:1250, tier:"advanced", biomes:["forest"] }, | |
| { name: "Vegetable Stock", carbs:11, protein:1, fat:2, vitamins:11, cal:700, tier:"cooked", biomes:["any"] }, | |
| { name: "Vegetable Soup", carbs:12, protein:4, fat:7, vitamins:19, cal:1200, tier:"cooked", biomes:["any"] }, | |
| { name: "Autumn Stew", carbs:13, protein:8, fat:5, vitamins:12, cal:1200, tier:"cooked", biomes:["forest"] }, | |
| { name: "Bean Paste", carbs:3, protein:5, fat:7, vitamins:0, cal:40, tier:"starter", biomes:["any"] }, | |
| { name: "Bearclaw", carbs:14, protein:4, fat:21, vitamins:7, cal:850, tier:"baked", biomes:["forest"] }, | |
| { name: "Pirozhok", carbs:14, protein:19, fat:10, vitamins:4, cal:850, tier:"advanced", biomes:["any"] }, | |
| { name: "Bread", carbs:23, protein:6, fat:4, vitamins:2, cal:750, tier:"baked", biomes:["any"] }, | |
| { name: "Seared Meat", carbs:4, protein:19, fat:17, vitamins:7, cal:600, tier:"cooked", biomes:["any"] }, | |
| { name: "Prickly Pear Fruit", carbs:2, protein:1, fat:1, vitamins:4, cal:190, tier:"gatherer", biomes:["desert"] }, | |
| { name: "Phad Thai", carbs:9, protein:11, fat:19, vitamins:5, cal:1200, tier:"advanced", biomes:["any"] }, | |
| { name: "Camas Bulb", carbs:1, protein:2, fat:5, vitamins:0, cal:150, tier:"gatherer", biomes:["grassland"] }, | |
| { name: "Topped Porridge", carbs:10, protein:4, fat:0, vitamins:10, cal:700, tier:"cooked", biomes:["any"] }, | |
| { name: "Dried Meat", carbs:1, protein:14, fat:4, vitamins:0, cal:550, tier:"campfire", biomes:["any"] }, | |
| { name: "Tomato", carbs:5, protein:1, fat:0, vitamins:2, cal:240, tier:"gatherer", biomes:["grassland"] }, | |
| { name: "Campfire Stew", carbs:5, protein:10, fat:9, vitamins:4, cal:1200, tier:"campfire", biomes:["any"] }, | |
| { name: "Taro Fries", carbs:10, protein:2, fat:20, vitamins:0, cal:600, tier:"cooked", biomes:["rainforest"] }, | |
| { name: "Tallow", carbs:0, protein:0, fat:8, vitamins:0, cal:200, tier:"starter", biomes:["any"] }, | |
| { name: "Sweet Salad", carbs:18, protein:9, fat:7, vitamins:22, cal:1200, tier:"advanced", biomes:["any"] }, | |
| { name: "Raw Fish", carbs:0, protein:7, fat:3, vitamins:0, cal:200, tier:"gatherer", biomes:["aquatic"] }, | |
| { name: "Sweet Deer Jerky", carbs:4, protein:22, fat:6, vitamins:3, cal:600, tier:"campfire", biomes:["forest"] }, | |
| { name: "Beet Greens", carbs:3, protein:1, fat:0, vitamins:4, cal:100, tier:"gatherer", biomes:["grassland"] }, | |
| { name: "Sun Cheese", carbs:2, protein:4, fat:12, vitamins:0, cal:250, tier:"advanced", biomes:["any"] }, | |
| { name: "Worldly Donut", carbs:15, protein:2, fat:17, vitamins:2, cal:750, tier:"baked", biomes:["any"] }, | |
| { name: "Stuffed Turkey", carbs:17, protein:24, fat:16, vitamins:7, cal:1600, tier:"advanced", biomes:["forest"] }, | |
| { name: "Spiky Roll", carbs:20, protein:17, fat:7, vitamins:2, cal:1300, tier:"advanced", biomes:["desert"] }, | |
| { name: "Baked Corn", carbs:12, protein:3, fat:2, vitamins:11, cal:700, tier:"baked", biomes:["grassland"] }, | |
| { name: "Jungle Campfire Salad", carbs:11, protein:4, fat:3, vitamins:10, cal:900, tier:"campfire", biomes:["rainforest"] }, | |
| { name: "Simmered Meat", carbs:6, protein:18, fat:13, vitamins:5, cal:900, tier:"cooked", biomes:["any"] }, | |
| { name: "Beet Campfire Salad", carbs:8, protein:4, fat:3, vitamins:13, cal:900, tier:"campfire", biomes:["grassland"] }, | |
| { name: "Sensuous Sea Pizza", carbs:28, protein:11, fat:7, vitamins:4, cal:1200, tier:"advanced", biomes:["aquatic"] }, | |
| { name: "Seeded Camas Roll", carbs:20, protein:2, fat:13, vitamins:16, cal:1400, tier:"baked", biomes:["grassland"] }, | |
| { name: "Beet", carbs:2, protein:0, fat:2, vitamins:4, cal:230, tier:"gatherer", biomes:["grassland"] }, | |
| { name: "Meaty Stew", carbs:6, protein:13, fat:10, vitamins:1, cal:1100, tier:"cooked", biomes:["any"] }, | |
| { name: "Roast Pumpkin", carbs:23, protein:2, fat:2, vitamins:7, cal:1400, tier:"baked", biomes:["grassland"] }, | |
| { name: "Fried Hare Haunches", carbs:6, protein:15, fat:27, vitamins:4, cal:750, tier:"cooked", biomes:["forest"] }, | |
| { name: "Tortilla", carbs:20, protein:10, fat:0, vitamins:0, cal:350, tier:"baked", biomes:["any"] }, | |
| { name: "Dried Fish", carbs:1, protein:16, fat:2, vitamins:0, cal:450, tier:"campfire", biomes:["aquatic"] }, | |
| { name: "Charred Beans", carbs:1, protein:8, fat:3, vitamins:0, cal:350, tier:"campfire", biomes:["any"] }, | |
| { name: "Kelpy Crab Roll", carbs:22, protein:13, fat:11, vitamins:5, cal:1350, tier:"advanced", biomes:["aquatic"] }, | |
| { name: "Rice", carbs:7, protein:1, fat:0, vitamins:0, cal:150, tier:"gatherer", biomes:["any"] }, | |
| { name: "Charred Beet", carbs:3, protein:0, fat:3, vitamins:6, cal:350, tier:"campfire", biomes:["grassland"] }, | |
| { name: "Pumpkin", carbs:5, protein:1, fat:0, vitamins:2, cal:340, tier:"gatherer", biomes:["grassland"] }, | |
| { name: "Milk", carbs:3, protein:10, fat:7, vitamins:0, cal:120, tier:"gatherer", biomes:["any"] }, | |
| { name: "Fish N Chips", carbs:20, protein:10, fat:20, vitamins:0, cal:1000, tier:"cooked", biomes:["aquatic"] }, | |
| { name: "Raw Meat", carbs:0, protein:4, fat:8, vitamins:0, cal:250, tier:"gatherer", biomes:["any"] }, | |
| { name: "Agouti Enchiladas", carbs:20, protein:8, fat:27, vitamins:3, cal:800, tier:"advanced", biomes:["rainforest"] }, | |
| { name: "Baked Taro", carbs:8, protein:6, fat:2, vitamins:12, cal:700, tier:"baked", biomes:["rainforest"] }, | |
| { name: "Campfire Roast", carbs:0, protein:16, fat:12, vitamins:0, cal:1000, tier:"campfire", biomes:["any"] }, | |
| { name: "Boiled Sausage", carbs:0, protein:27, fat:22, vitamins:0, cal:600, tier:"cooked", biomes:["any"] }, | |
| { name: "Mochi", carbs:25, protein:0, fat:0, vitamins:5, cal:750, tier:"baked", biomes:["any"] }, | |
| { name: "Root Campfire Stew", carbs:8, protein:5, fat:12, vitamins:5, cal:1100, tier:"campfire", biomes:["any"] }, | |
| { name: "Macarons", carbs:20, protein:7, fat:14, vitamins:16, cal:1000, tier:"advanced", biomes:["any"] }, | |
| { name: "Fruit Salad", carbs:12, protein:4, fat:3, vitamins:19, cal:900, tier:"starter", biomes:["any"] }, | |
| { name: "Flatbread", carbs:17, protein:8, fat:3, vitamins:2, cal:500, tier:"baked", biomes:["any"] }, | |
| { name: "Charred Fish", carbs:0, protein:11, fat:4, vitamins:0, cal:400, tier:"campfire", biomes:["aquatic"] }, | |
| { name: "Poke Bowl", carbs:21, protein:10, fat:11, vitamins:7, cal:1100, tier:"advanced", biomes:["aquatic"] }, | |
| { name: "Crispy Bacon", carbs:0, protein:18, fat:26, vitamins:0, cal:800, tier:"cooked", biomes:["any"] }, | |
| { name: "Corn", carbs:4, protein:1, fat:0, vitamins:3, cal:230, tier:"gatherer", biomes:["grassland"] }, | |
| { name: "Millionaires Salad", carbs:18, protein:6, fat:6, vitamins:26, cal:1000, tier:"advanced", biomes:["any"] }, | |
| { name: "Banh Xeo", carbs:26, protein:17, fat:10, vitamins:4, cal:1550, tier:"advanced", biomes:["any"] }, | |
| { name: "Charred Pineapple", carbs:8, protein:1, fat:0, vitamins:3, cal:350, tier:"campfire", biomes:["rainforest"] }, | |
| { name: "Charred Mushrooms", carbs:3, protein:6, fat:2, vitamins:1, cal:350, tier:"campfire", biomes:["forest"] }, | |
| { name: "Fern Campfire Salad", carbs:9, protein:5, fat:1, vitamins:13, cal:900, tier:"campfire", biomes:["forest"] }, | |
| { name: "Boiled Grains", carbs:9, protein:2, fat:0, vitamins:1, cal:350, tier:"starter", biomes:["any"] }, | |
| { name: "Baked Beet", carbs:10, protein:1, fat:2, vitamins:15, cal:700, tier:"baked", biomes:["grassland"] }, | |
| { name: "Rice Noodles", carbs:10, protein:0, fat:0, vitamins:0, cal:200, tier:"starter", biomes:["any"] }, | |
| { name: "Huckleberry Pie", carbs:13, protein:5, fat:10, vitamins:16, cal:1300, tier:"baked", biomes:["forest"] }, | |
| { name: "Fruit Muffin", carbs:10, protein:5, fat:4, vitamins:16, cal:800, tier:"baked", biomes:["any"] } | |
| ]; | |
| // State | |
| let enabledFoods = new Set(RAW_FOODS.map(f => f.name)); | |
| let currentPlanPool = []; | |
| let currentPlanIndex = 0; | |
| // ==================== UTILITIES ==================== | |
| function getFilter() { | |
| const tier = document.getElementById('tier').value; | |
| const disableTier = document.getElementById('disableTierFilter').checked; | |
| const biome = document.getElementById('biomeFilter').value; | |
| const disableBiome = document.getElementById('disableBiomeFilter').checked; | |
| return (food) => { | |
| if (!enabledFoods.has(food.name)) return false; | |
| if (!disableTier && tier !== 'all' && food.tier !== tier) return false; | |
| if (!disableBiome && biome !== 'all' && !food.biomes.includes(biome) && !food.biomes.includes('any')) return false; | |
| return true; | |
| }; | |
| } | |
| function drawPieChart(canvasId, c, p, f, v) { | |
| const canvas = document.getElementById(canvasId); | |
| if (!canvas) return; | |
| const ctx = canvas.getContext('2d'); | |
| const w = canvas.width; | |
| const h = canvas.height; | |
| ctx.clearRect(0, 0, w, h); | |
| const total = c + p + f + v; | |
| if (total === 0) { | |
| ctx.fillStyle = '#cbd5e1'; | |
| ctx.beginPath(); | |
| ctx.arc(w/2, h/2, 100, 0, Math.PI*2); | |
| ctx.fill(); | |
| ctx.fillStyle = '#64748b'; | |
| ctx.font = '20px Arial'; | |
| ctx.textAlign = 'center'; | |
| ctx.fillText("No Data", w/2, h/2 + 7); | |
| return; | |
| } | |
| const vals = [c, p, f, v]; | |
| const colors = ["#ef4444", "#f97316", "#eab308", "#22c55e"]; | |
| let startAngle = -Math.PI / 2; | |
| const cx = w/2, cy = h/2, r = 110; | |
| vals.forEach((val, i) => { | |
| if (val <= 0) return; | |
| const sliceAngle = (val / total) * 2 * Math.PI; | |
| ctx.beginPath(); | |
| ctx.moveTo(cx, cy); | |
| ctx.arc(cx, cy, r, startAngle, startAngle + sliceAngle); | |
| ctx.closePath(); | |
| ctx.fillStyle = colors[i]; | |
| ctx.fill(); | |
| startAngle += sliceAngle; | |
| }); | |
| // Inner circle for donut effect | |
| ctx.beginPath(); | |
| ctx.arc(cx, cy, r * 0.55, 0, 2 * Math.PI); | |
| ctx.fillStyle = "#ffffff"; | |
| ctx.fill(); | |
| // Text in center | |
| ctx.fillStyle = "#334155"; | |
| ctx.font = "bold 24px Segoe UI"; | |
| ctx.textAlign = "center"; | |
| ctx.textBaseline = "middle"; | |
| ctx.fillText(total.toFixed(1), cx, cy); | |
| } | |
| // ==================== CORE ALGORITHM (The Balance Logic) ==================== | |
| function calculatePerfectBalance() { | |
| // 1. Get Inputs | |
| const c = parseFloat(document.getElementById('carbs').value) || 0; |