oh-my-dear-ai's picture
update plants info
83cff4c
raw
history blame
8.34 kB
import gradio as gr
import pandas as pd
import pulp
import numpy as np
# Define the quality tiers and names for the plants
PLANTS_TIERS = {
"radiant": "RADIANT",
"flourishing": "FLOURISHING",
"hardy": "HARDY",
"feeble": "FEEBLE",
"radiant_rarecolor": "RADIANT+RARECOLOR",
"flourishing_rarecolor": "FLOURISHING+RARECOLOR",
"hardy_rarecolor": "HARDY+RARECOLOR",
}
PLANTS_LABLES = {
"fanged_geranium": "Fanged Geranium",
"gillyweed": "Gillyweed",
"rose": "Rose",
"puffapod": "Puffapod",
"wild_pansy": "Wild Pansy",
"nifflers_fancy": "Niffler's Fancy",
"fanwort": "Fanwort",
"ladys_mantle": "Lady's Mantle",
"kelp": "Kelp",
"mandrake": "Mandrake",
"chinese_chomping_cabbage": "Chinese Chomping Cabbage",
"dragons_breath_macroalgae": "Dragon's Breath Macroalgae",
"peony": "Peony",
"begonia": "Begonia",
"mayflower": "Mayflower",
"hydrangea": "Hydrangea",
"ludwigia_glandulosa": "Ludwigia Glandulosa",
"daffodil": "Daffodil",
"water_hyacinth": "Water Hyacinth",
"lily_of_the_valley": "Lily of the Valley",
"mosaic_flower": "Mosaic Flower",
"sunflower": "Sunflower",
"mimbulus_mimbletonia": "Mimbulus Mimbletonia",
"water_lily": "Water Lily",
}
INTERFACE_TEXTS = {
"cn": {
"gold_label": "葭碧の金币预算:",
"strategies_label": "请选择凑单策略:",
"clear_btn_label": "❌清除",
"calculate_btn_label": "🛠计算",
"output_label": "计算结果:",
"strategy_options": [
("最小化售出株数(优先出售高价植物)", "MaximizeStock"),
("最大化售出株数(优先出售低价植物)", "MinimizeStock"),
],
},
"en": {
"gold_label": "Gabby's Gold Budget:",
"strategies_label": "Select a strategy:",
"clear_btn_label": "❌Clear",
"calculate_btn_label": "🛠Calculate",
"output_label": "Output:",
"strategy_options": [
(
"Minimize the number of plants sold (prioritize high-priced plants)",
"MaximizeStock",
),
(
"Maximize the number of plants sold (prioritize low-priced plants)",
"MinimizeStock",
),
],
},
}
# Import and process plant data
df = pd.read_csv("plants.csv")
# Convert columns to Categorical type and remove rows with NaN in 'gold' column
df["species"] = pd.Categorical(df["species"])
df["tier"] = pd.Categorical(df["tier"])
df = df.dropna(subset=["gold"])
df = df.astype(
{
"gold": int,
"gems": int,
}
)
def calculator(*args):
"""
Calculate the optimal solution of plant sales based on the given budget
and inventory constraints.
Args:
*args (tuple): A tuple where the first element is Gabby's gold budget, the selected strategy for selling plants,
and the subsequent elements represent the stock levels of
each plant type.
Returns:
str: A description of the optimal solution, including which plants to sell,
the total gold earned, and the remaining inventory.
"""
budget = args[0] # 葭碧预算
strategy = args[1] # 出售策略
stocks = np.array([x if x else 0 for x in args[2:]]) # 植物库存
# 植物名称列表
plants_names = [
f"{PLANTS_TIERS[row['tier']]} {PLANTS_LABLES[row['species']]}"
for index, row in df.iterrows()
]
gold = np.array(df["gold"]) # 植物单价
if sum([gold[i] * stocks[i] for i in range(len(stocks))]) < budget:
return "No solution found.\nThe total value of the plants is lower than the budget."
# 创建问题实例,根据出售策略设定优化目标
if strategy == "MaximizeStock":
prob = pulp.LpProblem("Maximize_Stock", pulp.LpMinimize)
else:
prob = pulp.LpProblem("Maximize_Stock", pulp.LpMaximize)
# 决策变量,售出每种植物的件数,必须是整数
x = pulp.LpVariable.dicts("x", range(len(stocks)), lowBound=0, cat="Integer")
# 遍历,设置决策变量的上界为库存量
for i in range(len(stocks)):
x[i].upBound = stocks[i]
# 目标函数:最大化 / 最小化 售出株数
prob += pulp.lpSum([x[i] for i in range(len(stocks))])
# 约束条件:每类产品售出数量乘以单价之和等于总价格
prob += pulp.lpSum([gold[i] * x[i] for i in range(len(stocks))]) == budget
# 求解问题
# CBC(Coin-or Branch and Cut)求解器使用分支定界算法来寻找整数规划问题的最优解
solver = pulp.getSolver("PULP_CBC_CMD")
prob.solve(solver=solver)
if pulp.LpStatus[prob.status] == "Optimal":
sold = 0
solution = []
for i, v in x.items():
if v.varValue:
if v.varValue > 0:
solution.append(f"{plants_names[i]}: {int(v.varValue)}\n")
sold += int(v.varValue) * gold[i]
return f"Optimal solution found:\n\n{''.join(solution)}\nTotal Price: {sold}\nCount: {int(pulp.value(prob.objective))}"
else:
return "No solution found.\n"
# 高亮每种植物的最高品质
css = """
.firstbox {background-color: #fafad2}
"""
with gr.Blocks(css=css) as demo:
gr.Markdown(
"""<center><font size=8>HP-Magic-Awakened Herbologist Toolkit👾</center>"""
)
# Language selection dropdown
# language = gr.Radio(
# choices=["cn", "en"],
# value="cn",
# label="Language",
# info="Select the interface language:",
# interactive=True,
# )
# Create a Gradio interface with a column layout
with gr.Column():
# Add a row for the budget input
budget = gr.Number(
label="Gold",
info="Gabby's Gold Budget:", # "葭碧の金币预算:",
value=0,
minimum=0,
maximum=20000,
step=100,
)
# Add a radio selection for the strategy
selected_strategy = gr.Radio(
[
(
"Minimize the number of plants sold (prioritize high-priced plants)",
"MaximizeStock",
),
(
"Maximize the number of plants sold (prioritize low-priced plants)",
"MinimizeStock",
),
],
value="MaximizeStock",
label="Strategies",
info="Select a strategy:",
)
# Add a row for the plant inventory inputs
with gr.Row():
inventory = {}
species_set = set()
species_count = 0
for _, row in df.iterrows():
if is_gold := row["gold"] != 0:
species_set.add(row["species"])
inventory[f"{row['species']}_{row['tier']}"] = gr.Number(
# label=f"{PLANTS_I18N[row['species']]}_{PLANTS_TIERS[row['tier']]}",
label=PLANTS_LABLES[row["species"]],
info=PLANTS_TIERS[row["tier"]],
value=0,
precision=0,
minimum=0,
maximum=500,
step=10,
visible=is_gold,
elem_classes=("firstbox" if len(species_set) > species_count else None),
)
species_count = len(species_set)
# Add a row for the Clear and Calculate buttons
with gr.Row():
clear_btn = gr.ClearButton(list(inventory.values()), size="sm", value="❌Clear")
# Add a button to trigger the calculation
submit_btn = gr.Button(value="🛠Calculate")
# Add a row for the result textbox
with gr.Row():
result = gr.Textbox(label="Output")
# Set up the button click event to call the calculator function
submit_btn.click(
calculator,
inputs=[budget] + [selected_strategy] + list(inventory.values()),
outputs=[result],
api_name=False,
)
# Launch the Gradio application
demo.queue(api_open=False)
demo.launch(max_threads=5, share=False)