diff options
Diffstat (limited to 'searx/wikidata_units.py')
| -rw-r--r-- | searx/wikidata_units.py | 79 |
1 files changed, 70 insertions, 9 deletions
diff --git a/searx/wikidata_units.py b/searx/wikidata_units.py index 9fc94585f..b05ded220 100644 --- a/searx/wikidata_units.py +++ b/searx/wikidata_units.py @@ -5,6 +5,7 @@ Coordinates`_ .. _SPARQL/WIKIDATA Precision, Units and Coordinates: https://en.wikibooks.org/wiki/SPARQL/WIKIDATA_Precision,_Units_and_Coordinates#Quantities """ +from __future__ import annotations __all__ = ["convert_from_si", "convert_to_si", "symbol_to_si"] @@ -13,6 +14,47 @@ import collections from searx import data from searx.engines import wikidata + +class Beaufort: + """The mapping of the Beaufort_ contains values from 0 to 16 (55.6 m/s), + wind speeds greater than 200km/h (55.6 m/s) are given as 17 Bft. Thats why + a value of 17 Bft cannot be converted to SI. + + .. hint:: + + Negative values or values greater 16 Bft (55.6 m/s) will throw a + :py:obj:`ValueError`. + + _Beaufort: https://en.wikipedia.org/wiki/Beaufort_scale + """ + + # fmt: off + scale: list[float] = [ + 0.2, 1.5, 3.3, 5.4, 7.9, + 10.7, 13.8, 17.1, 20.7, 24.4, + 28.4, 32.6, 32.7, 41.1, 45.8, + 50.8, 55.6 + ] + # fmt: on + + @classmethod + def from_si(cls, value) -> float: + if value < 0 or value > 55.6: + raise ValueError(f"invalid value {value} / the Beaufort scales from 0 to 16 (55.6 m/s)") + bft = 0 + for bft, mps in enumerate(cls.scale): + if mps >= value: + break + return bft + + @classmethod + def to_si(cls, value) -> float: + idx = round(value) + if idx < 0 or idx > 16: + raise ValueError(f"invalid value {value} / the Beaufort scales from 0 to 16 (55.6 m/s)") + return cls.scale[idx] + + ADDITIONAL_UNITS = [ { "si_name": "Q11579", @@ -26,6 +68,12 @@ ADDITIONAL_UNITS = [ "to_si": lambda val: (val + 459.67) * 5 / 9, "from_si": lambda val: (val * 9 / 5) - 459.67, }, + { + "si_name": "Q182429", + "symbol": "Bft", + "to_si": Beaufort.to_si, + "from_si": Beaufort.from_si, + }, ] """Additional items to convert from a measure unit to a SI unit (vice versa). @@ -55,6 +103,7 @@ ALIAS_SYMBOLS = { '°C': ('C',), '°F': ('F',), 'mi': ('L',), + 'Bft': ('bft',), } """Alias symbols for known unit of measure symbols / by example:: @@ -65,11 +114,11 @@ ALIAS_SYMBOLS = { SYMBOL_TO_SI = [] -UNITS_BY_SI_NAME: dict | None = None +UNITS_BY_SI_NAME: dict = {} def convert_from_si(si_name: str, symbol: str, value: float | int) -> float: - from_si = units_by_si_name(si_name)[symbol][symbol]["from_si"] + from_si = units_by_si_name(si_name)[symbol][pos_from_si] if isinstance(from_si, (float, int)): value = float(value) * from_si else: @@ -78,7 +127,7 @@ def convert_from_si(si_name: str, symbol: str, value: float | int) -> float: def convert_to_si(si_name: str, symbol: str, value: float | int) -> float: - to_si = units_by_si_name(si_name)[symbol][symbol]["to_si"] + to_si = units_by_si_name(si_name)[symbol][pos_to_si] if isinstance(to_si, (float, int)): value = float(value) * to_si else: @@ -88,20 +137,32 @@ def convert_to_si(si_name: str, symbol: str, value: float | int) -> float: def units_by_si_name(si_name): - global UNITS_BY_SI_NAME - if UNITS_BY_SI_NAME is not None: + global UNITS_BY_SI_NAME # pylint: disable=global-statement,global-variable-not-assigned + if UNITS_BY_SI_NAME: return UNITS_BY_SI_NAME[si_name] - UNITS_BY_SI_NAME = {} + # build the catalog .. for item in symbol_to_si(): - by_symbol = UNITS_BY_SI_NAME.get(si_name) + + item_si_name = item[pos_si_name] + item_symbol = item[pos_symbol] + + by_symbol = UNITS_BY_SI_NAME.get(item_si_name) if by_symbol is None: by_symbol = {} - UNITS_BY_SI_NAME[si_name] = by_symbol - by_symbol[item["symbol"]] = item + UNITS_BY_SI_NAME[item_si_name] = by_symbol + by_symbol[item_symbol] = item + return UNITS_BY_SI_NAME[si_name] +pos_symbol = 0 # (alias) symbol +pos_si_name = 1 # si_name +pos_from_si = 2 # from_si +pos_to_si = 3 # to_si +pos_symbol = 4 # standardized symbol + + def symbol_to_si(): """Generates a list of tuples, each tuple is a measure unit and the fields in the tuple are: |