Spaces:
Sleeping
Sleeping
Commit ·
4d85b4b
1
Parent(s): 3c01117
feat: add talent price bonus feature and update UI labels
Browse files- app.py +3 -2
- solver.py +14 -16
- ui/display.py +48 -41
- ui/i18n.py +0 -11
- ui/labels.json +12 -0
app.py
CHANGED
|
@@ -10,12 +10,11 @@ from ui.display import (
|
|
| 10 |
get_language,
|
| 11 |
get_plants_selector,
|
| 12 |
get_strategy,
|
|
|
|
| 13 |
prerender_inventory_inputs,
|
| 14 |
update_dishes_selector_on_language,
|
| 15 |
-
update_dishes_selector_on_currency,
|
| 16 |
update_inventory_inputs,
|
| 17 |
update_inventory_ui_by_language,
|
| 18 |
-
update_plants_selector_on_currency,
|
| 19 |
update_plants_selector_on_language,
|
| 20 |
update_selectors_on_currency,
|
| 21 |
)
|
|
@@ -82,6 +81,7 @@ with gr.Blocks(js=js, css=css, theme=gr.themes.Monochrome()) as demo:
|
|
| 82 |
strategy: gr.Radio = get_strategy()
|
| 83 |
blooms_rate: gr.Dropdown = get_blooms_acquisition_rate()
|
| 84 |
confiserie_rate: gr.Dropdown = get_confiserie_acquisition_rate()
|
|
|
|
| 85 |
solve_button = gr.Button("Solve")
|
| 86 |
results_output = gr.Textbox(label="Results", show_copy_button=True)
|
| 87 |
|
|
@@ -127,6 +127,7 @@ with gr.Blocks(js=js, css=css, theme=gr.themes.Monochrome()) as demo:
|
|
| 127 |
budget,
|
| 128 |
blooms_rate,
|
| 129 |
confiserie_rate,
|
|
|
|
| 130 |
strategy,
|
| 131 |
]
|
| 132 |
+ inventory_inputs,
|
|
|
|
| 10 |
get_language,
|
| 11 |
get_plants_selector,
|
| 12 |
get_strategy,
|
| 13 |
+
get_talent_price_bonus,
|
| 14 |
prerender_inventory_inputs,
|
| 15 |
update_dishes_selector_on_language,
|
|
|
|
| 16 |
update_inventory_inputs,
|
| 17 |
update_inventory_ui_by_language,
|
|
|
|
| 18 |
update_plants_selector_on_language,
|
| 19 |
update_selectors_on_currency,
|
| 20 |
)
|
|
|
|
| 81 |
strategy: gr.Radio = get_strategy()
|
| 82 |
blooms_rate: gr.Dropdown = get_blooms_acquisition_rate()
|
| 83 |
confiserie_rate: gr.Dropdown = get_confiserie_acquisition_rate()
|
| 84 |
+
talent_price_bonus: gr.Number = get_talent_price_bonus()
|
| 85 |
solve_button = gr.Button("Solve")
|
| 86 |
results_output = gr.Textbox(label="Results", show_copy_button=True)
|
| 87 |
|
|
|
|
| 127 |
budget,
|
| 128 |
blooms_rate,
|
| 129 |
confiserie_rate,
|
| 130 |
+
talent_price_bonus,
|
| 131 |
strategy,
|
| 132 |
]
|
| 133 |
+ inventory_inputs,
|
solver.py
CHANGED
|
@@ -3,18 +3,13 @@ from datetime import datetime
|
|
| 3 |
import numpy as np
|
| 4 |
from numpy.typing import NDArray
|
| 5 |
from pyscipopt import Model, quicksum
|
| 6 |
-
from ui.display import format_results
|
| 7 |
-
from ui.i18n import setup_i18n
|
| 8 |
|
| 9 |
-
|
| 10 |
|
| 11 |
from data_loader import (
|
| 12 |
DISHES_DF,
|
| 13 |
-
DISHES_LABELS,
|
| 14 |
LABELS,
|
| 15 |
PLANTS_DF,
|
| 16 |
-
PLANTS_LABELS,
|
| 17 |
-
TIERS_LABELS,
|
| 18 |
)
|
| 19 |
|
| 20 |
|
|
@@ -94,13 +89,18 @@ def get_results(
|
|
| 94 |
budget,
|
| 95 |
plants_prices_extra_rate,
|
| 96 |
dishes_prices_extra_rate,
|
|
|
|
| 97 |
strategy,
|
| 98 |
*inventory,
|
| 99 |
):
|
| 100 |
prices: NDArray[np.int16] = np.concat(
|
| 101 |
[
|
| 102 |
PLANTS_DF[currency] * (1 + plants_prices_extra_rate),
|
| 103 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
| 104 |
],
|
| 105 |
dtype=np.int16,
|
| 106 |
)
|
|
@@ -122,15 +122,13 @@ def get_results(
|
|
| 122 |
for i in range(len(PLANTS_DF))
|
| 123 |
if plants_solution[i] > 0
|
| 124 |
}
|
| 125 |
-
results["solution"].update(
|
| 126 |
-
{
|
| 127 |
-
|
| 128 |
-
|
| 129 |
-
|
| 130 |
-
|
| 131 |
-
|
| 132 |
-
}
|
| 133 |
-
)
|
| 134 |
results["total_price"] = outputs["total_price"]
|
| 135 |
results["total_count"] = outputs["total_count"]
|
| 136 |
results["remaining"] = outputs["remaining"]
|
|
|
|
| 3 |
import numpy as np
|
| 4 |
from numpy.typing import NDArray
|
| 5 |
from pyscipopt import Model, quicksum
|
|
|
|
|
|
|
| 6 |
|
| 7 |
+
from ui.display import format_results
|
| 8 |
|
| 9 |
from data_loader import (
|
| 10 |
DISHES_DF,
|
|
|
|
| 11 |
LABELS,
|
| 12 |
PLANTS_DF,
|
|
|
|
|
|
|
| 13 |
)
|
| 14 |
|
| 15 |
|
|
|
|
| 89 |
budget,
|
| 90 |
plants_prices_extra_rate,
|
| 91 |
dishes_prices_extra_rate,
|
| 92 |
+
talent_price_bonus,
|
| 93 |
strategy,
|
| 94 |
*inventory,
|
| 95 |
):
|
| 96 |
prices: NDArray[np.int16] = np.concat(
|
| 97 |
[
|
| 98 |
PLANTS_DF[currency] * (1 + plants_prices_extra_rate),
|
| 99 |
+
np.floor(
|
| 100 |
+
DISHES_DF[currency]
|
| 101 |
+
* (1 + dishes_prices_extra_rate)
|
| 102 |
+
* (1 + talent_price_bonus / 100)
|
| 103 |
+
).astype(np.int16),
|
| 104 |
],
|
| 105 |
dtype=np.int16,
|
| 106 |
)
|
|
|
|
| 122 |
for i in range(len(PLANTS_DF))
|
| 123 |
if plants_solution[i] > 0
|
| 124 |
}
|
| 125 |
+
results["solution"].update({
|
| 126 |
+
f"{LABELS[language]['dishes'][DISHES_DF.iloc[i]['name']]} ({LABELS[language]['tiers'][DISHES_DF.iloc[i]['tier']]}, {int(prices[len(PLANTS_DF) + i])} {currency})": dishes_solution[
|
| 127 |
+
i
|
| 128 |
+
]
|
| 129 |
+
for i in range(len(DISHES_DF))
|
| 130 |
+
if dishes_solution[i] > 0
|
| 131 |
+
})
|
|
|
|
|
|
|
| 132 |
results["total_price"] = outputs["total_price"]
|
| 133 |
results["total_count"] = outputs["total_count"]
|
| 134 |
results["remaining"] = outputs["remaining"]
|
ui/display.py
CHANGED
|
@@ -14,9 +14,6 @@ from data_loader import (
|
|
| 14 |
PLANTS_LABELS,
|
| 15 |
TIERS_LABELS,
|
| 16 |
)
|
| 17 |
-
from ui.i18n import setup_i18n
|
| 18 |
-
|
| 19 |
-
_ = setup_i18n()
|
| 20 |
|
| 21 |
|
| 22 |
def get_language():
|
|
@@ -26,17 +23,14 @@ def get_language():
|
|
| 26 |
return gr.Dropdown(
|
| 27 |
choices=[("English", "en"), ("简体中文", "cn"), ("日本語", "ja")],
|
| 28 |
value="en",
|
| 29 |
-
label=
|
| 30 |
-
info=
|
| 31 |
-
"Select the language for the interface. Currently, only part of texts are translated."
|
| 32 |
-
),
|
| 33 |
elem_id="language-select",
|
| 34 |
interactive=True,
|
| 35 |
)
|
| 36 |
|
| 37 |
|
| 38 |
def update_inventory_ui_by_language(language):
|
| 39 |
-
setup_i18n(language)
|
| 40 |
inventory_inputs = [
|
| 41 |
gr.update(
|
| 42 |
label=LABELS[language]["plants"][row["name"]],
|
|
@@ -58,7 +52,7 @@ def get_currency():
|
|
| 58 |
Returns a Gradio Radio component for selecting currency.
|
| 59 |
"""
|
| 60 |
return gr.Radio(
|
| 61 |
-
choices=[(
|
| 62 |
value="gold",
|
| 63 |
type="value",
|
| 64 |
label="Currency",
|
|
@@ -75,8 +69,8 @@ def get_budget():
|
|
| 75 |
"""
|
| 76 |
return gr.Number(
|
| 77 |
value=0,
|
| 78 |
-
label=
|
| 79 |
-
info=
|
| 80 |
elem_id="budget-number",
|
| 81 |
interactive=True,
|
| 82 |
precision=0,
|
|
@@ -92,12 +86,12 @@ def get_blooms_acquisition_rate():
|
|
| 92 |
"""
|
| 93 |
return gr.Dropdown(
|
| 94 |
choices=[
|
| 95 |
-
|
| 96 |
-
|
| 97 |
-
|
| 98 |
-
|
| 99 |
],
|
| 100 |
-
value=
|
| 101 |
type="index",
|
| 102 |
label="Blooms Extra Acquisition Rate🌿",
|
| 103 |
info="Select your high-value acquisition rate for Bewildering Blooms.",
|
|
@@ -109,12 +103,12 @@ def get_confiserie_acquisition_rate():
|
|
| 109 |
"""Returns a Gradio Dropdown component for Confiserie Acquisition Rate."""
|
| 110 |
return gr.Dropdown(
|
| 111 |
choices=[
|
| 112 |
-
|
| 113 |
-
|
| 114 |
-
|
| 115 |
-
|
| 116 |
],
|
| 117 |
-
value=
|
| 118 |
type="index",
|
| 119 |
label="Confiserie Extra Acquisition Rate🍜",
|
| 120 |
info="Select your high-value acquisition rate for The Confiserie.",
|
|
@@ -154,8 +148,8 @@ def get_plants_selector(language, currency):
|
|
| 154 |
choices=filtered_plants_labels,
|
| 155 |
value=default_value,
|
| 156 |
type="value",
|
| 157 |
-
label=
|
| 158 |
-
info=
|
| 159 |
interactive=True,
|
| 160 |
)
|
| 161 |
return checkbox_group
|
|
@@ -214,8 +208,8 @@ def get_dishes_selector(language, currency):
|
|
| 214 |
choices=filtered_dishes_labels,
|
| 215 |
value=default_value,
|
| 216 |
type="value",
|
| 217 |
-
label=
|
| 218 |
-
info=
|
| 219 |
interactive=True,
|
| 220 |
)
|
| 221 |
|
|
@@ -266,14 +260,10 @@ def prerender_inventory_inputs() -> list[gr.Number]:
|
|
| 266 |
"""
|
| 267 |
Returns a Gradio Number component for inventory input based on the dataframe row data."""
|
| 268 |
return gr.Number(
|
| 269 |
-
label=
|
| 270 |
-
|
| 271 |
-
|
| 272 |
-
|
| 273 |
-
),
|
| 274 |
-
info=_(
|
| 275 |
-
f"{TIERS_LABELS[row['tier']]} ${row['gold'] if row['gold'] > 0 else row['gems']}"
|
| 276 |
-
),
|
| 277 |
value=0,
|
| 278 |
precision=0,
|
| 279 |
minimum=0,
|
|
@@ -316,19 +306,36 @@ def update_inventory_inputs(
|
|
| 316 |
return _out
|
| 317 |
|
| 318 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 319 |
def get_strategy():
|
| 320 |
"""
|
| 321 |
Returns a Gradio Radio component for selecting the selling strategy.
|
| 322 |
"""
|
| 323 |
return gr.Radio(
|
| 324 |
choices=[
|
| 325 |
-
(
|
| 326 |
-
(
|
| 327 |
],
|
| 328 |
value="MinimizeStock",
|
| 329 |
type="value",
|
| 330 |
-
label=
|
| 331 |
-
info=
|
| 332 |
interactive=True,
|
| 333 |
elem_id="strategy-radio",
|
| 334 |
)
|
|
@@ -345,12 +352,12 @@ def format_results(results):
|
|
| 345 |
str: A formatted string representation of the results.
|
| 346 |
"""
|
| 347 |
output = []
|
| 348 |
-
output.append(
|
| 349 |
for item, count in results["solution"].items():
|
| 350 |
output.append(f"{item}: {count}")
|
| 351 |
|
| 352 |
-
output.append(f"\n{
|
| 353 |
-
output.append(f"{
|
| 354 |
-
output.append(f"{
|
| 355 |
|
| 356 |
return "\n".join(output)
|
|
|
|
| 14 |
PLANTS_LABELS,
|
| 15 |
TIERS_LABELS,
|
| 16 |
)
|
|
|
|
|
|
|
|
|
|
| 17 |
|
| 18 |
|
| 19 |
def get_language():
|
|
|
|
| 23 |
return gr.Dropdown(
|
| 24 |
choices=[("English", "en"), ("简体中文", "cn"), ("日本語", "ja")],
|
| 25 |
value="en",
|
| 26 |
+
label="Language",
|
| 27 |
+
info="Select the language for the interface. Currently, only part of texts are translated.",
|
|
|
|
|
|
|
| 28 |
elem_id="language-select",
|
| 29 |
interactive=True,
|
| 30 |
)
|
| 31 |
|
| 32 |
|
| 33 |
def update_inventory_ui_by_language(language):
|
|
|
|
| 34 |
inventory_inputs = [
|
| 35 |
gr.update(
|
| 36 |
label=LABELS[language]["plants"][row["name"]],
|
|
|
|
| 52 |
Returns a Gradio Radio component for selecting currency.
|
| 53 |
"""
|
| 54 |
return gr.Radio(
|
| 55 |
+
choices=[("Gold", "gold"), ("Gems", "gems")],
|
| 56 |
value="gold",
|
| 57 |
type="value",
|
| 58 |
label="Currency",
|
|
|
|
| 69 |
"""
|
| 70 |
return gr.Number(
|
| 71 |
value=0,
|
| 72 |
+
label="Budget💸",
|
| 73 |
+
info="Enter your budget amount.",
|
| 74 |
elem_id="budget-number",
|
| 75 |
interactive=True,
|
| 76 |
precision=0,
|
|
|
|
| 86 |
"""
|
| 87 |
return gr.Dropdown(
|
| 88 |
choices=[
|
| 89 |
+
"0(Gabby's Acquisition)",
|
| 90 |
+
"+100%(HVA for Shop Level 1 & 2)",
|
| 91 |
+
"+200%(HVA for Shop Level 3 & 4)",
|
| 92 |
+
"+300%(HVA for Shop Level 5 & 6)",
|
| 93 |
],
|
| 94 |
+
value="0(Gabby's Acquisition)",
|
| 95 |
type="index",
|
| 96 |
label="Blooms Extra Acquisition Rate🌿",
|
| 97 |
info="Select your high-value acquisition rate for Bewildering Blooms.",
|
|
|
|
| 103 |
"""Returns a Gradio Dropdown component for Confiserie Acquisition Rate."""
|
| 104 |
return gr.Dropdown(
|
| 105 |
choices=[
|
| 106 |
+
"0(Andre's Acquisition)",
|
| 107 |
+
"+100%(HVA for Shop Level 1 & 2)",
|
| 108 |
+
"+200%(HVA for Shop Level 3 & 4)",
|
| 109 |
+
"+300%(HVA for Shop Level 5 & 6)",
|
| 110 |
],
|
| 111 |
+
value="0(Andre's Acquisition)",
|
| 112 |
type="index",
|
| 113 |
label="Confiserie Extra Acquisition Rate🍜",
|
| 114 |
info="Select your high-value acquisition rate for The Confiserie.",
|
|
|
|
| 148 |
choices=filtered_plants_labels,
|
| 149 |
value=default_value,
|
| 150 |
type="value",
|
| 151 |
+
label="Plants",
|
| 152 |
+
info="Select plants",
|
| 153 |
interactive=True,
|
| 154 |
)
|
| 155 |
return checkbox_group
|
|
|
|
| 208 |
choices=filtered_dishes_labels,
|
| 209 |
value=default_value,
|
| 210 |
type="value",
|
| 211 |
+
label="Dishes",
|
| 212 |
+
info="Select dishes.",
|
| 213 |
interactive=True,
|
| 214 |
)
|
| 215 |
|
|
|
|
| 260 |
"""
|
| 261 |
Returns a Gradio Number component for inventory input based on the dataframe row data."""
|
| 262 |
return gr.Number(
|
| 263 |
+
label=PLANTS_LABELS[row["name"]]
|
| 264 |
+
if row["name"] in PLANTS_LABELS
|
| 265 |
+
else DISHES_LABELS[row["name"]],
|
| 266 |
+
info=f"{TIERS_LABELS[row['tier']]} ${row['gold'] if row['gold'] > 0 else row['gems']}",
|
|
|
|
|
|
|
|
|
|
|
|
|
| 267 |
value=0,
|
| 268 |
precision=0,
|
| 269 |
minimum=0,
|
|
|
|
| 306 |
return _out
|
| 307 |
|
| 308 |
|
| 309 |
+
def get_talent_price_bonus():
|
| 310 |
+
"""
|
| 311 |
+
Returns a Gradio Number component for talent price bonus input.
|
| 312 |
+
"""
|
| 313 |
+
return gr.Number(
|
| 314 |
+
value=0,
|
| 315 |
+
label="Talent Price Bonus(%)",
|
| 316 |
+
info="Enter the total percentage increase in dish selling price from your talents.",
|
| 317 |
+
elem_id="talent-price-bonus",
|
| 318 |
+
interactive=True,
|
| 319 |
+
precision=0,
|
| 320 |
+
minimum=0,
|
| 321 |
+
maximum=1000,
|
| 322 |
+
step=1,
|
| 323 |
+
)
|
| 324 |
+
|
| 325 |
+
|
| 326 |
def get_strategy():
|
| 327 |
"""
|
| 328 |
Returns a Gradio Radio component for selecting the selling strategy.
|
| 329 |
"""
|
| 330 |
return gr.Radio(
|
| 331 |
choices=[
|
| 332 |
+
("Prioritize high-priced items", "MaximizeStock"),
|
| 333 |
+
("Prioritize low-priced items", "MinimizeStock"),
|
| 334 |
],
|
| 335 |
value="MinimizeStock",
|
| 336 |
type="value",
|
| 337 |
+
label="Selling Strategy📈📉",
|
| 338 |
+
info="Select the strategy for selling items.",
|
| 339 |
interactive=True,
|
| 340 |
elem_id="strategy-radio",
|
| 341 |
)
|
|
|
|
| 352 |
str: A formatted string representation of the results.
|
| 353 |
"""
|
| 354 |
output = []
|
| 355 |
+
output.append("Solution:")
|
| 356 |
for item, count in results["solution"].items():
|
| 357 |
output.append(f"{item}: {count}")
|
| 358 |
|
| 359 |
+
output.append(f"\n{'Total Value:'} {results['total_price']}")
|
| 360 |
+
output.append(f"{'Total Count:'} {results['total_count']}")
|
| 361 |
+
output.append(f"{'Remaining Budget'}: {results['remaining']}")
|
| 362 |
|
| 363 |
return "\n".join(output)
|
ui/i18n.py
DELETED
|
@@ -1,11 +0,0 @@
|
|
| 1 |
-
import gettext
|
| 2 |
-
import os
|
| 3 |
-
|
| 4 |
-
|
| 5 |
-
def setup_i18n(language="en"):
|
| 6 |
-
locales_dir = os.path.join(os.path.dirname(__file__), "locales")
|
| 7 |
-
translation = gettext.translation(
|
| 8 |
-
"messages", localedir=locales_dir, languages=[language], fallback=True
|
| 9 |
-
)
|
| 10 |
-
translation.install()
|
| 11 |
-
return translation.gettext
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
ui/labels.json
CHANGED
|
@@ -74,6 +74,10 @@
|
|
| 74 |
"feast_of_loyalty_and_dedication": "Feast of Loyalty and Dedication",
|
| 75 |
"feast_of_widsom_and_wit": "Feast of Wisdom and Wit",
|
| 76 |
"the_founders_feast": "The Founders Feast"
|
|
|
|
|
|
|
|
|
|
|
|
|
| 77 |
}
|
| 78 |
},
|
| 79 |
"cn": {
|
|
@@ -151,6 +155,10 @@
|
|
| 151 |
"feast_of_loyalty_and_dedication": "忠诚与无私之宴",
|
| 152 |
"feast_of_widsom_and_wit": "智慧与风雅之宴",
|
| 153 |
"the_founders_feast": "霍格沃茨盛宴"
|
|
|
|
|
|
|
|
|
|
|
|
|
| 154 |
}
|
| 155 |
},
|
| 156 |
"ja": {
|
|
@@ -228,6 +236,10 @@
|
|
| 228 |
"feast_of_loyalty_and_dedication": "知恵と風雅の宴",
|
| 229 |
"feast_of_widsom_and_wit": "忠誠と無私の宴",
|
| 230 |
"the_founders_feast": "ホグワーツの饗宴"
|
|
|
|
|
|
|
|
|
|
|
|
|
| 231 |
}
|
| 232 |
}
|
| 233 |
}
|
|
|
|
| 74 |
"feast_of_loyalty_and_dedication": "Feast of Loyalty and Dedication",
|
| 75 |
"feast_of_widsom_and_wit": "Feast of Wisdom and Wit",
|
| 76 |
"the_founders_feast": "The Founders Feast"
|
| 77 |
+
},
|
| 78 |
+
"ui": {
|
| 79 |
+
"talent_price_bonus": "Talent Price Bonus(%)",
|
| 80 |
+
"talent_price_bonus_info": "Enter the total percentage increase in dish selling price from your talents."
|
| 81 |
}
|
| 82 |
},
|
| 83 |
"cn": {
|
|
|
|
| 155 |
"feast_of_loyalty_and_dedication": "忠诚与无私之宴",
|
| 156 |
"feast_of_widsom_and_wit": "智慧与风雅之宴",
|
| 157 |
"the_founders_feast": "霍格沃茨盛宴"
|
| 158 |
+
},
|
| 159 |
+
"ui": {
|
| 160 |
+
"talent_price_bonus": "天赋价格加成(%)",
|
| 161 |
+
"talent_price_bonus_info": "输入天赋导致的菜品售价增幅百分比。"
|
| 162 |
}
|
| 163 |
},
|
| 164 |
"ja": {
|
|
|
|
| 236 |
"feast_of_loyalty_and_dedication": "知恵と風雅の宴",
|
| 237 |
"feast_of_widsom_and_wit": "忠誠と無私の宴",
|
| 238 |
"the_founders_feast": "ホグワーツの饗宴"
|
| 239 |
+
},
|
| 240 |
+
"ui": {
|
| 241 |
+
"talent_price_bonus": "才能価格ボーナス(%)",
|
| 242 |
+
"talent_price_bonus_info": "才能による料理販売価格の上昇率を入力してください。"
|
| 243 |
}
|
| 244 |
}
|
| 245 |
}
|