294 lines
10 KiB
Python
294 lines
10 KiB
Python
import datetime
|
|
import locale
|
|
import math
|
|
import re
|
|
|
|
import pytz
|
|
|
|
from core.decorators import instance
|
|
from core.dict_object import DictObject
|
|
from core.text import Text
|
|
|
|
|
|
@instance()
|
|
class Util:
|
|
budatime_full_regex = re.compile("^([0-9]+[a-z]+)+$", re.IGNORECASE)
|
|
budatime_unit_regex = re.compile("([0-9]+)([a-z]+)", re.IGNORECASE)
|
|
|
|
def __init__(self):
|
|
# needed for self.format_number() to work properly
|
|
locale.setlocale(locale.LC_NUMERIC, '')
|
|
|
|
self.abilities = [
|
|
"Agility",
|
|
"Intelligence",
|
|
"Psychic",
|
|
"Stamina",
|
|
"Strength",
|
|
"Sense"
|
|
]
|
|
|
|
self.time_units = [
|
|
{
|
|
"units": ["yr", "years", "year", "y"],
|
|
"conversion_factor": 31536000
|
|
}, {
|
|
"units": ["month", "months", "mo"],
|
|
"conversion_factor": 2592000
|
|
}, {
|
|
"units": ["week", "weeks", "w"],
|
|
"conversion_factor": 604800
|
|
}, {
|
|
"units": ["day", "days", "d"],
|
|
"conversion_factor": 86400
|
|
}, {
|
|
"units": ["hr", "hours", "hour", "hrs", "h"],
|
|
"conversion_factor": 3600
|
|
}, {
|
|
"units": ["min", "mins", "m"],
|
|
"conversion_factor": 60
|
|
}, {
|
|
"units": ["sec", "secs", "s"],
|
|
"conversion_factor": 1
|
|
}
|
|
]
|
|
|
|
def inject(self, registry):
|
|
self.text: Text = registry.get_instance("text")
|
|
|
|
def get_handler_name(self, handler):
|
|
return handler.__module__ + "." + handler.__qualname__
|
|
|
|
def get_module_name(self, handler):
|
|
handler_name = self.get_handler_name(handler)
|
|
parts = handler_name.split(".")
|
|
return parts[1] + "." + parts[2]
|
|
|
|
def parse_time(self, budatime, default=0):
|
|
unixtime = 0
|
|
|
|
if not self.budatime_full_regex.search(budatime):
|
|
return default
|
|
|
|
matches = self.budatime_unit_regex.finditer(budatime)
|
|
|
|
for match in matches:
|
|
for time_unit in self.time_units:
|
|
if match.group(2).lower() in time_unit["units"]:
|
|
unixtime += int(match.group(1)) * time_unit["conversion_factor"]
|
|
continue
|
|
|
|
return unixtime
|
|
|
|
def time_to_readable(self, unixtime, min_unit="sec", max_unit="day", max_levels=2):
|
|
if unixtime == 0:
|
|
return "0 secs"
|
|
|
|
# handle negative as positive, and add negative sign at the end
|
|
is_negative = False
|
|
if unixtime < 0:
|
|
is_negative = True
|
|
unixtime *= -1
|
|
|
|
found_max_unit = False
|
|
time_shift = ""
|
|
levels = 0
|
|
for time_unit in self.time_units:
|
|
unit = time_unit["units"][0]
|
|
|
|
if max_unit in time_unit["units"]:
|
|
found_max_unit = True
|
|
|
|
# continue to skip until we have found the max unit
|
|
if not found_max_unit:
|
|
continue
|
|
|
|
unit_value = math.floor(unixtime / time_unit["conversion_factor"])
|
|
|
|
if unit_value == 0:
|
|
# do not show units where unit_value is 0
|
|
pass
|
|
elif unit_value == 1:
|
|
# show singular where unit_value is 1
|
|
time_shift += str(unit_value) + " " + unit + " "
|
|
else:
|
|
# show plural where unit_value is greater than 1
|
|
time_shift += str(unit_value) + " " + unit + "s "
|
|
|
|
unixtime %= time_unit["conversion_factor"]
|
|
|
|
# record level after the first a unit has a length
|
|
if levels or unit_value >= 1:
|
|
levels += 1
|
|
|
|
if levels == max_levels:
|
|
break
|
|
|
|
# if we have reached the min unit, then break, unless we have no output, in which case we continue
|
|
if time_shift and min_unit in time_unit["units"]:
|
|
break
|
|
|
|
return ("-" if is_negative else "") + time_shift.strip()
|
|
|
|
def get_ability(self, ability_str):
|
|
ability_str = ability_str.capitalize()
|
|
for ability in self.abilities:
|
|
if ability.startswith(ability_str):
|
|
return ability
|
|
return None
|
|
|
|
def get_all_abilities(self):
|
|
return self.abilities.copy()
|
|
|
|
def get_title_level(self, level):
|
|
if level < 5:
|
|
return 0
|
|
elif level < 15:
|
|
return 1
|
|
elif level < 50:
|
|
return 2
|
|
elif level < 100:
|
|
return 3
|
|
elif level < 150:
|
|
return 4
|
|
elif level < 190:
|
|
return 5
|
|
elif level < 205:
|
|
return 6
|
|
else:
|
|
return 7
|
|
|
|
def get_level_range_tl(self, tl):
|
|
if tl == 0:
|
|
return 0, 4
|
|
elif tl == 1:
|
|
return 5, 14
|
|
elif tl == 2:
|
|
return 15, 49
|
|
elif tl == 3:
|
|
return 50, 99
|
|
elif tl == 4:
|
|
return 100, 149
|
|
elif tl == 5:
|
|
return 150, 189
|
|
elif tl == 6:
|
|
return 190, 204
|
|
elif tl == 7:
|
|
return 205, 300
|
|
else:
|
|
return 0, 0
|
|
|
|
def format_number(self, number):
|
|
return locale.format_string("%.*f", (0, number), grouping=True)
|
|
|
|
def get_profession(self, search, long=True):
|
|
search = search.lower()
|
|
|
|
if search in ["adv", "advy", "adventurer"]:
|
|
return "Adventurer" if long else "Adv"
|
|
elif search in ["agent"]:
|
|
return "Agent" if long else "Agent"
|
|
elif search in ["crat", "bureaucrat"]:
|
|
return "Bureaucrat" if long else "Crat"
|
|
elif search in ["doc", "doctor"]:
|
|
return "Doctor" if long else "Doc"
|
|
elif search in ["enf", "enfo", "enforcer"]:
|
|
return "Enforcer" if long else "Enf"
|
|
elif search in ["eng", "engi", "engy", "engineer"]:
|
|
return "Engineer" if long else "Eng"
|
|
elif search in ["fix", "fixer"]:
|
|
return "Fixer" if long else "Fix"
|
|
elif search in ["keep", "keeper"]:
|
|
return "Keeper" if long else "Keep"
|
|
elif search in ["ma", "martial", "martialartist", "martial artist"]:
|
|
return "Martial Artist" if long else "MA"
|
|
elif search in ["mp", "meta", "metaphysicist", "meta-physicist"]:
|
|
return "Meta-Physicist" if long else "MP"
|
|
elif search in ["nt", "nano", "nanotechnician", "nano-technician"]:
|
|
return "Nano-Technician" if long else "NT"
|
|
elif search in ["sha", "shade"]:
|
|
return "Shade" if long else "Shade"
|
|
elif search in ["sol", "sold", "soldier"]:
|
|
return "Soldier" if long else "Sold"
|
|
elif search in ["tra", "trad", "trader"]:
|
|
return "Trader" if long else "Trader"
|
|
elif search in ["gen", "general"]:
|
|
return "General" if long else "UKN"
|
|
else:
|
|
return None
|
|
|
|
def get_prof_icon(self, search, large=False):
|
|
large = "_LARGE" if large else ""
|
|
|
|
search = self.get_profession(search)
|
|
if search == "Adventurer":
|
|
return self.text.make_image(f"id:GFX_GUI_ICON_PROFESSION{large}_6", "tdb")
|
|
elif search == "Agent":
|
|
return self.text.make_image(f"id:GFX_GUI_ICON_PROFESSION{large}_5", "tdb")
|
|
elif search == "Bureaucrat":
|
|
return self.text.make_image(f"id:GFX_GUI_ICON_PROFESSION{large}_8", "tdb")
|
|
elif search == "Doctor":
|
|
return self.text.make_image(f"id:GFX_GUI_ICON_PROFESSION{large}_10", "tdb")
|
|
elif search == "Enforcer":
|
|
return self.text.make_image(f"id:GFX_GUI_ICON_PROFESSION{large}_9", "tdb")
|
|
elif search == "Engineer":
|
|
return self.text.make_image(f"id:GFX_GUI_ICON_PROFESSION{large}_3", "tdb")
|
|
elif search == "Fixer":
|
|
return self.text.make_image(f"id:GFX_GUI_ICON_PROFESSION{large}_4", "tdb")
|
|
elif search == "Keeper":
|
|
return self.text.make_image(f"id:GFX_GUI_ICON_PROFESSION{large}_14", "tdb")
|
|
elif search == "Martial Artist":
|
|
return self.text.make_image(f"id:GFX_GUI_ICON_PROFESSION{large}_2", "tdb")
|
|
elif search == "Meta-Physicist":
|
|
return self.text.make_image(f"id:GFX_GUI_ICON_PROFESSION{large}_12", "tdb")
|
|
elif search == "Nano-Technician":
|
|
return self.text.make_image(f"id:GFX_GUI_ICON_PROFESSION{large}_11", "tdb")
|
|
elif search == "Shade":
|
|
return self.text.make_image(f"id:GFX_GUI_ICON_PROFESSION{large}_15", "tdb")
|
|
elif search == "Soldier":
|
|
return self.text.make_image(f"id:GFX_GUI_ICON_PROFESSION{large}_1", "tdb")
|
|
elif search == "Trader":
|
|
return self.text.make_image(f"id:GFX_GUI_ICON_PROFESSION{large}_7", "tdb")
|
|
else:
|
|
return ""
|
|
|
|
def get_all_professions(self):
|
|
return ["Adventurer", "Agent", "Bureaucrat", "Doctor", "Enforcer", "Engineer", "Fixer", "Keeper",
|
|
"Martial Artist", "Meta-Physicist", "Nano-Technician", "Shade", "Soldier", "Trader"]
|
|
|
|
def format_date(self, timestamp):
|
|
value = datetime.datetime.fromtimestamp(timestamp, tz=pytz.UTC)
|
|
return value.strftime('%Y-%m-%d')
|
|
|
|
def format_time(self, timestamp):
|
|
value = datetime.datetime.fromtimestamp(timestamp, tz=pytz.UTC)
|
|
return value.strftime('%H:%M:%S')
|
|
|
|
def format_datetime(self, timestamp):
|
|
value = datetime.datetime.fromtimestamp(timestamp, tz=pytz.UTC)
|
|
return value.strftime('%Y-%m-%d %H:%M:%S %Z')
|
|
|
|
def interpolate_value(self, interpolated_ql, interpolation_ranges, precision=0):
|
|
min_val = None
|
|
max_val = None
|
|
for ql, v in interpolation_ranges.items():
|
|
# required to avoid division by zero
|
|
if ql == interpolated_ql:
|
|
return v
|
|
|
|
if interpolated_ql >= ql and (not min_val or ql > min_val.ql):
|
|
min_val = DictObject({"ql": ql, "val": v})
|
|
|
|
if interpolated_ql <= ql and (not max_val or ql < max_val.ql):
|
|
max_val = DictObject({"ql": ql, "val": v})
|
|
|
|
if not min_val or not max_val:
|
|
return None
|
|
|
|
return round((max_val.val - min_val.val) / (max_val.ql - min_val.ql) *
|
|
(interpolated_ql - min_val.ql) + min_val.val, precision)
|
|
|
|
# noinspection PyMethodMayBeStatic
|
|
def get_offset_limit(self, page_size, page_number):
|
|
return (page_number - 1) * page_size, page_size
|