Z21122

{
    "Z1K1": "Z2",
    "Z2K1": {
        "Z1K1": "Z6",
        "Z6K1": "Z21122"
    },
    "Z2K2": {
        "Z1K1": "Z14",
        "Z14K1": "Z21121",
        "Z14K3": {
            "Z1K1": "Z16",
            "Z16K1": "Z610",
            "Z16K2": "def Z21121(Z21121K1, Z21121K2, Z21121K3, Z21121K4, Z21121K5, Z21121K6, Z21121K7):\n    from fractions import Fraction\n    import re\n    Wikifunctions.Debug(Z21121K4)\n    # Constants\n    METRIC_PREFIXES = {\n        'Q': 30,\n        'R': 27,\n        'Y': 24,\n        'Z': 21,\n        'E': 18,\n        'P': 15,\n        'T': 12,\n        'G': 9,\n        'M': 6,\n        'k': 3,\n        'h': 2,\n        'da': 1,\n        'd': -1,\n        'c': -2,\n        'm': -3,\n        'μ': -6, # U+03BC: GREEK SMALL LETTER MU\n        'µ': -6, # U+00B5: MICRO SIGN\n        'n': -9,\n        'p': -12,\n        'f': -15,\n        'a': -18,\n        'z': -21,\n        'y': -24,\n        'r': -27,\n        'q': -30\n    }\n\n    METRIC_PREFIX_UNITS = {\n        'm': \"length\",\n        'g': \"mass\",\n        's': \"time\",\n        'b': \"storage\",\n        'B': \"storage\",\n        'Pa': \"pressure\",\n        'J': \"energy\",\n        'K': \"temperature\",\n        'C': \"temperature\",\n        'F': \"temperature\",\n        \"Wh\": \"energy\",\n        \"bar\": \"pressure\",\n        \"mHg\": \"pressure\"\n    }\n\n    PRIORITY_TOKENS = ['psi', 'mo']\n\n    UNITS = {\n        # Length units\n        'mi': [Fraction(1609.344), \"length\"],\n        'ft': [Fraction(3048, 10000), \"length\"],\n        'yd': [Fraction(9144, 10000), \"length\"],\n        'in': [Fraction(254, 10000), \"length\"],\n        'NM': [Fraction(1852), \"length\"],\n        'au': [Fraction(495978707e11), \"length\"],\n        'ly': [Fraction(461e15), \"length\"],\n        'Å': [Fraction(1e-10), \"length\"],\n        'fur': [Fraction(201168, 1000), \"length\"],\n        'ftm': [Fraction(18288, 10000), \"length\"],\n        'cb': [Fraction(1852, 10), \"length\"],\n        'ch': [Fraction(201168, 10000), \"length\"],\n        'rd': [Fraction(50292, 10000), \"length\"],\n        'li': [Fraction(201168, 1000000), \"length\"],\n\n        # Time units\n        's': [Fraction(1), \"time\"],\n        'min': [Fraction(60), \"time\"],\n        'd': [Fraction(3600 * 24), \"time\"],\n        'wk': [Fraction(3600 * 24 * 7), \"time\"],\n        'mo': [Fraction(31536000 / 12), \"time\"],\n        'y': [Fraction(31536000), \"time\"],\n\n        # Mass units\n        'lb': [Fraction(45359237, 100000000), \"mass\"],\n        'oz': [Fraction(28349523125, 1000000000000), \"mass\"],\n\n        # Digital storage units\n        'b': [Fraction(1), \"storage\"],\n        'B': [Fraction(8), \"storage\"],\n\n        # Pressure units\n        'Pa': [Fraction(1), \"pressure\"],\n        'bar': [Fraction(1e5), \"pressure\"],\n        'atm': [Fraction(101325), \"pressure\"],\n        'mHg': [Fraction(133322), \"pressure\"],\n        'psi': [Fraction(6894.76), \"pressure\"],\n\n        # Energy units\n        'J': [Fraction(1), \"energy\"],\n        'cal': [Fraction(4.184), \"energy\"],\n        'eV': [Fraction(1.602176634e-19), \"energy\"],\n        'BTU': [Fraction(1055.06), \"energy\"],\n        'Wh': [Fraction(3600), \"energy\"],\n\n        # Special units\n        'h': [Fraction(3600), \"time\"],\n        'm': [Fraction(1), \"length\"],\n        'g': [Fraction(1, 1000), \"mass\"],\n        'K': [Fraction(1), \"temperature\"],\n        'C': [Fraction(1), \"temperature\"],\n        'F': [Fraction(1), \"temperature\"]\n    }\n\n    Z21121K1 = Z21121K1.replace(\",\", \"\")\n\t\n    def convert_temperature(value, from_unit, to_unit):\n        kelvin = (value + 273.15 if from_unit == 'C' else\n                 (value + 459.67) * 5/9 if from_unit == 'F' else value)\n\n        return (kelvin - 273.15 if to_unit == 'C' else\n                kelvin * 9/5 - 459.67 if to_unit == 'F' else kelvin)\n\n    def parse_unit_string(unit_string):\n        tokens = []\n        i = 0\n\n        while i \u003C len(unit_string):\n            while i \u003C len(unit_string) and unit_string[i].isspace():\n                i += 1\n            if i \u003E= len(unit_string):\n                break\n\n            priority_match = next((token for token in PRIORITY_TOKENS\n                                 if unit_string[i:].startswith(token)), None)\n            if priority_match:\n                tokens.append((priority_match, 1))\n                i += len(priority_match)\n                continue\n\n            longest_match = None\n            if i + 1 \u003C len(unit_string):\n                for prefix in METRIC_PREFIXES:\n                    for base in METRIC_PREFIX_UNITS:\n                        combined = prefix + base\n                        if unit_string[i:].startswith(combined):\n                            if not longest_match or len(combined) \u003E len(longest_match[1] if isinstance(longest_match, tuple) else longest_match):\n                                longest_match = (prefix, base)\n\n            if longest_match is None:\n                valid_tokens = sorted(list(UNITS.keys()) + ['/', '*'], key=len, reverse=True)\n                for token in valid_tokens:\n                    if unit_string[i:].startswith(token):\n                        longest_match = token\n                        break\n\n            if not longest_match:\n                if unit_string[i].isdigit() or unit_string[i] == '-':\n                    num_start = i\n                    i += 1\n                    while i \u003C len(unit_string) and (unit_string[i].isdigit() or unit_string[i] == '.'):\n                        i += 1\n                    if tokens:\n                        try:\n                            tokens[-1] = (tokens[-1][0], int(unit_string[num_start:i]))\n                        except ValueError:\n                            raise ValueError(f\"Invalid exponent: {unit_string[num_start:i]}\")\n                    continue\n                raise ValueError(f\"Invalid unit token at position {i}: {unit_string[i:i+5]}\")\n\n            if isinstance(longest_match, tuple):\n                prefix, base = longest_match\n                tokens.append(((prefix, base), 1))\n                i += len(prefix) + len(base)\n            else:\n                tokens.append((longest_match, 1))\n                i += len(longest_match)\n\n        return tokens\n\n    def calculate_conversion_factor(tokens):\n        value = Fraction(1)\n        unit_types = {}\n        dividing = False\n\n        for token, exponent in tokens:\n            if token == '/':\n                dividing = True\n                continue\n            elif token == '*':\n                continue\n\n            exp_multiplier = -1 if dividing else 1\n\n            if isinstance(token, tuple):\n                prefix, base = token\n                prefix_value = Fraction(10 ** (METRIC_PREFIXES[prefix]))\n                base_type = METRIC_PREFIX_UNITS[base]\n                base_value = UNITS.get(base, [Fraction(1)])[0]\n\n                value *= (prefix_value * base_value) ** (exponent * exp_multiplier)\n                unit_types[base_type] = unit_types.get(base_type, 0) + (exponent * exp_multiplier)\n            elif token in UNITS:\n                unit_info = UNITS[token]\n                value *= unit_info[0] ** (exponent * exp_multiplier)\n                unit_types[unit_info[1]] = unit_types.get(unit_info[1], 0) + (exponent * exp_multiplier)\n            else:\n                raise ValueError(f\"Unknown token: {token}\")\n\n        return value, unit_types\n\n    def clean_unit(unit):\n        replacements = {\n            \"mi/h\": \"mph\",\n            r'([a-zA-Z]+)(\\d+)': r'\\1\u003Csup\u003E\\2\u003C/sup\u003E'\n        }\n        for pattern, replacement in replacements.items():\n            unit = re.sub(pattern, replacement, unit)\n            Wikifunctions.Debug(unit)\n        return unit\n\n    from_tokens = parse_unit_string(Z21121K2)\n    to_tokens = parse_unit_string(Z21121K3)\n\n    if len(from_tokens) == 1 and len(to_tokens) == 1:\n        from_unit = from_tokens[0][0]\n        to_unit = to_tokens[0][0]\n        if isinstance(from_unit, tuple):\n            from_unit = from_unit[1]\n        if isinstance(to_unit, tuple):\n            to_unit = to_unit[1]\n\n        if from_unit in ['K', 'C', 'F'] and to_unit in ['K', 'C', 'F']:\n            result = Fraction(convert_temperature(float(Z21121K1), from_unit, to_unit))\n            result = result.limit_denominator(1000000000)\n            final_value = round(float(result), Z21121K4)\n            if final_value == int(final_value):\n                final_value = int(final_value)\n            return f\"{Z21121K1} {clean_unit(Z21121K2)} ({final_value} {clean_unit(Z21121K3)})\"\n\n    from_factor, from_types = calculate_conversion_factor(from_tokens)\n    to_factor, to_types = calculate_conversion_factor(to_tokens)\n\n    if from_types != to_types:\n        raise ValueError(f\"Incompatible unit types: {from_types} vs {to_types}\")\n\n    result = (Fraction(Z21121K1) * from_factor / to_factor).limit_denominator(1000000000)\n    final_value = round(float(result), Z21121K4)\n    final_value = f\"{final_value:,.{max(Z21121K4, 0)}f}\"\n    if Fraction(Z21121K1).denominator == 1:\n        Z21121K1 = str(int(Z21121K1))\n    else:\n        Z21121K1 = f\"{float(Fraction(Z21121K1)):,}\"\n\n    return f\"{Z21121K1} {clean_unit(Z21121K2)} ({final_value} {clean_unit(Z21121K3)})\"\n"
        }
    },
    "Z2K3": {
        "Z1K1": "Z12",
        "Z12K1": [
            "Z11",
            {
                "Z1K1": "Z11",
                "Z11K1": "Z1002",
                "Z11K2": "Convert, python "
            },
            {
                "Z1K1": "Z11",
                "Z11K1": "Z1004",
                "Z11K2": "convertir, en Python"
            }
        ]
    },
    "Z2K4": {
        "Z1K1": "Z32",
        "Z32K1": [
            "Z31"
        ]
    },
    "Z2K5": {
        "Z1K1": "Z12",
        "Z12K1": [
            "Z11"
        ]
    }
}