{"abstract":"\"+150\" is read as a 150.00 decimal price, or empty input crashes.","category":"Betting odds conversion","checks":10,"contract":"Normalise user-typed odds to a decimal price string with two decimals (half up). Detection order: text containing \"/\" is fractional a/b; text starting with \"+\" or \"-\" is American (magnitude >= 100); an unsigned integer >= 100 is a positive American line; anything else is a decimal price, where a comma is the decimal separator (\"2,50\"). Unparseable input, zero denominators, magnitudes below 100 and results not above 1 return \"invalid\".","evaluation_group":"w2-odds-conversion-odds-format-autodetect","failed_approach":"Indexing the first character crashes on empty input.","family":"w2-odds-conversion-odds-format-autodetect-plus-sign-detection","id":"FA-84686","implementations":{"attempt":{"sha256":"993959a7ec9fa4a515520a42b99985ca1fea52f1596f7169fb7ff893ac17a3a3","source":"\"\"\"Failure Map reference implementation. Python standard library only.\"\"\"\nimport json\nfrom fractions import Fraction\nimport math\nN = 1\nobservations = []\ndef solve(text):\n    t = text.strip()\n    try:\n        if '/' in t:\n            a, b = t.split('/')\n            dec = 1 + Fraction(int(a), int(b))\n        elif t[0] in '+-':\n            n = int(t[1:])\n            if n < 100:\n                return 'invalid'\n            dec = 1 + (Fraction(n, 100) if t[0] == '+' else Fraction(100, n))\n        elif t.isdigit() and int(t) >= 100:\n            dec = 1 + Fraction(int(t), 100)\n        else:\n            dec = Fraction(t.replace(',', '.'))\n    except (ValueError, ZeroDivisionError):\n        return 'invalid'\n    if dec <= 1:\n        return 'invalid'\n    c = math.floor(dec * 100 + Fraction(1, 2))\n    return '%d.%02d' % (c // 100, c % 100)\ndef check(label, actual, expected):\n    observations.append({\"check\": label, \"actual\": actual, \"expected\": expected, \"passed\": actual == expected})\ndef run(args):\n    try:\n        return solve(*args)\n    except Exception as exc:\n        return 'raised ' + type(exc).__name__\ncases = [[('control fractional', ('5/2',), '3.50'),\n  ('control negative american', ('-110',), '1.91'),\n  ('boundary unsigned hundred', ('100',), '2.00'),\n  ('boundary small integer is decimal', ('3',), '3.00'),\n  ('boundary decimal comma', ('2,50',), '2.50'),\n  ('control empty input', ('',), 'invalid'),\n  ('regression: plus sign detection', ('+487',), '5.87'),\n  ('regression: plus sign detection', ('',), 'invalid'),\n  ('variant scenario 1', ('3,36',), '3.36'),\n  ('variant scenario 2', ('3/1',), '4.00')],\n [('control fractional', ('5/2',), '3.50'),\n  ('control negative american', ('-110',), '1.91'),\n  ('boundary unsigned hundred', ('100',), '2.00'),\n  ('boundary small integer is decimal', ('3',), '3.00'),\n  ('boundary decimal comma', ('2,50',), '2.50'),\n  ('control empty input', ('',), 'invalid'),\n  ('regression: plus sign detection', ('+319',), '4.19'),\n  ('regression: plus sign detection', ('',), 'invalid'),\n  ('variant scenario 1', ('-595',), '1.17'),\n  ('variant scenario 2', ('13/2',), '7.50')],\n [('control fractional', ('5/2',), '3.50'),\n  ('control negative american', ('-110',), '1.91'),\n  ('boundary unsigned hundred', ('100',), '2.00'),\n  ('boundary small integer is decimal', ('3',), '3.00'),\n  ('boundary decimal comma', ('2,50',), '2.50'),\n  ('control empty input', ('',), 'invalid'),\n  ('regression: plus sign detection', ('',), 'invalid'),\n  ('regression: plus sign detection', ('+100',), '2.00'),\n  ('variant scenario 1', ('3,07',), '3.07'),\n  ('variant scenario 2', ('256',), '3.56')],\n [('control fractional', ('5/2',), '3.50'),\n  ('control negative american', ('-110',), '1.91'),\n  ('boundary unsigned hundred', ('100',), '2.00'),\n  ('boundary small integer is decimal', ('3',), '3.00'),\n  ('boundary decimal comma', ('2,50',), '2.50'),\n  ('control empty input', ('',), 'invalid'),\n  ('regression: plus sign detection', ('+150',), '2.50'),\n  ('regression: plus sign detection', ('',), 'invalid'),\n  ('variant scenario 1', ('1.84',), '1.84'),\n  ('variant scenario 2', ('6,57',), '6.57')],\n [('control fractional', ('5/2',), '3.50'),\n  ('control negative american', ('-110',), '1.91'),\n  ('boundary unsigned hundred', ('100',), '2.00'),\n  ('boundary small integer is decimal', ('3',), '3.00'),\n  ('boundary decimal comma', ('2,50',), '2.50'),\n  ('control empty input', ('',), 'invalid'),\n  ('regression: plus sign detection', ('+553',), '6.53'),\n  ('regression: plus sign detection', ('',), 'invalid'),\n  ('variant scenario 1', ('-513',), '1.19'),\n  ('variant scenario 2', ('191',), '2.91')]]\nfor label, args, expected in cases[N - 1]:\n    check(label, run(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":"65e7c81a562b960bbe3134a15718508715be9a7c245d74fd35c5d712b929c0c5","source":"\"\"\"Failure Map reference implementation. Python standard library only.\"\"\"\nimport json\nfrom fractions import Fraction\nimport math\nN = 1\nobservations = []\ndef solve(text):\n    t = text.strip()\n    try:\n        if '/' in t:\n            a, b = t.split('/')\n            dec = 1 + Fraction(int(a), int(b))\n        elif t[:1] == '-':\n            n = int(t[1:])\n            if n < 100:\n                return 'invalid'\n            dec = 1 + (Fraction(n, 100) if t[0] == '+' else Fraction(100, n))\n        elif t.isdigit() and int(t) >= 100:\n            dec = 1 + Fraction(int(t), 100)\n        else:\n            dec = Fraction(t.replace(',', '.'))\n    except (ValueError, ZeroDivisionError):\n        return 'invalid'\n    if dec <= 1:\n        return 'invalid'\n    c = math.floor(dec * 100 + Fraction(1, 2))\n    return '%d.%02d' % (c // 100, c % 100)\ndef check(label, actual, expected):\n    observations.append({\"check\": label, \"actual\": actual, \"expected\": expected, \"passed\": actual == expected})\ndef run(args):\n    try:\n        return solve(*args)\n    except Exception as exc:\n        return 'raised ' + type(exc).__name__\ncases = [[('control fractional', ('5/2',), '3.50'),\n  ('control negative american', ('-110',), '1.91'),\n  ('boundary unsigned hundred', ('100',), '2.00'),\n  ('boundary small integer is decimal', ('3',), '3.00'),\n  ('boundary decimal comma', ('2,50',), '2.50'),\n  ('control empty input', ('',), 'invalid'),\n  ('regression: plus sign detection', ('+487',), '5.87'),\n  ('regression: plus sign detection', ('',), 'invalid'),\n  ('variant scenario 1', ('3,36',), '3.36'),\n  ('variant scenario 2', ('3/1',), '4.00')],\n [('control fractional', ('5/2',), '3.50'),\n  ('control negative american', ('-110',), '1.91'),\n  ('boundary unsigned hundred', ('100',), '2.00'),\n  ('boundary small integer is decimal', ('3',), '3.00'),\n  ('boundary decimal comma', ('2,50',), '2.50'),\n  ('control empty input', ('',), 'invalid'),\n  ('regression: plus sign detection', ('+319',), '4.19'),\n  ('regression: plus sign detection', ('',), 'invalid'),\n  ('variant scenario 1', ('-595',), '1.17'),\n  ('variant scenario 2', ('13/2',), '7.50')],\n [('control fractional', ('5/2',), '3.50'),\n  ('control negative american', ('-110',), '1.91'),\n  ('boundary unsigned hundred', ('100',), '2.00'),\n  ('boundary small integer is decimal', ('3',), '3.00'),\n  ('boundary decimal comma', ('2,50',), '2.50'),\n  ('control empty input', ('',), 'invalid'),\n  ('regression: plus sign detection', ('',), 'invalid'),\n  ('regression: plus sign detection', ('+100',), '2.00'),\n  ('variant scenario 1', ('3,07',), '3.07'),\n  ('variant scenario 2', ('256',), '3.56')],\n [('control fractional', ('5/2',), '3.50'),\n  ('control negative american', ('-110',), '1.91'),\n  ('boundary unsigned hundred', ('100',), '2.00'),\n  ('boundary small integer is decimal', ('3',), '3.00'),\n  ('boundary decimal comma', ('2,50',), '2.50'),\n  ('control empty input', ('',), 'invalid'),\n  ('regression: plus sign detection', ('+150',), '2.50'),\n  ('regression: plus sign detection', ('',), 'invalid'),\n  ('variant scenario 1', ('1.84',), '1.84'),\n  ('variant scenario 2', ('6,57',), '6.57')],\n [('control fractional', ('5/2',), '3.50'),\n  ('control negative american', ('-110',), '1.91'),\n  ('boundary unsigned hundred', ('100',), '2.00'),\n  ('boundary small integer is decimal', ('3',), '3.00'),\n  ('boundary decimal comma', ('2,50',), '2.50'),\n  ('control empty input', ('',), 'invalid'),\n  ('regression: plus sign detection', ('+553',), '6.53'),\n  ('regression: plus sign detection', ('',), 'invalid'),\n  ('variant scenario 1', ('-513',), '1.19'),\n  ('variant scenario 2', ('191',), '2.91')]]\nfor label, args, expected in cases[N - 1]:\n    check(label, run(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":"fc7786f59e1cd476e8265c4754aeb95b3451bcbb655a88b1321284d9e056dbf2","source":"\"\"\"Failure Map reference implementation. Python standard library only.\"\"\"\nimport json\nfrom fractions import Fraction\nimport math\nN = 1\nobservations = []\ndef solve(text):\n    t = text.strip()\n    try:\n        if '/' in t:\n            a, b = t.split('/')\n            dec = 1 + Fraction(int(a), int(b))\n        elif t[:1] in ('+', '-'):\n            n = int(t[1:])\n            if n < 100:\n                return 'invalid'\n            dec = 1 + (Fraction(n, 100) if t[0] == '+' else Fraction(100, n))\n        elif t.isdigit() and int(t) >= 100:\n            dec = 1 + Fraction(int(t), 100)\n        else:\n            dec = Fraction(t.replace(',', '.'))\n    except (ValueError, ZeroDivisionError):\n        return 'invalid'\n    if dec <= 1:\n        return 'invalid'\n    c = math.floor(dec * 100 + Fraction(1, 2))\n    return '%d.%02d' % (c // 100, c % 100)\ndef check(label, actual, expected):\n    observations.append({\"check\": label, \"actual\": actual, \"expected\": expected, \"passed\": actual == expected})\ndef run(args):\n    try:\n        return solve(*args)\n    except Exception as exc:\n        return 'raised ' + type(exc).__name__\ncases = [[('control fractional', ('5/2',), '3.50'),\n  ('control negative american', ('-110',), '1.91'),\n  ('boundary unsigned hundred', ('100',), '2.00'),\n  ('boundary small integer is decimal', ('3',), '3.00'),\n  ('boundary decimal comma', ('2,50',), '2.50'),\n  ('control empty input', ('',), 'invalid'),\n  ('regression: plus sign detection', ('+487',), '5.87'),\n  ('regression: plus sign detection', ('',), 'invalid'),\n  ('variant scenario 1', ('3,36',), '3.36'),\n  ('variant scenario 2', ('3/1',), '4.00')],\n [('control fractional', ('5/2',), '3.50'),\n  ('control negative american', ('-110',), '1.91'),\n  ('boundary unsigned hundred', ('100',), '2.00'),\n  ('boundary small integer is decimal', ('3',), '3.00'),\n  ('boundary decimal comma', ('2,50',), '2.50'),\n  ('control empty input', ('',), 'invalid'),\n  ('regression: plus sign detection', ('+319',), '4.19'),\n  ('regression: plus sign detection', ('',), 'invalid'),\n  ('variant scenario 1', ('-595',), '1.17'),\n  ('variant scenario 2', ('13/2',), '7.50')],\n [('control fractional', ('5/2',), '3.50'),\n  ('control negative american', ('-110',), '1.91'),\n  ('boundary unsigned hundred', ('100',), '2.00'),\n  ('boundary small integer is decimal', ('3',), '3.00'),\n  ('boundary decimal comma', ('2,50',), '2.50'),\n  ('control empty input', ('',), 'invalid'),\n  ('regression: plus sign detection', ('',), 'invalid'),\n  ('regression: plus sign detection', ('+100',), '2.00'),\n  ('variant scenario 1', ('3,07',), '3.07'),\n  ('variant scenario 2', ('256',), '3.56')],\n [('control fractional', ('5/2',), '3.50'),\n  ('control negative american', ('-110',), '1.91'),\n  ('boundary unsigned hundred', ('100',), '2.00'),\n  ('boundary small integer is decimal', ('3',), '3.00'),\n  ('boundary decimal comma', ('2,50',), '2.50'),\n  ('control empty input', ('',), 'invalid'),\n  ('regression: plus sign detection', ('+150',), '2.50'),\n  ('regression: plus sign detection', ('',), 'invalid'),\n  ('variant scenario 1', ('1.84',), '1.84'),\n  ('variant scenario 2', ('6,57',), '6.57')],\n [('control fractional', ('5/2',), '3.50'),\n  ('control negative american', ('-110',), '1.91'),\n  ('boundary unsigned hundred', ('100',), '2.00'),\n  ('boundary small integer is decimal', ('3',), '3.00'),\n  ('boundary decimal comma', ('2,50',), '2.50'),\n  ('control empty input', ('',), 'invalid'),\n  ('regression: plus sign detection', ('+553',), '6.53'),\n  ('regression: plus sign detection', ('',), 'invalid'),\n  ('variant scenario 1', ('-513',), '1.19'),\n  ('variant scenario 2', ('191',), '2.91')]]\nfor label, args, expected in cases[N - 1]:\n    check(label, run(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":"Stipulated, bounded toy contract stated in the contract field; not a claim of conformance with any operator, exchange or regulator rule set. 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-odds-conversion-odds-format-autodetect-plus-sign-detection","generated_at":"2026-09-29T14:50:33.304488+00:00","license":"CC0-1.0","python":"3.12.14","seed":1,"split":"open-access"},"relevance":"Bet-slip inputs accept several odds formats and must not misclassify ambiguous text.","repair":"Treat a leading + or - as American and keep empty input invalid.","root_cause":"Only a leading minus sign selects the American branch.","sha256":"43a91961fac70e4d814d27a5a0107d3e98219530c2538c976cc9da74fb8b9383","title":"Explicit plus-sign American lines parsed as decimals · case 01","variant":1,"variant_policy":"Five numbered records share a model and may reuse boundary fixtures.","verification":{"attempt":{"elapsed_ms":42.86,"exit_code":1,"observations":[{"actual":"3.50","check":"control fractional","expected":"3.50","passed":true},{"actual":"1.91","check":"control negative american","expected":"1.91","passed":true},{"actual":"2.00","check":"boundary unsigned hundred","expected":"2.00","passed":true},{"actual":"3.00","check":"boundary small integer is decimal","expected":"3.00","passed":true},{"actual":"2.50","check":"boundary decimal comma","expected":"2.50","passed":true},{"actual":"raised IndexError","check":"control empty input","expected":"invalid","passed":false},{"actual":"5.87","check":"regression: plus sign detection","expected":"5.87","passed":true},{"actual":"raised IndexError","check":"regression: plus sign detection","expected":"invalid","passed":false},{"actual":"3.36","check":"variant scenario 1","expected":"3.36","passed":true},{"actual":"4.00","check":"variant scenario 2","expected":"4.00","passed":true}],"passed":false,"stderr":"","stdout":"{\"observations\": [{\"check\": \"control fractional\", \"actual\": \"3.50\", \"expected\": \"3.50\", \"passed\": true}, {\"check\": \"control negative american\", \"actual\": \"1.91\", \"expected\": \"1.91\", \"passed\": true}, {\"check\": \"boundary unsigned hundred\", \"actual\": \"2.00\", \"expected\": \"2.00\", \"passed\": true}, {\"check\": \"boundary small integer is decimal\", \"actual\": \"3.00\", \"expected\": \"3.00\", \"passed\": true}, {\"check\": \"boundary decimal comma\", \"actual\": \"2.50\", \"expected\": \"2.50\", \"passed\": true}, {\"check\": \"control empty input\", \"actual\": \"raised IndexError\", \"expected\": \"invalid\", \"passed\": false}, {\"check\": \"regression: plus sign detection\", \"actual\": \"5.87\", \"expected\": \"5.87\", \"passed\": true}, {\"check\": \"regression: plus sign detection\", \"actual\": \"raised IndexError\", \"expected\": \"invalid\", \"passed\": false}, {\"check\": \"variant scenario 1\", \"actual\": \"3.36\", \"expected\": \"3.36\", \"passed\": true}, {\"check\": \"variant scenario 2\", \"actual\": \"4.00\", \"expected\": \"4.00\", \"passed\": true}], \"passed\": false}\n"},"broken":{"elapsed_ms":42.819,"exit_code":1,"observations":[{"actual":"3.50","check":"control fractional","expected":"3.50","passed":true},{"actual":"1.91","check":"control negative american","expected":"1.91","passed":true},{"actual":"2.00","check":"boundary unsigned hundred","expected":"2.00","passed":true},{"actual":"3.00","check":"boundary small integer is decimal","expected":"3.00","passed":true},{"actual":"2.50","check":"boundary decimal comma","expected":"2.50","passed":true},{"actual":"invalid","check":"control empty input","expected":"invalid","passed":true},{"actual":"487.00","check":"regression: plus sign detection","expected":"5.87","passed":false},{"actual":"invalid","check":"regression: plus sign detection","expected":"invalid","passed":true},{"actual":"3.36","check":"variant scenario 1","expected":"3.36","passed":true},{"actual":"4.00","check":"variant scenario 2","expected":"4.00","passed":true}],"passed":false,"stderr":"","stdout":"{\"observations\": [{\"check\": \"control fractional\", \"actual\": \"3.50\", \"expected\": \"3.50\", \"passed\": true}, {\"check\": \"control negative american\", \"actual\": \"1.91\", \"expected\": \"1.91\", \"passed\": true}, {\"check\": \"boundary unsigned hundred\", \"actual\": \"2.00\", \"expected\": \"2.00\", \"passed\": true}, {\"check\": \"boundary small integer is decimal\", \"actual\": \"3.00\", \"expected\": \"3.00\", \"passed\": true}, {\"check\": \"boundary decimal comma\", \"actual\": \"2.50\", \"expected\": \"2.50\", \"passed\": true}, {\"check\": \"control empty input\", \"actual\": \"invalid\", \"expected\": \"invalid\", \"passed\": true}, {\"check\": \"regression: plus sign detection\", \"actual\": \"487.00\", \"expected\": \"5.87\", \"passed\": false}, {\"check\": \"regression: plus sign detection\", \"actual\": \"invalid\", \"expected\": \"invalid\", \"passed\": true}, {\"check\": \"variant scenario 1\", \"actual\": \"3.36\", \"expected\": \"3.36\", \"passed\": true}, {\"check\": \"variant scenario 2\", \"actual\": \"4.00\", \"expected\": \"4.00\", \"passed\": true}], \"passed\": false}\n"},"fixed":{"elapsed_ms":44.905,"exit_code":0,"observations":[{"actual":"3.50","check":"control fractional","expected":"3.50","passed":true},{"actual":"1.91","check":"control negative american","expected":"1.91","passed":true},{"actual":"2.00","check":"boundary unsigned hundred","expected":"2.00","passed":true},{"actual":"3.00","check":"boundary small integer is decimal","expected":"3.00","passed":true},{"actual":"2.50","check":"boundary decimal comma","expected":"2.50","passed":true},{"actual":"invalid","check":"control empty input","expected":"invalid","passed":true},{"actual":"5.87","check":"regression: plus sign detection","expected":"5.87","passed":true},{"actual":"invalid","check":"regression: plus sign detection","expected":"invalid","passed":true},{"actual":"3.36","check":"variant scenario 1","expected":"3.36","passed":true},{"actual":"4.00","check":"variant scenario 2","expected":"4.00","passed":true}],"passed":true,"stderr":"","stdout":"{\"observations\": [{\"check\": \"control fractional\", \"actual\": \"3.50\", \"expected\": \"3.50\", \"passed\": true}, {\"check\": \"control negative american\", \"actual\": \"1.91\", \"expected\": \"1.91\", \"passed\": true}, {\"check\": \"boundary unsigned hundred\", \"actual\": \"2.00\", \"expected\": \"2.00\", \"passed\": true}, {\"check\": \"boundary small integer is decimal\", \"actual\": \"3.00\", \"expected\": \"3.00\", \"passed\": true}, {\"check\": \"boundary decimal comma\", \"actual\": \"2.50\", \"expected\": \"2.50\", \"passed\": true}, {\"check\": \"control empty input\", \"actual\": \"invalid\", \"expected\": \"invalid\", \"passed\": true}, {\"check\": \"regression: plus sign detection\", \"actual\": \"5.87\", \"expected\": \"5.87\", \"passed\": true}, {\"check\": \"regression: plus sign detection\", \"actual\": \"invalid\", \"expected\": \"invalid\", \"passed\": true}, {\"check\": \"variant scenario 1\", \"actual\": \"3.36\", \"expected\": \"3.36\", \"passed\": true}, {\"check\": \"variant scenario 2\", \"actual\": \"4.00\", \"expected\": \"4.00\", \"passed\": true}], \"passed\": true}\n"}},"verified":true,"visibility":"public"}