{"abstract":"A CHF fare paid in euro cash is rounded to 5 cents.","category":"Ride-hailing fare and surge pricing","checks":7,"contract":"Convert a fare to the payment currency with the directed rate fx[FROM+TO] = [num, den] (half up), then, for cash payments only, round half up to the payment currency cash step (CHF 5 centimes, SEK 100 ore, others 1). Card and wallet payments are not cash-rounded. Return the amount in minor units of the payment currency.","evaluation_group":"w2-ride-hailing-fare-surge-cash-rounding-fx","failed_approach":"Defaulting unknown currencies to a 5-unit step rounds euro cash.","family":"w2-ride-hailing-fare-surge-cash-rounding-fx-cash-step-currency","id":"FA-85721","implementations":{"attempt":{"sha256":"4b6d8b9e4d6272a58d85a444023bce7a3fffb7376610c5bab91bcfb435e10d7e","source":"\"\"\"Failure Map reference implementation. Python standard library only.\"\"\"\nimport json\n\nN = 1\nobservations = []\ndef solve(fare_cents, fare_ccy, pay_ccy, method, fx, cash_step):\n    amt = fare_cents\n    if pay_ccy != fare_ccy:\n        num, den = fx[fare_ccy + pay_ccy]\n        amt = (amt * num * 2 + den) // (2 * den)\n    if method == 'cash':\n        step = cash_step.get(pay_ccy, 5)\n        amt = (amt * 2 + step) // (2 * step) * step\n    return amt\ndef check(label, actual, expected):\n    observations.append({\"check\": label, \"actual\": actual, \"expected\": expected, \"passed\": actual == expected})\nfixtures = [[('regression: cash step currency',\n   [2502, 'SEK', 'EUR', 'cash',\n    {'CHFEUR': [104, 100], 'EURCHF': [94, 100], 'EURSEK': [1147, 100], 'SEKEUR': [9, 100]},\n    {'CHF': 5, 'SEK': 100}],\n   225),\n  ('partial repair probe: cash step currency',\n   [1234, 'EUR', 'EUR', 'cash',\n    {'CHFEUR': [104, 100], 'EURCHF': [94, 100], 'EURSEK': [1147, 100], 'SEKEUR': [9, 100]},\n    {'CHF': 5, 'SEK': 100}],\n   1234),\n  ('second regression',\n   [1003, 'SEK', 'EUR', 'cash',\n    {'CHFEUR': [104, 100], 'EURCHF': [94, 100], 'EURSEK': [1147, 100], 'SEKEUR': [9, 100]},\n    {'CHF': 5, 'SEK': 100}],\n   90),\n  ('normal control 1',\n   [1234, 'SEK', 'EUR', 'wallet',\n    {'CHFEUR': [104, 100], 'EURCHF': [94, 100], 'EURSEK': [1147, 100], 'SEKEUR': [9, 100]},\n    {'CHF': 5, 'SEK': 100}],\n   111),\n  ('normal control 2',\n   [1003, 'CHF', 'CHF', 'card',\n    {'CHFEUR': [104, 100], 'EURCHF': [94, 100], 'EURSEK': [1147, 100], 'SEKEUR': [9, 100]},\n    {'CHF': 5, 'SEK': 100}],\n   1003),\n  ('normal control 3',\n   [4194, 'EUR', 'EUR', 'card',\n    {'CHFEUR': [104, 100], 'EURCHF': [94, 100], 'EURSEK': [1147, 100], 'SEKEUR': [9, 100]},\n    {'CHF': 5, 'SEK': 100}],\n   4194),\n  ('normal control 4',\n   [1999, 'EUR', 'EUR', 'wallet',\n    {'CHFEUR': [104, 100], 'EURCHF': [94, 100], 'EURSEK': [1147, 100], 'SEKEUR': [9, 100]},\n    {'CHF': 5, 'SEK': 100}],\n   1999)],\n [('regression: cash step currency',\n   [1003, 'CHF', 'EUR', 'cash',\n    {'CHFEUR': [104, 100], 'EURCHF': [94, 100], 'EURSEK': [1147, 100], 'SEKEUR': [9, 100]},\n    {'CHF': 5, 'SEK': 100}],\n   1043),\n  ('partial repair probe: cash step currency',\n   [2502, 'EUR', 'EUR', 'cash',\n    {'CHFEUR': [104, 100], 'EURCHF': [94, 100], 'EURSEK': [1147, 100], 'SEKEUR': [9, 100]},\n    {'CHF': 5, 'SEK': 100}],\n   2502),\n  ('second regression',\n   [1003, 'EUR', 'SEK', 'cash',\n    {'CHFEUR': [104, 100], 'EURCHF': [94, 100], 'EURSEK': [1147, 100], 'SEKEUR': [9, 100]},\n    {'CHF': 5, 'SEK': 100}],\n   11500),\n  ('normal control 1',\n   [3395, 'EUR', 'SEK', 'wallet',\n    {'CHFEUR': [104, 100], 'EURCHF': [94, 100], 'EURSEK': [1147, 100], 'SEKEUR': [9, 100]},\n    {'CHF': 5, 'SEK': 100}],\n   38941),\n  ('normal control 2',\n   [2795, 'EUR', 'EUR', 'cash',\n    {'CHFEUR': [104, 100], 'EURCHF': [94, 100], 'EURSEK': [1147, 100], 'SEKEUR': [9, 100]},\n    {'CHF': 5, 'SEK': 100}],\n   2795),\n  ('normal control 3',\n   [1234, 'CHF', 'EUR', 'card',\n    {'CHFEUR': [104, 100], 'EURCHF': [94, 100], 'EURSEK': [1147, 100], 'SEKEUR': [9, 100]},\n    {'CHF': 5, 'SEK': 100}],\n   1283),\n  ('normal control 4',\n   [2502, 'SEK', 'SEK', 'cash',\n    {'CHFEUR': [104, 100], 'EURCHF': [94, 100], 'EURSEK': [1147, 100], 'SEKEUR': [9, 100]},\n    {'CHF': 5, 'SEK': 100}],\n   2500)],\n [('regression: cash step currency',\n   [2387, 'CHF', 'EUR', 'cash',\n    {'CHFEUR': [104, 100], 'EURCHF': [94, 100], 'EURSEK': [1147, 100], 'SEKEUR': [9, 100]},\n    {'CHF': 5, 'SEK': 100}],\n   2482),\n  ('partial repair probe: cash step currency',\n   [1003, 'CHF', 'EUR', 'cash',\n    {'CHFEUR': [104, 100], 'EURCHF': [94, 100], 'EURSEK': [1147, 100], 'SEKEUR': [9, 100]},\n    {'CHF': 5, 'SEK': 100}],\n   1043),\n  ('second regression',\n   [2017, 'EUR', 'SEK', 'cash',\n    {'CHFEUR': [104, 100], 'EURCHF': [94, 100], 'EURSEK': [1147, 100], 'SEKEUR': [9, 100]},\n    {'CHF': 5, 'SEK': 100}],\n   23100),\n  ('normal control 1',\n   [873, 'EUR', 'EUR', 'card',\n    {'CHFEUR': [104, 100], 'EURCHF': [94, 100], 'EURSEK': [1147, 100], 'SEKEUR': [9, 100]},\n    {'CHF': 5, 'SEK': 100}],\n   873),\n  ('normal control 2',\n   [1003, 'SEK', 'SEK', 'wallet',\n    {'CHFEUR': [104, 100], 'EURCHF': [94, 100], 'EURSEK': [1147, 100], 'SEKEUR': [9, 100]},\n    {'CHF': 5, 'SEK': 100}],\n   1003),\n  ('normal control 3',\n   [1003, 'EUR', 'EUR', 'wallet',\n    {'CHFEUR': [104, 100], 'EURCHF': [94, 100], 'EURSEK': [1147, 100], 'SEKEUR': [9, 100]},\n    {'CHF': 5, 'SEK': 100}],\n   1003),\n  ('normal control 4',\n   [1234, 'CHF', 'EUR', 'card',\n    {'CHFEUR': [104, 100], 'EURCHF': [94, 100], 'EURSEK': [1147, 100], 'SEKEUR': [9, 100]},\n    {'CHF': 5, 'SEK': 100}],\n   1283)],\n [('regression: cash step currency',\n   [2502, 'EUR', 'SEK', 'cash',\n    {'CHFEUR': [104, 100], 'EURCHF': [94, 100], 'EURSEK': [1147, 100], 'SEKEUR': [9, 100]},\n    {'CHF': 5, 'SEK': 100}],\n   28700),\n  ('partial repair probe: cash step currency',\n   [1234, 'CHF', 'EUR', 'cash',\n    {'CHFEUR': [104, 100], 'EURCHF': [94, 100], 'EURSEK': [1147, 100], 'SEKEUR': [9, 100]},\n    {'CHF': 5, 'SEK': 100}],\n   1283),\n  ('second regression',\n   [2502, 'SEK', 'EUR', 'cash',\n    {'CHFEUR': [104, 100], 'EURCHF': [94, 100], 'EURSEK': [1147, 100], 'SEKEUR': [9, 100]},\n    {'CHF': 5, 'SEK': 100}],\n   225),\n  ('normal control 1',\n   [2110, 'EUR', 'SEK', 'wallet',\n    {'CHFEUR': [104, 100], 'EURCHF': [94, 100], 'EURSEK': [1147, 100], 'SEKEUR': [9, 100]},\n    {'CHF': 5, 'SEK': 100}],\n   24202),\n  ('normal control 2',\n   [1999, 'CHF', 'EUR', 'card',\n    {'CHFEUR': [104, 100], 'EURCHF': [94, 100], 'EURSEK': [1147, 100], 'SEKEUR': [9, 100]},\n    {'CHF': 5, 'SEK': 100}],\n   2079),\n  ('normal control 3',\n   [1999, 'EUR', 'SEK', 'card',\n    {'CHFEUR': [104, 100], 'EURCHF': [94, 100], 'EURSEK': [1147, 100], 'SEKEUR': [9, 100]},\n    {'CHF': 5, 'SEK': 100}],\n   22929),\n  ('normal control 4',\n   [852, 'EUR', 'SEK', 'card',\n    {'CHFEUR': [104, 100], 'EURCHF': [94, 100], 'EURSEK': [1147, 100], 'SEKEUR': [9, 100]},\n    {'CHF': 5, 'SEK': 100}],\n   9772)],\n [('regression: cash step currency',\n   [2502, 'EUR', 'SEK', 'cash',\n    {'CHFEUR': [104, 100], 'EURCHF': [94, 100], 'EURSEK': [1147, 100], 'SEKEUR': [9, 100]},\n    {'CHF': 5, 'SEK': 100}],\n   28700),\n  ('partial repair probe: cash step currency',\n   [1234, 'EUR', 'EUR', 'cash',\n    {'CHFEUR': [104, 100], 'EURCHF': [94, 100], 'EURSEK': [1147, 100], 'SEKEUR': [9, 100]},\n    {'CHF': 5, 'SEK': 100}],\n   1234),\n  ('second regression',\n   [2502, 'EUR', 'EUR', 'cash',\n    {'CHFEUR': [104, 100], 'EURCHF': [94, 100], 'EURSEK': [1147, 100], 'SEKEUR': [9, 100]},\n    {'CHF': 5, 'SEK': 100}],\n   2502),\n  ('normal control 1',\n   [1234, 'EUR', 'EUR', 'wallet',\n    {'CHFEUR': [104, 100], 'EURCHF': [94, 100], 'EURSEK': [1147, 100], 'SEKEUR': [9, 100]},\n    {'CHF': 5, 'SEK': 100}],\n   1234),\n  ('normal control 2',\n   [1999, 'CHF', 'EUR', 'wallet',\n    {'CHFEUR': [104, 100], 'EURCHF': [94, 100], 'EURSEK': [1147, 100], 'SEKEUR': [9, 100]},\n    {'CHF': 5, 'SEK': 100}],\n   2079),\n  ('normal control 3',\n   [2203, 'EUR', 'EUR', 'wallet',\n    {'CHFEUR': [104, 100], 'EURCHF': [94, 100], 'EURSEK': [1147, 100], 'SEKEUR': [9, 100]},\n    {'CHF': 5, 'SEK': 100}],\n   2203),\n  ('normal control 4',\n   [1999, 'SEK', 'SEK', 'cash',\n    {'CHFEUR': [104, 100], 'EURCHF': [94, 100], 'EURSEK': [1147, 100], 'SEKEUR': [9, 100]},\n    {'CHF': 5, 'SEK': 100}],\n   2000)]]\nfor label, args, expected in fixtures[N-1]:\n    check(label, solve(*args), expected)\nprint(json.dumps({\"observations\": observations, \"passed\": all(x[\"passed\"] for x in observations)}, ensure_ascii=False))\nraise SystemExit(0 if all(x[\"passed\"] for x in observations) else 1)\n"},"broken":{"sha256":"7578b48018930064dfaa30e6c2d37d3ec5ea1e7d81099202d6864e1b59b43ea0","source":"\"\"\"Failure Map reference implementation. Python standard library only.\"\"\"\nimport json\n\nN = 1\nobservations = []\ndef solve(fare_cents, fare_ccy, pay_ccy, method, fx, cash_step):\n    amt = fare_cents\n    if pay_ccy != fare_ccy:\n        num, den = fx[fare_ccy + pay_ccy]\n        amt = (amt * num * 2 + den) // (2 * den)\n    if method == 'cash':\n        step = cash_step.get(fare_ccy, 1)\n        amt = (amt * 2 + step) // (2 * step) * step\n    return amt\ndef check(label, actual, expected):\n    observations.append({\"check\": label, \"actual\": actual, \"expected\": expected, \"passed\": actual == expected})\nfixtures = [[('regression: cash step currency',\n   [2502, 'SEK', 'EUR', 'cash',\n    {'CHFEUR': [104, 100], 'EURCHF': [94, 100], 'EURSEK': [1147, 100], 'SEKEUR': [9, 100]},\n    {'CHF': 5, 'SEK': 100}],\n   225),\n  ('partial repair probe: cash step currency',\n   [1234, 'EUR', 'EUR', 'cash',\n    {'CHFEUR': [104, 100], 'EURCHF': [94, 100], 'EURSEK': [1147, 100], 'SEKEUR': [9, 100]},\n    {'CHF': 5, 'SEK': 100}],\n   1234),\n  ('second regression',\n   [1003, 'SEK', 'EUR', 'cash',\n    {'CHFEUR': [104, 100], 'EURCHF': [94, 100], 'EURSEK': [1147, 100], 'SEKEUR': [9, 100]},\n    {'CHF': 5, 'SEK': 100}],\n   90),\n  ('normal control 1',\n   [1234, 'SEK', 'EUR', 'wallet',\n    {'CHFEUR': [104, 100], 'EURCHF': [94, 100], 'EURSEK': [1147, 100], 'SEKEUR': [9, 100]},\n    {'CHF': 5, 'SEK': 100}],\n   111),\n  ('normal control 2',\n   [1003, 'CHF', 'CHF', 'card',\n    {'CHFEUR': [104, 100], 'EURCHF': [94, 100], 'EURSEK': [1147, 100], 'SEKEUR': [9, 100]},\n    {'CHF': 5, 'SEK': 100}],\n   1003),\n  ('normal control 3',\n   [4194, 'EUR', 'EUR', 'card',\n    {'CHFEUR': [104, 100], 'EURCHF': [94, 100], 'EURSEK': [1147, 100], 'SEKEUR': [9, 100]},\n    {'CHF': 5, 'SEK': 100}],\n   4194),\n  ('normal control 4',\n   [1999, 'EUR', 'EUR', 'wallet',\n    {'CHFEUR': [104, 100], 'EURCHF': [94, 100], 'EURSEK': [1147, 100], 'SEKEUR': [9, 100]},\n    {'CHF': 5, 'SEK': 100}],\n   1999)],\n [('regression: cash step currency',\n   [1003, 'CHF', 'EUR', 'cash',\n    {'CHFEUR': [104, 100], 'EURCHF': [94, 100], 'EURSEK': [1147, 100], 'SEKEUR': [9, 100]},\n    {'CHF': 5, 'SEK': 100}],\n   1043),\n  ('partial repair probe: cash step currency',\n   [2502, 'EUR', 'EUR', 'cash',\n    {'CHFEUR': [104, 100], 'EURCHF': [94, 100], 'EURSEK': [1147, 100], 'SEKEUR': [9, 100]},\n    {'CHF': 5, 'SEK': 100}],\n   2502),\n  ('second regression',\n   [1003, 'EUR', 'SEK', 'cash',\n    {'CHFEUR': [104, 100], 'EURCHF': [94, 100], 'EURSEK': [1147, 100], 'SEKEUR': [9, 100]},\n    {'CHF': 5, 'SEK': 100}],\n   11500),\n  ('normal control 1',\n   [3395, 'EUR', 'SEK', 'wallet',\n    {'CHFEUR': [104, 100], 'EURCHF': [94, 100], 'EURSEK': [1147, 100], 'SEKEUR': [9, 100]},\n    {'CHF': 5, 'SEK': 100}],\n   38941),\n  ('normal control 2',\n   [2795, 'EUR', 'EUR', 'cash',\n    {'CHFEUR': [104, 100], 'EURCHF': [94, 100], 'EURSEK': [1147, 100], 'SEKEUR': [9, 100]},\n    {'CHF': 5, 'SEK': 100}],\n   2795),\n  ('normal control 3',\n   [1234, 'CHF', 'EUR', 'card',\n    {'CHFEUR': [104, 100], 'EURCHF': [94, 100], 'EURSEK': [1147, 100], 'SEKEUR': [9, 100]},\n    {'CHF': 5, 'SEK': 100}],\n   1283),\n  ('normal control 4',\n   [2502, 'SEK', 'SEK', 'cash',\n    {'CHFEUR': [104, 100], 'EURCHF': [94, 100], 'EURSEK': [1147, 100], 'SEKEUR': [9, 100]},\n    {'CHF': 5, 'SEK': 100}],\n   2500)],\n [('regression: cash step currency',\n   [2387, 'CHF', 'EUR', 'cash',\n    {'CHFEUR': [104, 100], 'EURCHF': [94, 100], 'EURSEK': [1147, 100], 'SEKEUR': [9, 100]},\n    {'CHF': 5, 'SEK': 100}],\n   2482),\n  ('partial repair probe: cash step currency',\n   [1003, 'CHF', 'EUR', 'cash',\n    {'CHFEUR': [104, 100], 'EURCHF': [94, 100], 'EURSEK': [1147, 100], 'SEKEUR': [9, 100]},\n    {'CHF': 5, 'SEK': 100}],\n   1043),\n  ('second regression',\n   [2017, 'EUR', 'SEK', 'cash',\n    {'CHFEUR': [104, 100], 'EURCHF': [94, 100], 'EURSEK': [1147, 100], 'SEKEUR': [9, 100]},\n    {'CHF': 5, 'SEK': 100}],\n   23100),\n  ('normal control 1',\n   [873, 'EUR', 'EUR', 'card',\n    {'CHFEUR': [104, 100], 'EURCHF': [94, 100], 'EURSEK': [1147, 100], 'SEKEUR': [9, 100]},\n    {'CHF': 5, 'SEK': 100}],\n   873),\n  ('normal control 2',\n   [1003, 'SEK', 'SEK', 'wallet',\n    {'CHFEUR': [104, 100], 'EURCHF': [94, 100], 'EURSEK': [1147, 100], 'SEKEUR': [9, 100]},\n    {'CHF': 5, 'SEK': 100}],\n   1003),\n  ('normal control 3',\n   [1003, 'EUR', 'EUR', 'wallet',\n    {'CHFEUR': [104, 100], 'EURCHF': [94, 100], 'EURSEK': [1147, 100], 'SEKEUR': [9, 100]},\n    {'CHF': 5, 'SEK': 100}],\n   1003),\n  ('normal control 4',\n   [1234, 'CHF', 'EUR', 'card',\n    {'CHFEUR': [104, 100], 'EURCHF': [94, 100], 'EURSEK': [1147, 100], 'SEKEUR': [9, 100]},\n    {'CHF': 5, 'SEK': 100}],\n   1283)],\n [('regression: cash step currency',\n   [2502, 'EUR', 'SEK', 'cash',\n    {'CHFEUR': [104, 100], 'EURCHF': [94, 100], 'EURSEK': [1147, 100], 'SEKEUR': [9, 100]},\n    {'CHF': 5, 'SEK': 100}],\n   28700),\n  ('partial repair probe: cash step currency',\n   [1234, 'CHF', 'EUR', 'cash',\n    {'CHFEUR': [104, 100], 'EURCHF': [94, 100], 'EURSEK': [1147, 100], 'SEKEUR': [9, 100]},\n    {'CHF': 5, 'SEK': 100}],\n   1283),\n  ('second regression',\n   [2502, 'SEK', 'EUR', 'cash',\n    {'CHFEUR': [104, 100], 'EURCHF': [94, 100], 'EURSEK': [1147, 100], 'SEKEUR': [9, 100]},\n    {'CHF': 5, 'SEK': 100}],\n   225),\n  ('normal control 1',\n   [2110, 'EUR', 'SEK', 'wallet',\n    {'CHFEUR': [104, 100], 'EURCHF': [94, 100], 'EURSEK': [1147, 100], 'SEKEUR': [9, 100]},\n    {'CHF': 5, 'SEK': 100}],\n   24202),\n  ('normal control 2',\n   [1999, 'CHF', 'EUR', 'card',\n    {'CHFEUR': [104, 100], 'EURCHF': [94, 100], 'EURSEK': [1147, 100], 'SEKEUR': [9, 100]},\n    {'CHF': 5, 'SEK': 100}],\n   2079),\n  ('normal control 3',\n   [1999, 'EUR', 'SEK', 'card',\n    {'CHFEUR': [104, 100], 'EURCHF': [94, 100], 'EURSEK': [1147, 100], 'SEKEUR': [9, 100]},\n    {'CHF': 5, 'SEK': 100}],\n   22929),\n  ('normal control 4',\n   [852, 'EUR', 'SEK', 'card',\n    {'CHFEUR': [104, 100], 'EURCHF': [94, 100], 'EURSEK': [1147, 100], 'SEKEUR': [9, 100]},\n    {'CHF': 5, 'SEK': 100}],\n   9772)],\n [('regression: cash step currency',\n   [2502, 'EUR', 'SEK', 'cash',\n    {'CHFEUR': [104, 100], 'EURCHF': [94, 100], 'EURSEK': [1147, 100], 'SEKEUR': [9, 100]},\n    {'CHF': 5, 'SEK': 100}],\n   28700),\n  ('partial repair probe: cash step currency',\n   [1234, 'EUR', 'EUR', 'cash',\n    {'CHFEUR': [104, 100], 'EURCHF': [94, 100], 'EURSEK': [1147, 100], 'SEKEUR': [9, 100]},\n    {'CHF': 5, 'SEK': 100}],\n   1234),\n  ('second regression',\n   [2502, 'EUR', 'EUR', 'cash',\n    {'CHFEUR': [104, 100], 'EURCHF': [94, 100], 'EURSEK': [1147, 100], 'SEKEUR': [9, 100]},\n    {'CHF': 5, 'SEK': 100}],\n   2502),\n  ('normal control 1',\n   [1234, 'EUR', 'EUR', 'wallet',\n    {'CHFEUR': [104, 100], 'EURCHF': [94, 100], 'EURSEK': [1147, 100], 'SEKEUR': [9, 100]},\n    {'CHF': 5, 'SEK': 100}],\n   1234),\n  ('normal control 2',\n   [1999, 'CHF', 'EUR', 'wallet',\n    {'CHFEUR': [104, 100], 'EURCHF': [94, 100], 'EURSEK': [1147, 100], 'SEKEUR': [9, 100]},\n    {'CHF': 5, 'SEK': 100}],\n   2079),\n  ('normal control 3',\n   [2203, 'EUR', 'EUR', 'wallet',\n    {'CHFEUR': [104, 100], 'EURCHF': [94, 100], 'EURSEK': [1147, 100], 'SEKEUR': [9, 100]},\n    {'CHF': 5, 'SEK': 100}],\n   2203),\n  ('normal control 4',\n   [1999, 'SEK', 'SEK', 'cash',\n    {'CHFEUR': [104, 100], 'EURCHF': [94, 100], 'EURSEK': [1147, 100], 'SEKEUR': [9, 100]},\n    {'CHF': 5, 'SEK': 100}],\n   2000)]]\nfor label, args, expected in fixtures[N-1]:\n    check(label, solve(*args), expected)\nprint(json.dumps({\"observations\": observations, \"passed\": all(x[\"passed\"] for x in observations)}, ensure_ascii=False))\nraise SystemExit(0 if all(x[\"passed\"] for x in observations) else 1)\n"},"fixed":{"sha256":"c9311d673be4d5b18c1212c4855a10e2cb463798419400a061b421a0926b3371","source":"\"\"\"Failure Map reference implementation. Python standard library only.\"\"\"\nimport json\n\nN = 1\nobservations = []\ndef solve(fare_cents, fare_ccy, pay_ccy, method, fx, cash_step):\n    amt = fare_cents\n    if pay_ccy != fare_ccy:\n        num, den = fx[fare_ccy + pay_ccy]\n        amt = (amt * num * 2 + den) // (2 * den)\n    if method == 'cash':\n        step = cash_step.get(pay_ccy, 1)\n        amt = (amt * 2 + step) // (2 * step) * step\n    return amt\ndef check(label, actual, expected):\n    observations.append({\"check\": label, \"actual\": actual, \"expected\": expected, \"passed\": actual == expected})\nfixtures = [[('regression: cash step currency',\n   [2502, 'SEK', 'EUR', 'cash',\n    {'CHFEUR': [104, 100], 'EURCHF': [94, 100], 'EURSEK': [1147, 100], 'SEKEUR': [9, 100]},\n    {'CHF': 5, 'SEK': 100}],\n   225),\n  ('partial repair probe: cash step currency',\n   [1234, 'EUR', 'EUR', 'cash',\n    {'CHFEUR': [104, 100], 'EURCHF': [94, 100], 'EURSEK': [1147, 100], 'SEKEUR': [9, 100]},\n    {'CHF': 5, 'SEK': 100}],\n   1234),\n  ('second regression',\n   [1003, 'SEK', 'EUR', 'cash',\n    {'CHFEUR': [104, 100], 'EURCHF': [94, 100], 'EURSEK': [1147, 100], 'SEKEUR': [9, 100]},\n    {'CHF': 5, 'SEK': 100}],\n   90),\n  ('normal control 1',\n   [1234, 'SEK', 'EUR', 'wallet',\n    {'CHFEUR': [104, 100], 'EURCHF': [94, 100], 'EURSEK': [1147, 100], 'SEKEUR': [9, 100]},\n    {'CHF': 5, 'SEK': 100}],\n   111),\n  ('normal control 2',\n   [1003, 'CHF', 'CHF', 'card',\n    {'CHFEUR': [104, 100], 'EURCHF': [94, 100], 'EURSEK': [1147, 100], 'SEKEUR': [9, 100]},\n    {'CHF': 5, 'SEK': 100}],\n   1003),\n  ('normal control 3',\n   [4194, 'EUR', 'EUR', 'card',\n    {'CHFEUR': [104, 100], 'EURCHF': [94, 100], 'EURSEK': [1147, 100], 'SEKEUR': [9, 100]},\n    {'CHF': 5, 'SEK': 100}],\n   4194),\n  ('normal control 4',\n   [1999, 'EUR', 'EUR', 'wallet',\n    {'CHFEUR': [104, 100], 'EURCHF': [94, 100], 'EURSEK': [1147, 100], 'SEKEUR': [9, 100]},\n    {'CHF': 5, 'SEK': 100}],\n   1999)],\n [('regression: cash step currency',\n   [1003, 'CHF', 'EUR', 'cash',\n    {'CHFEUR': [104, 100], 'EURCHF': [94, 100], 'EURSEK': [1147, 100], 'SEKEUR': [9, 100]},\n    {'CHF': 5, 'SEK': 100}],\n   1043),\n  ('partial repair probe: cash step currency',\n   [2502, 'EUR', 'EUR', 'cash',\n    {'CHFEUR': [104, 100], 'EURCHF': [94, 100], 'EURSEK': [1147, 100], 'SEKEUR': [9, 100]},\n    {'CHF': 5, 'SEK': 100}],\n   2502),\n  ('second regression',\n   [1003, 'EUR', 'SEK', 'cash',\n    {'CHFEUR': [104, 100], 'EURCHF': [94, 100], 'EURSEK': [1147, 100], 'SEKEUR': [9, 100]},\n    {'CHF': 5, 'SEK': 100}],\n   11500),\n  ('normal control 1',\n   [3395, 'EUR', 'SEK', 'wallet',\n    {'CHFEUR': [104, 100], 'EURCHF': [94, 100], 'EURSEK': [1147, 100], 'SEKEUR': [9, 100]},\n    {'CHF': 5, 'SEK': 100}],\n   38941),\n  ('normal control 2',\n   [2795, 'EUR', 'EUR', 'cash',\n    {'CHFEUR': [104, 100], 'EURCHF': [94, 100], 'EURSEK': [1147, 100], 'SEKEUR': [9, 100]},\n    {'CHF': 5, 'SEK': 100}],\n   2795),\n  ('normal control 3',\n   [1234, 'CHF', 'EUR', 'card',\n    {'CHFEUR': [104, 100], 'EURCHF': [94, 100], 'EURSEK': [1147, 100], 'SEKEUR': [9, 100]},\n    {'CHF': 5, 'SEK': 100}],\n   1283),\n  ('normal control 4',\n   [2502, 'SEK', 'SEK', 'cash',\n    {'CHFEUR': [104, 100], 'EURCHF': [94, 100], 'EURSEK': [1147, 100], 'SEKEUR': [9, 100]},\n    {'CHF': 5, 'SEK': 100}],\n   2500)],\n [('regression: cash step currency',\n   [2387, 'CHF', 'EUR', 'cash',\n    {'CHFEUR': [104, 100], 'EURCHF': [94, 100], 'EURSEK': [1147, 100], 'SEKEUR': [9, 100]},\n    {'CHF': 5, 'SEK': 100}],\n   2482),\n  ('partial repair probe: cash step currency',\n   [1003, 'CHF', 'EUR', 'cash',\n    {'CHFEUR': [104, 100], 'EURCHF': [94, 100], 'EURSEK': [1147, 100], 'SEKEUR': [9, 100]},\n    {'CHF': 5, 'SEK': 100}],\n   1043),\n  ('second regression',\n   [2017, 'EUR', 'SEK', 'cash',\n    {'CHFEUR': [104, 100], 'EURCHF': [94, 100], 'EURSEK': [1147, 100], 'SEKEUR': [9, 100]},\n    {'CHF': 5, 'SEK': 100}],\n   23100),\n  ('normal control 1',\n   [873, 'EUR', 'EUR', 'card',\n    {'CHFEUR': [104, 100], 'EURCHF': [94, 100], 'EURSEK': [1147, 100], 'SEKEUR': [9, 100]},\n    {'CHF': 5, 'SEK': 100}],\n   873),\n  ('normal control 2',\n   [1003, 'SEK', 'SEK', 'wallet',\n    {'CHFEUR': [104, 100], 'EURCHF': [94, 100], 'EURSEK': [1147, 100], 'SEKEUR': [9, 100]},\n    {'CHF': 5, 'SEK': 100}],\n   1003),\n  ('normal control 3',\n   [1003, 'EUR', 'EUR', 'wallet',\n    {'CHFEUR': [104, 100], 'EURCHF': [94, 100], 'EURSEK': [1147, 100], 'SEKEUR': [9, 100]},\n    {'CHF': 5, 'SEK': 100}],\n   1003),\n  ('normal control 4',\n   [1234, 'CHF', 'EUR', 'card',\n    {'CHFEUR': [104, 100], 'EURCHF': [94, 100], 'EURSEK': [1147, 100], 'SEKEUR': [9, 100]},\n    {'CHF': 5, 'SEK': 100}],\n   1283)],\n [('regression: cash step currency',\n   [2502, 'EUR', 'SEK', 'cash',\n    {'CHFEUR': [104, 100], 'EURCHF': [94, 100], 'EURSEK': [1147, 100], 'SEKEUR': [9, 100]},\n    {'CHF': 5, 'SEK': 100}],\n   28700),\n  ('partial repair probe: cash step currency',\n   [1234, 'CHF', 'EUR', 'cash',\n    {'CHFEUR': [104, 100], 'EURCHF': [94, 100], 'EURSEK': [1147, 100], 'SEKEUR': [9, 100]},\n    {'CHF': 5, 'SEK': 100}],\n   1283),\n  ('second regression',\n   [2502, 'SEK', 'EUR', 'cash',\n    {'CHFEUR': [104, 100], 'EURCHF': [94, 100], 'EURSEK': [1147, 100], 'SEKEUR': [9, 100]},\n    {'CHF': 5, 'SEK': 100}],\n   225),\n  ('normal control 1',\n   [2110, 'EUR', 'SEK', 'wallet',\n    {'CHFEUR': [104, 100], 'EURCHF': [94, 100], 'EURSEK': [1147, 100], 'SEKEUR': [9, 100]},\n    {'CHF': 5, 'SEK': 100}],\n   24202),\n  ('normal control 2',\n   [1999, 'CHF', 'EUR', 'card',\n    {'CHFEUR': [104, 100], 'EURCHF': [94, 100], 'EURSEK': [1147, 100], 'SEKEUR': [9, 100]},\n    {'CHF': 5, 'SEK': 100}],\n   2079),\n  ('normal control 3',\n   [1999, 'EUR', 'SEK', 'card',\n    {'CHFEUR': [104, 100], 'EURCHF': [94, 100], 'EURSEK': [1147, 100], 'SEKEUR': [9, 100]},\n    {'CHF': 5, 'SEK': 100}],\n   22929),\n  ('normal control 4',\n   [852, 'EUR', 'SEK', 'card',\n    {'CHFEUR': [104, 100], 'EURCHF': [94, 100], 'EURSEK': [1147, 100], 'SEKEUR': [9, 100]},\n    {'CHF': 5, 'SEK': 100}],\n   9772)],\n [('regression: cash step currency',\n   [2502, 'EUR', 'SEK', 'cash',\n    {'CHFEUR': [104, 100], 'EURCHF': [94, 100], 'EURSEK': [1147, 100], 'SEKEUR': [9, 100]},\n    {'CHF': 5, 'SEK': 100}],\n   28700),\n  ('partial repair probe: cash step currency',\n   [1234, 'EUR', 'EUR', 'cash',\n    {'CHFEUR': [104, 100], 'EURCHF': [94, 100], 'EURSEK': [1147, 100], 'SEKEUR': [9, 100]},\n    {'CHF': 5, 'SEK': 100}],\n   1234),\n  ('second regression',\n   [2502, 'EUR', 'EUR', 'cash',\n    {'CHFEUR': [104, 100], 'EURCHF': [94, 100], 'EURSEK': [1147, 100], 'SEKEUR': [9, 100]},\n    {'CHF': 5, 'SEK': 100}],\n   2502),\n  ('normal control 1',\n   [1234, 'EUR', 'EUR', 'wallet',\n    {'CHFEUR': [104, 100], 'EURCHF': [94, 100], 'EURSEK': [1147, 100], 'SEKEUR': [9, 100]},\n    {'CHF': 5, 'SEK': 100}],\n   1234),\n  ('normal control 2',\n   [1999, 'CHF', 'EUR', 'wallet',\n    {'CHFEUR': [104, 100], 'EURCHF': [94, 100], 'EURSEK': [1147, 100], 'SEKEUR': [9, 100]},\n    {'CHF': 5, 'SEK': 100}],\n   2079),\n  ('normal control 3',\n   [2203, 'EUR', 'EUR', 'wallet',\n    {'CHFEUR': [104, 100], 'EURCHF': [94, 100], 'EURSEK': [1147, 100], 'SEKEUR': [9, 100]},\n    {'CHF': 5, 'SEK': 100}],\n   2203),\n  ('normal control 4',\n   [1999, 'SEK', 'SEK', 'cash',\n    {'CHFEUR': [104, 100], 'EURCHF': [94, 100], 'EURSEK': [1147, 100], 'SEKEUR': [9, 100]},\n    {'CHF': 5, 'SEK': 100}],\n   2000)]]\nfor label, args, expected in fixtures[N-1]:\n    check(label, solve(*args), expected)\nprint(json.dumps({\"observations\": observations, \"passed\": all(x[\"passed\"] for x in observations)}, ensure_ascii=False))\nraise SystemExit(0 if all(x[\"passed\"] for x in observations) else 1)\n"}},"limitations":"A deterministic toy pricing contract stipulated for this example; it does not reproduce the pricing of any real ride-hailing operator or regulator. This reproducer isolates one failure mechanism. Results cover the supplied fixtures. Variants within a family share a test contract and should remain grouped when constructing evaluation splits. Related mechanisms with a shared evaluation_group must also remain together; these controlled models are not independent production incidents.","method":"Deterministic executable model with adversarial boundary fixtures.","provenance":{"created_by":"Failure Map","dependencies":"Python standard library","family":"w2-ride-hailing-fare-surge-cash-rounding-fx-cash-step-currency","generated_at":"2026-09-29T14:50:43.009905+00:00","license":"CC0-1.0","python":"3.12.14","seed":1,"split":"open-access"},"relevance":"Ride-hailing prices are computed per trip at scale; ordering, unit and boundary slips become systematic over- or under-charging.","repair":"Look up the cash step for the payment currency.","root_cause":"The cash step is looked up by the fare currency.","sha256":"2b6e350f34ac21ff30f84a2423850b86312b462cb10970fe785c166cdd5d8a78","title":"Cash step taken from the fare currency · case 01","variant":1,"variant_policy":"Five numbered records share a model and may reuse boundary fixtures.","verification":{"attempt":{"elapsed_ms":38.434,"exit_code":1,"observations":[{"actual":225,"check":"regression: cash step currency","expected":225,"passed":true},{"actual":1235,"check":"partial repair probe: cash step currency","expected":1234,"passed":false},{"actual":90,"check":"second regression","expected":90,"passed":true},{"actual":111,"check":"normal control 1","expected":111,"passed":true},{"actual":1003,"check":"normal control 2","expected":1003,"passed":true},{"actual":4194,"check":"normal control 3","expected":4194,"passed":true},{"actual":1999,"check":"normal control 4","expected":1999,"passed":true}],"passed":false,"stderr":"","stdout":"{\"observations\": [{\"check\": \"regression: cash step currency\", \"actual\": 225, \"expected\": 225, \"passed\": true}, {\"check\": \"partial repair probe: cash step currency\", \"actual\": 1235, \"expected\": 1234, \"passed\": false}, {\"check\": \"second regression\", \"actual\": 90, \"expected\": 90, \"passed\": true}, {\"check\": \"normal control 1\", \"actual\": 111, \"expected\": 111, \"passed\": true}, {\"check\": \"normal control 2\", \"actual\": 1003, \"expected\": 1003, \"passed\": true}, {\"check\": \"normal control 3\", \"actual\": 4194, \"expected\": 4194, \"passed\": true}, {\"check\": \"normal control 4\", \"actual\": 1999, \"expected\": 1999, \"passed\": true}], \"passed\": false}\n"},"broken":{"elapsed_ms":38.636,"exit_code":1,"observations":[{"actual":200,"check":"regression: cash step currency","expected":225,"passed":false},{"actual":1234,"check":"partial repair probe: cash step currency","expected":1234,"passed":true},{"actual":100,"check":"second regression","expected":90,"passed":false},{"actual":111,"check":"normal control 1","expected":111,"passed":true},{"actual":1003,"check":"normal control 2","expected":1003,"passed":true},{"actual":4194,"check":"normal control 3","expected":4194,"passed":true},{"actual":1999,"check":"normal control 4","expected":1999,"passed":true}],"passed":false,"stderr":"","stdout":"{\"observations\": [{\"check\": \"regression: cash step currency\", \"actual\": 200, \"expected\": 225, \"passed\": false}, {\"check\": \"partial repair probe: cash step currency\", \"actual\": 1234, \"expected\": 1234, \"passed\": true}, {\"check\": \"second regression\", \"actual\": 100, \"expected\": 90, \"passed\": false}, {\"check\": \"normal control 1\", \"actual\": 111, \"expected\": 111, \"passed\": true}, {\"check\": \"normal control 2\", \"actual\": 1003, \"expected\": 1003, \"passed\": true}, {\"check\": \"normal control 3\", \"actual\": 4194, \"expected\": 4194, \"passed\": true}, {\"check\": \"normal control 4\", \"actual\": 1999, \"expected\": 1999, \"passed\": true}], \"passed\": false}\n"},"fixed":{"elapsed_ms":39.342,"exit_code":0,"observations":[{"actual":225,"check":"regression: cash step currency","expected":225,"passed":true},{"actual":1234,"check":"partial repair probe: cash step currency","expected":1234,"passed":true},{"actual":90,"check":"second regression","expected":90,"passed":true},{"actual":111,"check":"normal control 1","expected":111,"passed":true},{"actual":1003,"check":"normal control 2","expected":1003,"passed":true},{"actual":4194,"check":"normal control 3","expected":4194,"passed":true},{"actual":1999,"check":"normal control 4","expected":1999,"passed":true}],"passed":true,"stderr":"","stdout":"{\"observations\": [{\"check\": \"regression: cash step currency\", \"actual\": 225, \"expected\": 225, \"passed\": true}, {\"check\": \"partial repair probe: cash step currency\", \"actual\": 1234, \"expected\": 1234, \"passed\": true}, {\"check\": \"second regression\", \"actual\": 90, \"expected\": 90, \"passed\": true}, {\"check\": \"normal control 1\", \"actual\": 111, \"expected\": 111, \"passed\": true}, {\"check\": \"normal control 2\", \"actual\": 1003, \"expected\": 1003, \"passed\": true}, {\"check\": \"normal control 3\", \"actual\": 4194, \"expected\": 4194, \"passed\": true}, {\"check\": \"normal control 4\", \"actual\": 1999, \"expected\": 1999, \"passed\": true}], \"passed\": true}\n"}},"verified":true,"visibility":"public"}