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)