Spaces:
Runtime error
Runtime error
Upload 5 files
Browse files- DMSans-Regular.ttf +0 -0
- app.py +93 -0
- requirements.txt +6 -0
- template.png +0 -0
- utils.py +212 -0
DMSans-Regular.ttf
ADDED
|
Binary file (72 kB). View file
|
|
|
app.py
ADDED
|
@@ -0,0 +1,93 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
import gradio as gr
|
| 2 |
+
from utils import *
|
| 3 |
+
|
| 4 |
+
duration = 35
|
| 5 |
+
start_patch = datetime.date(2023, 10, 11) # year, month, days
|
| 6 |
+
end_patch = start_patch + datetime.timedelta(days = duration)
|
| 7 |
+
print('patch 1.3: {0} - {1}'.format(start_patch, end_patch))
|
| 8 |
+
|
| 9 |
+
#depand on patch
|
| 10 |
+
data_patch = {'n_character_banner':3, 'n_character_quest':{'first_half':1,
|
| 11 |
+
'second_half':0}}
|
| 12 |
+
|
| 13 |
+
limited_event = {'gift_odyssey':{'reward':10, 'date':(start_patch, end_patch)}, #end date is completed event
|
| 14 |
+
#'gift_patrol':{'reward':800, 'date':(start_patch + datetime.timedelta(days = duration // 2), end_patch)},
|
| 15 |
+
'aetherium':{'reward':1200, 'date':(start_patch + datetime.timedelta(days = 2), start_patch + datetime.timedelta(days = 23))},
|
| 16 |
+
'SU_event':{'reward':500, 'date':(start_patch + datetime.timedelta(days = 24), start_patch + datetime.timedelta(days = 36))},
|
| 17 |
+
}
|
| 18 |
+
|
| 19 |
+
permanent_event = {'aetherium':{'reward':1040},
|
| 20 |
+
'S_training':{'reward':330},
|
| 21 |
+
'exploration':{'reward':300},
|
| 22 |
+
}
|
| 23 |
+
|
| 24 |
+
#user input
|
| 25 |
+
mode = 0
|
| 26 |
+
equilibrium = 0
|
| 27 |
+
MoC = False
|
| 28 |
+
ES = False
|
| 29 |
+
BP = False
|
| 30 |
+
|
| 31 |
+
def inference(mode_dropdown, equilibrium_dropdown, condition_checkbox):
|
| 32 |
+
global start_patch, end_patch, mode, equilibrium, MoC, ES, BP
|
| 33 |
+
|
| 34 |
+
mode = ["ทั้งหมด", "ครึ่งแรก", "ครึ่งหลัง"].index(mode_dropdown)
|
| 35 |
+
equilibrium = int(equilibrium_dropdown)
|
| 36 |
+
|
| 37 |
+
if "Memory of Chaos" in condition_checkbox:
|
| 38 |
+
MoC = True
|
| 39 |
+
else: MoC = False
|
| 40 |
+
|
| 41 |
+
if "บัตรเสบียงรถไฟ" in condition_checkbox:
|
| 42 |
+
ES = True
|
| 43 |
+
else: ES = False
|
| 44 |
+
|
| 45 |
+
if "Battle Pass" in condition_checkbox:
|
| 46 |
+
BP = True
|
| 47 |
+
else: BP = False
|
| 48 |
+
|
| 49 |
+
|
| 50 |
+
reward = estimator(start_patch, end_patch, mode, equilibrium, data_patch, limited_event, permanent_event, MoC, ES, BP)
|
| 51 |
+
|
| 52 |
+
reward_img = export_to_image(reward)
|
| 53 |
+
graph = export_to_graph(reward)
|
| 54 |
+
|
| 55 |
+
|
| 56 |
+
return reward_img, graph
|
| 57 |
+
|
| 58 |
+
js = """function () {
|
| 59 |
+
gradioURL = window.location.href
|
| 60 |
+
if (!gradioURL.endsWith('?__theme=dark')) {
|
| 61 |
+
window.location.replace(gradioURL + '?__theme=dark');
|
| 62 |
+
}
|
| 63 |
+
}"""
|
| 64 |
+
|
| 65 |
+
with gr.Blocks() as demo:
|
| 66 |
+
|
| 67 |
+
demo.load(None,None,None,_js=js)
|
| 68 |
+
|
| 69 |
+
gr.Markdown(
|
| 70 |
+
"""
|
| 71 |
+
# Stellar Jade Estimator Patch 1.4
|
| 72 |
+
ฝากติดตามผลงาน : https://www.youtube.com/@hewchayen
|
| 73 |
+
<br />last update : 13/10/2023, 10:48
|
| 74 |
+
"""
|
| 75 |
+
)
|
| 76 |
+
|
| 77 |
+
|
| 78 |
+
with gr.Row():
|
| 79 |
+
|
| 80 |
+
with gr.Column():
|
| 81 |
+
mode_dropdown = gr.Dropdown(["ทั้งหมด", "ครึ่งแรก", "ครึ่งหลัง"], label="ระยะเวลาในการนับ")
|
| 82 |
+
equilibrium_dropdown = gr.Dropdown([0, 1, 2, 3, 4, 5, 6], label="ระดับสมดุล", info="เลือกระดับสมดุลของไอดี")
|
| 83 |
+
condition_checkbox = gr.CheckboxGroup(["Memory of Chaos", "บัตรเสบียงรถไฟ", "Battle Pass"], label="สถานะ (optional)")
|
| 84 |
+
button = gr.Button("Calculate")
|
| 85 |
+
|
| 86 |
+
output = gr.Image(label = "Reward", type="pil")
|
| 87 |
+
|
| 88 |
+
output2 = gr.Image(label = "Resource")
|
| 89 |
+
|
| 90 |
+
button.click(fn=inference, inputs=[mode_dropdown, equilibrium_dropdown, condition_checkbox], outputs = [output, output2],)
|
| 91 |
+
|
| 92 |
+
demo.queue(api_open=False)
|
| 93 |
+
demo.launch()
|
requirements.txt
ADDED
|
@@ -0,0 +1,6 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
|
| 2 |
+
Pillow
|
| 3 |
+
pandas
|
| 4 |
+
opencv-python
|
| 5 |
+
numpy
|
| 6 |
+
matplotlib
|
template.png
ADDED
|
utils.py
ADDED
|
@@ -0,0 +1,212 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
|
| 2 |
+
import io
|
| 3 |
+
import cv2
|
| 4 |
+
import datetime
|
| 5 |
+
import calendar
|
| 6 |
+
import numpy as np
|
| 7 |
+
import pandas as pd
|
| 8 |
+
import gradio as gr
|
| 9 |
+
import matplotlib.pyplot as plt
|
| 10 |
+
from PIL import ImageFont, ImageDraw, Image
|
| 11 |
+
|
| 12 |
+
from datetime import date, timedelta
|
| 13 |
+
from collections import Counter
|
| 14 |
+
from typing import NamedTuple
|
| 15 |
+
|
| 16 |
+
class Reward():
|
| 17 |
+
def __init__(self):
|
| 18 |
+
self.stellar_jade = {}
|
| 19 |
+
self.special_pass = {}
|
| 20 |
+
self.oneiric_shard = 0
|
| 21 |
+
|
| 22 |
+
def weekday_count(start_date, end_date):
|
| 23 |
+
week = {}
|
| 24 |
+
for i in range((end_date - start_date).days):
|
| 25 |
+
day = calendar.day_name[(start_date + datetime.timedelta(days=i+1)).weekday()]
|
| 26 |
+
week[day] = week[day] + 1 if day in week else 1
|
| 27 |
+
return week
|
| 28 |
+
|
| 29 |
+
def daterange(start_date, end_date):
|
| 30 |
+
for n in range(int((end_date - start_date).days)):
|
| 31 |
+
yield start_date + timedelta(n)
|
| 32 |
+
|
| 33 |
+
def estimator(start_patch, end_patch, mode, equilibrium, data_patch, limited_event, permanent_event, play_memory_of_chaos, EXPRESS_SUPPLY, BP):
|
| 34 |
+
|
| 35 |
+
duration = abs(start_patch - end_patch).days
|
| 36 |
+
|
| 37 |
+
n_weekdays = weekday_count(start_patch, end_patch)
|
| 38 |
+
n_weeks = Counter(n_weekdays.values()).most_common(1)[0][0]
|
| 39 |
+
|
| 40 |
+
if mode == 1:
|
| 41 |
+
start_half = start_patch
|
| 42 |
+
end_half = start_half + datetime.timedelta(days = duration // 2 )
|
| 43 |
+
|
| 44 |
+
duration = abs(start_half - end_half).days
|
| 45 |
+
|
| 46 |
+
if mode == 2:
|
| 47 |
+
start_half = start_patch + datetime.timedelta(days = duration // 2 )
|
| 48 |
+
end_half = end_patch
|
| 49 |
+
|
| 50 |
+
duration = abs(start_half - end_half).days
|
| 51 |
+
|
| 52 |
+
reward = Reward()
|
| 53 |
+
reward_SU = {0:75, 1:75, 2:105, 3:135, 4:165, 5:195, 6:225}
|
| 54 |
+
|
| 55 |
+
reward.stellar_jade['daily_quest'] = 60 * duration
|
| 56 |
+
# reward.stellar_jade['chat'] = 5 * duration
|
| 57 |
+
|
| 58 |
+
if (mode == 0 or mode == 1) :
|
| 59 |
+
reward.stellar_jade['update'] = 600
|
| 60 |
+
reward.stellar_jade['permanent_event'] = np.sum([permanent_event[i]['reward'] for i in permanent_event])
|
| 61 |
+
|
| 62 |
+
|
| 63 |
+
special_event = 'gift_odyssey'
|
| 64 |
+
|
| 65 |
+
if mode == 0:
|
| 66 |
+
reward.stellar_jade['daily_login'] = 80
|
| 67 |
+
reward.stellar_jade['SU'] = reward_SU[equilibrium] * n_weekdays['Monday']
|
| 68 |
+
reward.stellar_jade['character_tryout'] = 20 * data_patch['n_character_banner']
|
| 69 |
+
reward.stellar_jade['character_quest'] = 100 * np.sum([data_patch['n_character_quest'][i] for i in data_patch['n_character_quest']])
|
| 70 |
+
reward.special_pass['Ember'] = 5 * Counter([single_date.day for single_date in daterange(start_patch, end_patch)])[1]
|
| 71 |
+
|
| 72 |
+
#edit every patch
|
| 73 |
+
reward.stellar_jade['event'] = np.sum([limited_event[i]['reward'] for i in limited_event if i != special_event])
|
| 74 |
+
reward.special_pass['event'] = limited_event[special_event]['reward']
|
| 75 |
+
|
| 76 |
+
if play_memory_of_chaos: reward.stellar_jade['memory_of_chaos'] = 600 * (n_weeks // 2)
|
| 77 |
+
|
| 78 |
+
if EXPRESS_SUPPLY:
|
| 79 |
+
reward.stellar_jade['EXPRESS_SUPPLY'] = 90 * duration
|
| 80 |
+
reward.oneiric_shard = int(300 * np.ceil(duration/30))
|
| 81 |
+
|
| 82 |
+
if BP:
|
| 83 |
+
reward.stellar_jade['BP'] = 680
|
| 84 |
+
reward.special_pass['BP'] = 4
|
| 85 |
+
|
| 86 |
+
reward.stellar_jade['redeem_code_next_patch'] = 300
|
| 87 |
+
|
| 88 |
+
else:
|
| 89 |
+
reward.stellar_jade['daily_login'] = 40
|
| 90 |
+
reward.stellar_jade['SU'] = reward_SU[equilibrium] * (n_weekdays['Monday'] // 2)
|
| 91 |
+
|
| 92 |
+
#companion quest
|
| 93 |
+
if mode == 1: reward.stellar_jade['character_quest'] = 100 * data_patch['n_character_quest']['first_half']
|
| 94 |
+
elif mode == 2: reward.stellar_jade['character_quest'] = 100 * data_patch['n_character_quest']['second_half']
|
| 95 |
+
|
| 96 |
+
#temporary
|
| 97 |
+
reward.stellar_jade['character_tryout'] = 20 * (data_patch['n_character_banner'] // 2)
|
| 98 |
+
reward.special_pass['Ember'] = 5 * Counter([single_date.day for single_date in daterange(start_half, end_half)])[1]
|
| 99 |
+
|
| 100 |
+
#edit every patch
|
| 101 |
+
reward.stellar_jade['event'] = np.sum([limited_event[i]['reward'] for i in limited_event if (i != special_event) and (limited_event[i]['date'][0] >= start_half and limited_event[i]['date'][0] + datetime.timedelta(days = 7) < end_half)])
|
| 102 |
+
reward.special_pass['event'] = limited_event[special_event]['reward'] if (limited_event[special_event]['date'][0] >= start_half and start_half + datetime.timedelta(days = 7) < end_half) else 0
|
| 103 |
+
|
| 104 |
+
if play_memory_of_chaos:
|
| 105 |
+
if mode == 1:
|
| 106 |
+
reward.stellar_jade['memory_of_chaos'] = 600 * 2
|
| 107 |
+
else: reward.stellar_jade['memory_of_chaos'] = 600
|
| 108 |
+
|
| 109 |
+
if EXPRESS_SUPPLY:
|
| 110 |
+
reward.stellar_jade['EXPRESS_SUPPLY'] = 90 * duration
|
| 111 |
+
reward.oneiric_shard = int(300 * np.ceil(duration/30))
|
| 112 |
+
|
| 113 |
+
if BP:
|
| 114 |
+
if mode == 2:
|
| 115 |
+
reward.stellar_jade['BP'] = 680
|
| 116 |
+
reward.special_pass['BP'] = 4
|
| 117 |
+
|
| 118 |
+
if mode == 2 : reward.stellar_jade['redeem_code_next_patch'] = 300
|
| 119 |
+
|
| 120 |
+
return reward
|
| 121 |
+
|
| 122 |
+
|
| 123 |
+
def export_to_image(data):
|
| 124 |
+
template = cv2.imread('./template.png')
|
| 125 |
+
|
| 126 |
+
font = ImageFont.truetype("./DMSans-Regular.ttf", 80)
|
| 127 |
+
color = (0, 78, 53)
|
| 128 |
+
|
| 129 |
+
image_rgb = cv2.cvtColor(template, cv2.COLOR_BGR2RGB)
|
| 130 |
+
pil_image = Image.fromarray(image_rgb)
|
| 131 |
+
draw = ImageDraw.Draw(pil_image)
|
| 132 |
+
|
| 133 |
+
pos = [(500, 50), (500, 280), (500, 530)]
|
| 134 |
+
text = [int(sum(data.stellar_jade.values())), int(sum(data.special_pass.values())), int(data.oneiric_shard)]
|
| 135 |
+
for d, position in zip(text, pos):
|
| 136 |
+
draw.text(position, str(d), font=font, fill=color)
|
| 137 |
+
|
| 138 |
+
return pil_image
|
| 139 |
+
|
| 140 |
+
def export_to_graph(data):
|
| 141 |
+
|
| 142 |
+
df = pd.DataFrame(sorted(data.stellar_jade.items(), key = lambda x:x[1], reverse = True), columns = ['source', 'stellar jade'])
|
| 143 |
+
|
| 144 |
+
source_map = {'daily_quest':'Daily Quest', 'permanent_event':'Permanent Event', 'event':'Limited Event', 'memory_of_chaos': 'Memory of Chaos', 'SU':'Simulate Universe', 'update':'Update', 'redeem_code_next_patch':'Code live next patch', 'character_quest':'Companion Quest', 'daily_login':'Website daily login', 'character_tryout':'Character trial', 'EXPRESS_SUPPLY':'Express supply', 'BP':'Battle pass', 'chat':'Daily Chat'}
|
| 145 |
+
|
| 146 |
+
filtered = df[df['stellar jade'] != 0]
|
| 147 |
+
|
| 148 |
+
source = [source_map[i] for i in filtered['source']]
|
| 149 |
+
|
| 150 |
+
filtered['source'] = source
|
| 151 |
+
|
| 152 |
+
df = filtered
|
| 153 |
+
|
| 154 |
+
df['stellar jade'] = df['stellar jade'].astype('int')
|
| 155 |
+
|
| 156 |
+
total_jade = df['stellar jade'].sum()
|
| 157 |
+
|
| 158 |
+
# Figure Size
|
| 159 |
+
fig, ax = plt.subplots(figsize =(16, 9))
|
| 160 |
+
|
| 161 |
+
stellar_jade = df['stellar jade']
|
| 162 |
+
|
| 163 |
+
# Horizontal Bar Plot
|
| 164 |
+
ax.barh(source, stellar_jade)
|
| 165 |
+
|
| 166 |
+
# Remove axes splines
|
| 167 |
+
for s in ['top', 'bottom', 'left', 'right']:
|
| 168 |
+
ax.spines[s].set_visible(False)
|
| 169 |
+
|
| 170 |
+
# Remove x, y Ticks
|
| 171 |
+
ax.xaxis.set_ticks_position('none')
|
| 172 |
+
ax.yaxis.set_ticks_position('none')
|
| 173 |
+
|
| 174 |
+
# Add padding between axes and labels
|
| 175 |
+
ax.xaxis.set_tick_params(pad = 5)
|
| 176 |
+
ax.yaxis.set_tick_params(pad = 10)
|
| 177 |
+
|
| 178 |
+
# Add x, y gridlines
|
| 179 |
+
ax.grid(color ='grey',linestyle ='--', linewidth = 0.5,alpha = 0.4)
|
| 180 |
+
|
| 181 |
+
# Show top values
|
| 182 |
+
ax.invert_yaxis()
|
| 183 |
+
|
| 184 |
+
# Add annotation to bars
|
| 185 |
+
for index, i in enumerate(ax.patches):
|
| 186 |
+
if index < 3 :
|
| 187 |
+
number_color = 'red'
|
| 188 |
+
elif index < 6:
|
| 189 |
+
number_color = 'orange'
|
| 190 |
+
else: number_color = 'grey'
|
| 191 |
+
|
| 192 |
+
plt.text(i.get_width()+10, i.get_y()+0.5,
|
| 193 |
+
str(round((i.get_width()), 2)) + ' ({0}%)'.format(round(100 * (i.get_width() / total_jade), 2)),
|
| 194 |
+
fontsize = 10,
|
| 195 |
+
color = number_color)
|
| 196 |
+
|
| 197 |
+
title = 'The most Stellar Jade Resource'
|
| 198 |
+
|
| 199 |
+
ax.set_title(title,
|
| 200 |
+
loc ='left', )
|
| 201 |
+
|
| 202 |
+
# Add Text watermark
|
| 203 |
+
fig.text(0.9, 0.15, 'CHAYEN', fontsize = 12,
|
| 204 |
+
color ='grey', ha ='right', va ='bottom',
|
| 205 |
+
alpha = 0.7)
|
| 206 |
+
|
| 207 |
+
buf = io.BytesIO()
|
| 208 |
+
fig.savefig(buf)
|
| 209 |
+
buf.seek(0)
|
| 210 |
+
img = Image.open(buf)
|
| 211 |
+
|
| 212 |
+
return img
|