import urllib.request import json import all_constant as c def round_ans(val): """ Rounds currency amount to 2 decimal places. :param val: Number to be rounded :return: Number rounded to 2 decimal places as string """ return "{:.2f}".format(val) def get_live_rates(): """ Fetches live exchange rates relative to NZD from the Frankfurter API. Returns a dictionary of rates, or falls back to constants if unavailable. No API key required. :return: Dictionary of exchange rates relative to NZD """ try: # Build list of target currencies excluding NZD (the base) targets = ",".join([cur for cur in c.CURRENCIES if cur != "NZD"]) url = f"https://api.frankfurter.app/latest?from=NZD&to={targets}" with urllib.request.urlopen(url, timeout=5) as response: data = json.loads(response.read()) # Build rates dict — always include NZD = 1.0 as base rates = {"NZD": 1.0} rates.update(data["rates"]) return rates except Exception: # If fetch fails for any reason, fall back to hardcoded constants return c.RATES_FROM_NZD def convert_currency(amount, from_currency, to_currency, rates): """ Converts an amount between any two supported currencies. Uses NZD as the base currency for all conversions. :param amount: Amount to convert :param from_currency: Currency code to convert from (e.g. "NZD") :param to_currency: Currency code to convert to (e.g. "JPY") :param rates: Dictionary of exchange rates relative to NZD :return: Converted amount as a rounded string """ # Convert from source currency to NZD, then from NZD to target currency rate_from = rates[from_currency] rate_to = rates[to_currency] amount_in_nzd = amount / rate_from converted = amount_in_nzd * rate_to return round_ans(converted) def get_currency_symbol(currency): """ Returns the currency symbol for a given currency code. :param currency: Currency code (e.g. "NZD") :return: Currency symbol string """ symbols = { "NZD": "$", "AUD": "$", "USD": "$", "JPY": "¥", } return symbols.get(currency, "") # Legacy functions kept for compatibility with earlier versions def nzd_to_jpy(to_convert): """ Converts from NZD to JPY using fallback constant rate. :param to_convert: Amount in NZD :return: Converted amount in JPY """ return convert_currency(to_convert, "NZD", "JPY", c.RATES_FROM_NZD) def jpy_to_nzd(to_convert): """ Converts from JPY to NZD using fallback constant rate. :param to_convert: Amount in JPY :return: Converted amount in NZD """ return convert_currency(to_convert, "JPY", "NZD", c.RATES_FROM_NZD) # Main Routine / Testing starts here # rates = get_live_rates() # test_cases = [(100, "NZD", "JPY"), (850, "JPY", "NZD"), # (100, "NZD", "USD"), (100, "USD", "AUD")] # # for amount, frm, to in test_cases: # sym_from = get_currency_symbol(frm) # sym_to = get_currency_symbol(to) # result = convert_currency(amount, frm, to, rates) # print(f"{sym_from}{amount} {frm} is {sym_to}{result} {to}")