File size: 9,838 Bytes
45e026b 3d42a7e 45e026b 3d42a7e 45e026b 3d42a7e 45e026b 3ea6c37 45e026b 3ea6c37 45e026b 3ea6c37 065abb2 45e026b 3ea6c37 45e026b 3ea6c37 45e026b 1bb525a 3ea6c37 45e026b e60e419 45e026b 3ea6c37 |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 |
const express = require("express")
const app = express()
const port = 7860
const path = require("path")
app.use(express.static("public"))
app.use(express.urlencoded({ extended: true }))
app.use(express.json())
const fruits = [
["Carrot", 0.275, 20, 100], ["Strawberry", 0.3, 15, 100], ["Blueberry", 0.2, 20, 100], ["Orange Tulip", 0.05, 850, 55],
["Tomato", 0.5, 30, 100], ["Corn", 2, 40, 100], ["Daffodil", 0.2, 1000, 45], ["Watermelon", 7, 3000, 70],
["Pumpkin", 8, 3400, 80], ["Apple", 3, 275, 50], ["Bamboo", 4, 4000, 35], ["Coconut", 14, 400, 70],
["Cactus", 7, 3400, 100], ["Dragon Fruit", 12, 4750, 100], ["Mango", 15, 6500, 200], ["Grape", 3, 7850, 200],
["Mushroom", 25, 151000, 220], ["Pepper", 5, 8000, 200], ["Cacao", 8, 12000, 250], ["Beanstalk", 10, 28000, 300],
["Ember Lily", 12, 66666, 450], ["Sugar Apple", 9, 48000, 200], ["Burning Bud", 12, 65000, 500], ["Cauliflower", 5, 50, 150],
["Rafflesia", 8, 3500, 80], ["Green Apple", 3, 300, 200], ["Avocado", 6.5, 350, 300], ["Banana", 1.5, 2000, 100],
["Pineapple", 3, 2000, 70], ["Kiwi", 5, 2750, 300], ["Bell Pepper", 8, 5500, 325], ["Prickly Pear", 7, 7000, 375],
["Loquat", 6.5, 8000, 200], ["Pitcher Plant", 12, 32000, 275], ["Feijoa", 10, 13000, 400], ["Wild Carrot", 1.3, 25000, 100],
["Pear", 3, 20000, 120], ["Cantaloupe", 5.5, 34000, 250], ["Parasol Flower", 6, 200000, 350],
["Rosy Delight", 10, 69000, 450], ["Elephant Ears", 18, 77000, 500], ["Delphinium", 0.3, 24000, 100],
["Lily of the Valley", 6, 49120, 400], ["Traveler's Fruit", 15, 59000, 500], ["Peace Lily", 0.6, 24000, 100],
["Aloe Vera", 5.5, 69000, 350], ["Guanabana", 4, 72500, 400], ["Chocolate Carrot", 0.275, 11000, 100],
["Red Lollipop", 4, 50000, 65], ["Blue Lollipop", 1, 50000, 65], ["Candy Sunflower", 1.5, 80000, 85],
["Easter Egg", 3, 2500, 20], ["Candy Blossom", 3, 100000, 40], ["Peach", 2, 300, 70], ["Raspberry", 0.75, 100, 70],
["Papaya", 3, 1000, 60], ["Banana", 1.5, 1750, 100], ["Passionfruit", 3, 3550, 40], ["Soul Fruit", 25, 7750, 200],
["Cursed Fruit", 30, 25750, 200], ["Mega Mushroom", 70, 500, 2000000], ["Cherry Blossom", 3, 500, 400],
["Purple Cabbage", 5, 500, 70], ["Lemon", 1, 350, 50], ["Pink Tulip", 0.05, 850, 55], ["Cranberry", 1, 3500, 50],
["Durian", 8, 7500, 200], ["Eggplant", 5, 12000, 220], ["Lotus", 20, 35000, 650], ["Venus Fly Trap", 10, 85000, 650],
["Nightshade", 0.5, 3500, 100], ["Glowshroom", 0.75, 300, 100], ["Mint", 1, 5250, 150], ["Moonflower", 2, 9500, 200],
["Starfruit", 3, 15000, 250], ["Moonglow", 7, 25000, 400], ["Moon Blossom", 3, 66666, 400],
["Crimson Vine", 1, 1250, 100], ["Moon Melon", 8, 18000, 300], ["Blood Banana", 1.5, 6000, 200],
["Celestiberry", 2, 10000, 200], ["Moon Mango", 15, 50000, 300], ["Rose", 1, 5000, 100],
["Foxglove", 2, 20000, 250], ["Lilac", 3, 35000, 250], ["Pink Lily", 6, 65000, 400],
["Purple Dahlia", 12, 75000, 400], ["Sunflower", 16.5, 160000, 600], ["Lavender", 0.275, 25000, 90],
["Nectarshade", 0.8, 50000, 100], ["Nectarine", 3, 48000, 200], ["Hive Fruit", 8, 62000, 300],
["Manuka Flower", 0.3, 25000, 200], ["Dandelion", 4, 50000, 300], ["Lumira", 6, 85000, 350],
["Honeysuckle", 12, 100000, 400], ["Crocus", 0.275, 30000, 150], ["Succulent", 5, 25000, 175],
["Violet Corn", 3, 50000, 250], ["Bendboo", 18, 155000, 275], ["Cocovine", 14, 66666, 275],
["Dragon Pepper", 6, 88888, 300], ["Bee Balm", 1, 18000, 200], ["Nectar Thorn", 7, 44444, 350],
["Suncoil", 10, 80000, 400], ["Noble Flower", 5, 20000, 250], ["Ice Cream Bean", 4, 4500, 200],
["Lime", 1, 1000, 125], ["White Mulberry", 3, 3000, 200]
]
const mutationMultiplier = {
Dawnbound: 150, Voidtouched: 135, Disco: 125, Meteoric: 125, Galactic: 120,
Celestial: 120, Shocked: 100, Alienlike: 100, Paradisal: 100, Aurora: 90, Sundried: 85, Molten: 25,
Zombified: 25, Frozen: 10, Cooked: 10, Fried: 8, Plasma: 5,
Heavenly: 5, HoneyGlazed: 5, Twisted: 5, Cloudtouched: 5, Drenched: 5, Burnt: 4, Bloodlit: 4, Wiltproof: 4,
Verdant: 4, Pollinated: 3, Windstruck: 2, Wet: 2, Chilled: 2,
Choc: 2, Moonlit: 2,
}
const rarityMultiplier = { Normal: 1, Gold: 20, Rainbow: 50 }
function clamp(v, min, max) { return Math.min(Math.max(v, min), max) }
function format(n) { return n.toLocaleString("en-US") + "¢" }
function calcValue(name, weight, rarity = "Normal", mutations = []) {
const item = fruits.find(f => f[0] === name)
if (!item) return "0¢"
let mutationMult = 1
for (const m of mutations) {
mutationMult += (mutationMultiplier[m] || 1) - 1
}
mutationMult = Math.max(1, mutationMult)
const clamped = clamp(weight / item[1], 0.95, 1e8)
const mult = (rarityMultiplier[rarity] || 1) * mutationMult
const value = Math.round(item[2] * mult * (clamped * clamped) + 1)
return format(value)
}
app.get("/", (req, res) => {
const fruitOptions = fruits.map(f => f[0]).sort().map(name => `<option value="${name}">${name}</option>`).join("")
const mutationOptions = Object.keys(mutationMultiplier).map(m => `<option value="${m}">${m}</option>`).join("")
const rarityOptions = ["Normal", "Gold", "Rainbow"].map(r => `<option value="${r}">${r}</option>`).join("")
res.send(`
<!DOCTYPE html>
<html lang='en'>
<head>
<meta charset='UTF-8'>
<meta name='viewport' content='width=device-width, initial-scale=1.0'>
<title>Price Calculator</title>
<script src="https://cdn.tailwindcss.com"></script>
<style>
.fade-in { animation: fadeIn 0.6s ease-in-out; }
@keyframes fadeIn { from { opacity: 0; transform: translateY(20px); } to { opacity: 1; transform: translateY(0); } }
select { appearance: none; background-image: url("data:image/svg+xml,%3Csvg fill='white' viewBox='0 0 20 20' xmlns='http://www.w3.org/2000/svg'%3E%3Cpath d='M10 12l-4-4h8l-4 4z'/%3E%3C/svg%3E"); background-repeat: no-repeat; background-position: right 0.75rem center; background-size: 1rem; }
</style>
</head>
<body class="bg-gradient-to-br from-[#0f0f1a] to-[#0c1b2a] text-white flex items-center justify-center min-h-screen px-4">
<div class="w-full max-w-lg fade-in">
<h1 class="text-3xl font-bold text-center mb-4 text-blue-300">Grow a Garden</h1>
<h2 class="text-lg text-center text-blue-400 mb-6">Calculate your fruit's price</h2>
<form id="form" class="bg-[#1a1d2c] p-6 rounded-2xl shadow-xl space-y-4">
<div>
<label class="block mb-1 text-sm">Fruit</label>
<select name="fruit" id="fruit" required class="w-full p-3 rounded bg-[#2c3144] text-white focus:outline-none focus:ring-2 focus:ring-blue-400">${fruitOptions}</select>
</div>
<div>
<label class="block mb-1 text-sm">Weight (kg)</label>
<input name="weight" type="number" step="0.01" placeholder="0.00" required class="w-full p-3 rounded bg-[#2c3144] text-white focus:outline-none focus:ring-2 focus:ring-blue-400">
</div>
<div>
<label class="block mb-1 text-sm">Rarity</label>
<select name="rarity" id="rarity" required class="w-full p-3 rounded bg-[#2c3144] text-white focus:outline-none focus:ring-2 focus:ring-blue-400">${rarityOptions}</select>
</div>
<div>
<label class="block mb-1 text-sm">Mutations</label>
<select name="mutations" id="mutations" multiple size="6" class="w-full p-3 rounded bg-[#2c3144] text-white focus:outline-none focus:ring-2 focus:ring-blue-400">${mutationOptions}</select>
</div>
<button type="submit" class="w-full bg-blue-500 hover:bg-blue-600 p-3 rounded font-bold transition-all">Calculate</button>
<div id="result" class="text-center text-blue-300 font-semibold"></div>
</form>
</div>
<script>
document.getElementById("form").onsubmit = async e => {
e.preventDefault()
const form = e.target
const data = new URLSearchParams()
const fruit = form.fruit.value
const rarity = form.rarity.value.trim()
data.append("fruit", fruit)
data.append("weight", form.weight.value)
data.append("rarity", rarity)
let selected = Array.from(form.mutations.selectedOptions).map(o => o.value)
if (selected.includes("Frozen") || (selected.includes("Wet") && selected.includes("Chilled"))) {
selected = selected.filter(m => !["Wet", "Chilled"].includes(m))
if (!selected.includes("Frozen")) selected.push("Frozen")
}
if (selected.includes("Sundried") && selected.includes("Verdant")) {
selected = selected.filter(m => !["Sundried", "Verdant"].includes(m))
selected.push("Paradisal")
}
if (selected.includes("Cooked")) {
selected = selected.filter(m => m !== "Burnt")
}
if (selected.includes("Burnt")) {
selected = selected.filter(m => m !== "Cooked")
}
selected.forEach(m => data.append("mutations", m))
const res = await fetch("/calc", {
method: "POST",
headers: { "Content-Type": "application/x-www-form-urlencoded" },
body: data
})
const json = await res.json()
const output = json.value ? \`<p>Total: <span class='text-blue-400'>\${json.value}</span></p>\` : \`<p class='text-red-400'>Invalid input</p>\`
document.getElementById("result").innerHTML = output
}
</script>
</body>
</html>
`)
})
app.post("/calc", (req, res) => {
const { fruit, weight, rarity } = req.body
let mutations = req.body.mutations || []
if (!Array.isArray(mutations)) mutations = [mutations]
const result = calcValue(fruit, parseFloat(weight), rarity, mutations)
res.json({ value: result })
})
app.listen(port) |