Spaces:
Runtime error
Runtime error
Upload 5 files
Browse files- app.py +35 -0
- app_gradio.py +35 -0
- app_streamlit.py +27 -0
- requirements.txt +3 -0
- utils.py +107 -0
app.py
ADDED
@@ -0,0 +1,35 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
import gradio as gr
|
2 |
+
from utils import get_calculated_df, get_info, text2oddslist
|
3 |
+
|
4 |
+
|
5 |
+
def calculate(amount, text):
|
6 |
+
df = get_calculated_df(amount, text2oddslist(text))
|
7 |
+
info = get_info(df)
|
8 |
+
|
9 |
+
# dfの整形
|
10 |
+
display_cols = ["odds", "buy", "refound"]
|
11 |
+
if df["name"].map(lambda name: name != "").any():
|
12 |
+
display_cols = ["name"] + display_cols
|
13 |
+
|
14 |
+
# markdownの整形
|
15 |
+
md_string = (
|
16 |
+
f"**購入額:** ¥ **{info['sum']:,}**<br>"
|
17 |
+
f"**点数:** **{info['num_kind']}** 点<br>"
|
18 |
+
f"**払戻:** ¥ **{info['refound_mean']:,}** (**{info['profit_mean']:+,}** (**{info['rate_min']:+.0%}**))<br>"
|
19 |
+
"---"
|
20 |
+
)
|
21 |
+
|
22 |
+
return md_string, df[["index"] + display_cols]
|
23 |
+
|
24 |
+
|
25 |
+
amount_input = gr.Number(value=3000, label="amount")
|
26 |
+
text_input = gr.Textbox(label="text")
|
27 |
+
markdown_output = gr.Markdown()
|
28 |
+
df_output = gr.Dataframe(type="pandas")
|
29 |
+
iface = gr.Interface(
|
30 |
+
fn=calculate,
|
31 |
+
inputs=[amount_input, text_input],
|
32 |
+
outputs=[markdown_output, df_output],
|
33 |
+
)
|
34 |
+
|
35 |
+
iface.launch()
|
app_gradio.py
ADDED
@@ -0,0 +1,35 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
import gradio as gr
|
2 |
+
from utils import get_calculated_df, get_info, text2oddslist
|
3 |
+
|
4 |
+
|
5 |
+
def calculate(amount, text):
|
6 |
+
df = get_calculated_df(amount, text2oddslist(text))
|
7 |
+
info = get_info(df)
|
8 |
+
|
9 |
+
# dfの整形
|
10 |
+
display_cols = ["odds", "buy", "refound"]
|
11 |
+
if df["name"].map(lambda name: name != "").any():
|
12 |
+
display_cols = ["name"] + display_cols
|
13 |
+
|
14 |
+
# markdownの整形
|
15 |
+
md_string = (
|
16 |
+
f"**購入額:** ¥ **{info['sum']:,}**<br>"
|
17 |
+
f"**点数:** **{info['num_kind']}** 点<br>"
|
18 |
+
f"**払戻:** ¥ **{info['refound_mean']:,}** (**{info['profit_mean']:+,}** (**{info['rate_min']:+.0%}**))<br>"
|
19 |
+
"---"
|
20 |
+
)
|
21 |
+
|
22 |
+
return md_string, df[["index"] + display_cols]
|
23 |
+
|
24 |
+
|
25 |
+
amount_input = gr.Number(value=3000, label="amount")
|
26 |
+
text_input = gr.Textbox(label="text")
|
27 |
+
markdown_output = gr.Markdown()
|
28 |
+
df_output = gr.Dataframe(type="pandas")
|
29 |
+
iface = gr.Interface(
|
30 |
+
fn=calculate,
|
31 |
+
inputs=[amount_input, text_input],
|
32 |
+
outputs=[markdown_output, df_output],
|
33 |
+
)
|
34 |
+
|
35 |
+
iface.launch()
|
app_streamlit.py
ADDED
@@ -0,0 +1,27 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
import streamlit as st
|
2 |
+
from utils import get_calculated_df, get_info, text2oddslist
|
3 |
+
|
4 |
+
amount: int = int(st.number_input("amount", min_value=100, value=3000, step=100))
|
5 |
+
text: str = st.text_area("text", "")
|
6 |
+
# ボタンを作る
|
7 |
+
st.button("calculate")
|
8 |
+
if text:
|
9 |
+
df = get_calculated_df(amount, text2oddslist(text))
|
10 |
+
# dataframeを綺麗に出力する
|
11 |
+
info = get_info(df)
|
12 |
+
col1, col2 = st.columns(2)
|
13 |
+
with col1:
|
14 |
+
st.markdown(f"#### 購入額: ¥ **{info['sum']:,}**")
|
15 |
+
st.markdown(f"#### 点 数: **{info['num_kind']}** 点")
|
16 |
+
with col2:
|
17 |
+
st.metric(
|
18 |
+
label="払戻",
|
19 |
+
value=f"¥ {info['refound_mean']:,}",
|
20 |
+
delta=f"{info['profit_mean']:+,}({info['rate_min']:.0%})",
|
21 |
+
)
|
22 |
+
st.markdown("---")
|
23 |
+
# dfの表示
|
24 |
+
display_cols = ["odds", "buy", "refound"]
|
25 |
+
if df["name"].map(lambda name: name != "").any():
|
26 |
+
display_cols = ["name"] + display_cols
|
27 |
+
st.dataframe(df[display_cols])
|
requirements.txt
ADDED
@@ -0,0 +1,3 @@
|
|
|
|
|
|
|
|
|
1 |
+
pandas==2.1.0
|
2 |
+
streamlit==1.26.0
|
3 |
+
gradio==3.44.3
|
utils.py
ADDED
@@ -0,0 +1,107 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
import math
|
2 |
+
from typing import TypedDict
|
3 |
+
|
4 |
+
import pandas as pd
|
5 |
+
|
6 |
+
|
7 |
+
# Typing -----------------------------------------------------------------------
|
8 |
+
class OddsInfo(TypedDict):
|
9 |
+
index: str
|
10 |
+
name: str
|
11 |
+
odds: float
|
12 |
+
|
13 |
+
|
14 |
+
OdddsList = list[OddsInfo]
|
15 |
+
|
16 |
+
|
17 |
+
class Info(TypedDict):
|
18 |
+
sum: int
|
19 |
+
num_kind: int
|
20 |
+
refound_mean: int
|
21 |
+
profit_mean: int
|
22 |
+
rate_min: float
|
23 |
+
rate_max: float
|
24 |
+
rate_mean: float
|
25 |
+
|
26 |
+
|
27 |
+
# text -> odds_list ------------------------------------------------------------
|
28 |
+
def _text2oddslist_pc(text: str) -> OdddsList:
|
29 |
+
odds_list: OdddsList = []
|
30 |
+
tmp_list: list[str] = []
|
31 |
+
lines: list[str] = text.split("\n")
|
32 |
+
for text in lines:
|
33 |
+
if "." in text:
|
34 |
+
odds_list.append(
|
35 |
+
{
|
36 |
+
"index": "-".join(tmp_list),
|
37 |
+
"name": "",
|
38 |
+
"odds": float(text),
|
39 |
+
}
|
40 |
+
)
|
41 |
+
tmp_list = []
|
42 |
+
else:
|
43 |
+
if text.strip():
|
44 |
+
tmp_list.append(text.strip())
|
45 |
+
return odds_list
|
46 |
+
|
47 |
+
|
48 |
+
def _text2oddslist_mobile(text: str) -> OdddsList:
|
49 |
+
odds_list: OdddsList = []
|
50 |
+
lines: list[str] = text.split("\n")
|
51 |
+
if "選択" in lines:
|
52 |
+
lines = lines[lines.index("選択") + 1 :]
|
53 |
+
if "すべてを選択" in lines:
|
54 |
+
lines = lines[: lines.index("すべてを選択")]
|
55 |
+
for i in range(len(lines) // 3):
|
56 |
+
# oddsが1つ目にある
|
57 |
+
if "." in lines[3 * i + 1]:
|
58 |
+
idx_odds = 1
|
59 |
+
idx_name = 2
|
60 |
+
else:
|
61 |
+
idx_odds = 2
|
62 |
+
idx_name = 1
|
63 |
+
|
64 |
+
odds_list.append(
|
65 |
+
{
|
66 |
+
"index": "-".join(lines[3 * i].split()),
|
67 |
+
"name": "-".join(lines[3 * i + idx_name].split()),
|
68 |
+
"odds": float(lines[3 * i + idx_odds]),
|
69 |
+
}
|
70 |
+
)
|
71 |
+
return odds_list
|
72 |
+
|
73 |
+
|
74 |
+
def text2oddslist(text: str) -> OdddsList:
|
75 |
+
# pcの時
|
76 |
+
if set("".join(text.split())) <= set("0123456789.-"):
|
77 |
+
odds_list = _text2oddslist_pc(text)
|
78 |
+
# moduleの時
|
79 |
+
else:
|
80 |
+
odds_list = _text2oddslist_mobile(text)
|
81 |
+
return odds_list
|
82 |
+
|
83 |
+
|
84 |
+
# odds_list -> df ---------------------------------------------------------------
|
85 |
+
def get_calculated_df(amount: int, odds_list: OdddsList) -> pd.DataFrame:
|
86 |
+
df = pd.DataFrame(odds_list)
|
87 |
+
df["weight"] = (1 / df["odds"]) / (1 / df["odds"]).sum()
|
88 |
+
df["buy"] = (df["weight"] * amount / 100).map(
|
89 |
+
lambda x: max(math.floor(x) * 100, 100)
|
90 |
+
)
|
91 |
+
df["refound"] = (df["buy"] * df["odds"]).astype(int)
|
92 |
+
df["profit"] = df["refound"] - amount
|
93 |
+
df = df
|
94 |
+
return df
|
95 |
+
|
96 |
+
|
97 |
+
def get_info(df: pd.DataFrame) -> Info:
|
98 |
+
info: Info = {
|
99 |
+
"sum": df["buy"].sum(),
|
100 |
+
"num_kind": df.shape[0],
|
101 |
+
"refound_mean": int(df["refound"].mean()),
|
102 |
+
"profit_mean": int(df["profit"].mean()),
|
103 |
+
"rate_min": df["refound"].min() / df["buy"].sum(),
|
104 |
+
"rate_max": df["refound"].max() / df["buy"].sum(),
|
105 |
+
"rate_mean": df["refound"].mean() / df["buy"].sum(),
|
106 |
+
}
|
107 |
+
return info
|