from flask import Flask, request, render_template_string, jsonify import re app = Flask(__name__) # taken from https://github.com/ilovecats4606/fx-82AU-PLUS-II-2nd/blob/main/tokentranslator.py (thanks ilovecats4606!) TOKEN_MAP = { 0x00: 'null', 0x01: 'mᴘ', 0x02: 'mn', 0x03: 'me', 0x04: 'm𝜇', 0x05: 'ao', 0x06: 'h', 0x07: '𝜇ɴ', 0x08: '𝜇ʙ', 0x09: 'ħ', 0x0A: 'α', 0x0B: 're', 0x0C: '𝜆c', 0x0D: 'γᴘ', 0x0E: 'γcp', 0x0F: '𝜆cn', 0x10: 'Σx²', 0x11: 'Σx', 0x12: 'n', 0x13: 'Σy²', 0x14: 'Σy', 0x15: 'Σxy', 0x16: 'Σy³', 0x17: '∑x²y', 0x18: '∑x⁴', 0x19: 'minX', 0x1A: 'maxX', 0x1B: 'minY', 0x1C: 'maxY', 0x1D: 'R∞', 0x1E: 'u', 0x1F: '𝜇ᴘ', 0x20: 'AtWt ', 0x21: '▯', 0x22: '𝜇e', 0x23: '𝜇n', 0x24: '𝜇𝜇', 0x25: '%', 0x26: 'F', 0x27: 'e', 0x28: '(', 0x29: ')', 0x2A: 'Nᴀ', 0x2B: '+', 0x2C: ',', 0x2D: '-', 0x2E: '.', 0x2F: '.+1', 0x30: '0', 0x31: '1', 0x32: '2', 0x33: '3', 0x34: '4', 0x35: '5', 0x36: '6', 0x37: '7', 0x38: '8', 0x39: '9', 0x3A: ':', 0x3B: 'k', 0x3C: '<', 0x3D: '=', 0x3E: '>', 0x3F: 'RndFix(', 0x40: 'Vm', 0x41: 'A', 0x42: 'B', 0x43: 'C', 0x44: 'D', 0x45: 'E', 0x46: 'F', 0x47: '->A', 0x48: '->B', 0x49: '->C', 0x4A: '->D', 0x4B: '->E', 0x4C: '->F', 0x4D: '->Y', 0x4E: '×', 0x4F: '÷', 0x50: 'h', 0x51: 'c', 0x52: 'o', 0x53: 'b', 0x54: 'M', 0x55: '▶a+b𝐢', 0x56: '▶r∠𝜃', 0x57: '!', 0x58: 'X', 0x59: 'Y', 0x5A: 'Ref(', 0x5B: 'Rref(', 0x5C: '▫', 0x5D: 'π(', 0x5E: '^( ', 0x5F: '÷R', 0x60: '(-)', 0x61: 'Not(', 0x62: 'Neg(', 0x63: 'Abs(', 0x64: 'x̂₁', 0x65: 'x̂', 0x66: 'ŷ', 0x67: 'x̂₂', 0x68: 'log(', 0x69: 'Σ(', 0x6A: '∫(', 0x6B: 'd/dx(', 0x6C: 'Pol(', 0x6D: 'Rec(', 0x6E: 'and', 0x6F: 'or', 0x70: 'sinh(', 0x71: 'cosh(', 0x72: 'tanh(', 0x73: '𝒆^(', 0x74: 'x10', 0x75: '^2', 0x76: '^3', 0x77: '^-1', 0x78: 'R', 0x79: 'c₀', 0x7A: 'c₁', 0x7B: 'Int(', 0x7C: '@', 0x7D: 'Intg(', 0x7E: 'xor', 0x7F: 'xnor', 0x80: '𝐢', 0x81: '𝒆', 0x82: 'π', 0x83: '->E', 0x84: '->F', 0x85: '°', 0x86: 'ʳ', 0x87: 'ᵍ', 0x88: 'Conjg(', 0x89: 'x̄', 0x8A: 'ȳ', 0x8B: 'Ans', 0x8C: 'Ran#', 0x8D: 'Q1', 0x8E: 'Q3', 0x8F: 'med', 0x90: 'sinh⁻¹(', 0x91: 'cosh⁻¹(', 0x92: 'tanh⁻¹(', 0x93: '10^(', 0x94: '≤', 0x95: '≠', 0x96: '≥', 0x97: '▶Simp ', 0x98: '√(', 0x99: 'M+', 0x9A: 'ᴀ', 0x9B: 'ʙ', 0x9C: 'ᴄ', 0x9D: 'r', 0x9E: '⋅', 0x9F: 'ˣ√(', 0xA0: 'sin(', 0xA1: 'cos(', 0xA2: 'tan(', 0xA3: 'ln(', 0xA4: '(', 0xA5: '▶Conv ', 0xA6: 'GCD(', 0xA7: 'LCM(', 0xA8: '³√(', 0xA9: 'M-', 0xAA: '𝜎x', 0xAB: 'sx', 0xAC: '𝜎y', 0xAD: 'sy', 0xAE: '⌟', 0xAF: '∠', 0xB0: 'sin⁻¹(', 0xB1: 'cos⁻¹(', 0xB2: 'tan⁻¹(', 0xB3: 'Rnd(', 0xB4: 'c₂', 0xB5: '𝜎', 0xB6: '𝜀₀', 0xB7: '𝜇₀', 0xB8: '𝗔', 0xB9: '𝗕', 0xBA: '𝗖', 0xBB: '𝗗', 0xBC: '𝗘', 0xBD: '𝗙', 0xBE: '𝗣', 0xBF: '𝗖', 0xC0: 'det(', 0xC1: 'Trn(', 0xC2: 'RanInt#(', 0xC3: 'arg(', 0xC4: '𝜙₀', 0xC5: 'g', 0xC6: 'G₀', 0xC7: 'Z₀', 0xC8: 'MatA', 0xC9: 'MatB', 0xCA: 'MatC', 0xCB: 'MatAns', 0xCC: 'VctA', 0xCD: 'VctB', 0xCE: 'VctC', 0xCF: 'VctAns', 0xD0: 'P(', 0xD1: 'Q(', 0xD2: 'R(', 0xD3: '▶t', 0xD4: 't', 0xD5: 'G', 0xD6: 'atm', 0xD7: 'in▶cm', 0xD8: 'cm▶in', 0xD9: 'ft▶m', 0xDA: 'm▶ft', 0xDB: 'yd▶m', 0xDC: 'm▶yd', 0xDD: 'mile▶km', 0xDE: 'km▶mile', 0xDF: 'n mile▶m', 0xE0: 'm▶n mile', 0xE1: 'acre▶m²', 0xE2: 'm²▶acre', 0xE3: 'gal(US)▶ℓ', 0xE4: 'ℓ▶gal(US)', 0xE5: 'gal(UK)▶ℓ', 0xE6: 'ℓ▶gal(UK)', 0xE7: 'pc▶km', 0xE8: 'km▶pc', 0xE9: 'km/h▶m/s', 0xEA: 'm/s▶km/h', 0xEB: 'oz▶g', 0xEC: 'g▶oz', 0xED: 'lb▶kg', 0xEE: 'kg▶lb', 0xEF: 'atm▶Pa', 0xF0: 'Pa▶atm', 0xF1: 'mmHg▶Pa', 0xF2: 'Pa▶mmHg', 0xF3: 'hp▶kW', 0xF4: 'kW▶hp', 0xF5: 'kgf/cm²▶Pa', 0xF6: 'Pa▶kgf/cm²', 0xF7: 'kgf⋅m▶J', 0xF8: 'J▶kgf⋅m', 0xF9: 'lbf/in²▶kPa', 0xFA: 'kPa▶lbf/in²', 0xFB: '°F▶°C', 0xFC: '°C▶°F', 0xFD: 'J▶cal', 0xFE: 'cal▶J', 0xFF: '@', } _unstable_ranges = [ (0x00, 0x24), (0x26, 0x2A), (0x2F, 0x2F), (0x3A, 0x3E), (0x40, 0x40), (0x47, 0x4D), (0x50, 0x53), (0x55, 0x56), (0x5A, 0x5B), (0x5D, 0x5F), (0x61, 0x67), (0x69, 0x6F), (0x77, 0x80), (0x83, 0x8A), (0x8D, 0x8E), (0x8F, 0x8F), (0x93, 0x97), (0x99, 0x9E), (0xA4, 0xA7), (0xA9, 0xAF), (0xB4, 0xC1), (0xC3, 0xFF), ] UNSTABLE_SET = set() for a, b in _unstable_ranges: for v in range(a, b + 1): UNSTABLE_SET.add(v) LAST_TYPEABLE_TOKEN = None for val, token in sorted(TOKEN_MAP.items()): if val not in UNSTABLE_SET and token != '': LAST_TYPEABLE_TOKEN = token def translate_hex_bytes(hex_bytes: list[int]): items = [] total = 0 typeable_count = 0 unstable_count = 0 unknown_count = 0 for val in hex_bytes: total += 1 tok = TOKEN_MAP.get(val, '') unstable = val in UNSTABLE_SET if unstable: unstable_count += 1 else: if tok != '': typeable_count += 1 else: unknown_count += 1 items.append({ 'hex': format(val, '02X'), 'token': tok, 'unstable': unstable, }) totals = { 'total': total, 'typeable_count': typeable_count, 'unstable_count': unstable_count, 'unknown_count': unknown_count } return {'items': items, 'totals': totals} def translate_line(line: str): line_hex = list(line.encode('UTF-8')) return translate_hex_bytes(line_hex) def create_hackstring(text: str): if len(text) >= 64: text = text[:64] else: text = text.ljust(64) __lines = [text[i:i+16] for i in range(0, 64, 16)] lines = [__lines[2], __lines[3], __lines[0], __lines[1]] items = [] totals = {'total': 0, 'typeable_count': 0, 'unstable_count': 0, 'unknown_count': 0} results = translate_line(lines[0]) items += results['items'] totals['total'] += results['totals']['total'] totals['typeable_count'] += results['totals']['typeable_count'] totals['unstable_count'] += results['totals']['unstable_count'] totals['unknown_count'] += results['totals']['unknown_count'] results = translate_hex_bytes([0x30]) items += results['items'] totals['total'] += results['totals']['total'] totals['typeable_count'] += results['totals']['typeable_count'] totals['unstable_count'] += results['totals']['unstable_count'] totals['unknown_count'] += results['totals']['unknown_count'] results = translate_line(lines[1]) items += results['items'] totals['total'] += results['totals']['total'] totals['typeable_count'] += results['totals']['typeable_count'] totals['unstable_count'] += results['totals']['unstable_count'] totals['unknown_count'] += results['totals']['unknown_count'] results = translate_hex_bytes([0x30]) items += results['items'] totals['total'] += results['totals']['total'] totals['typeable_count'] += results['totals']['typeable_count'] totals['unstable_count'] += results['totals']['unstable_count'] totals['unknown_count'] += results['totals']['unknown_count'] results = translate_line("3636363636") items += results['items'] totals['total'] += results['totals']['total'] totals['typeable_count'] += results['totals']['typeable_count'] totals['unstable_count'] += results['totals']['unstable_count'] totals['unknown_count'] += results['totals']['unknown_count'] results = translate_hex_bytes([0x3A, 0x31, 0x30, 0x30, 0x96, 0x81, 0x50, 0x30, 0x30, 0x30, 0x30, 0xC2, 0x30, 0x30]) items += results['items'] totals['total'] += results['totals']['total'] totals['typeable_count'] += results['totals']['typeable_count'] totals['unstable_count'] += results['totals']['unstable_count'] totals['unknown_count'] += results['totals']['unknown_count'] results = translate_line("36363636") items += results['items'] totals['total'] += results['totals']['total'] totals['typeable_count'] += results['totals']['typeable_count'] totals['unstable_count'] += results['totals']['unstable_count'] totals['unknown_count'] += results['totals']['unknown_count'] results = translate_line(lines[2]) items += results['items'] totals['total'] += results['totals']['total'] totals['typeable_count'] += results['totals']['typeable_count'] totals['unstable_count'] += results['totals']['unstable_count'] totals['unknown_count'] += results['totals']['unknown_count'] results = translate_hex_bytes([0x30]) items += results['items'] totals['total'] += results['totals']['total'] totals['typeable_count'] += results['totals']['typeable_count'] totals['unstable_count'] += results['totals']['unstable_count'] totals['unknown_count'] += results['totals']['unknown_count'] results = translate_line(lines[3]) items += results['items'] totals['total'] += results['totals']['total'] totals['typeable_count'] += results['totals']['typeable_count'] totals['unstable_count'] += results['totals']['unstable_count'] totals['unknown_count'] += results['totals']['unknown_count'] results = translate_hex_bytes([0x30]) items += results['items'] totals['total'] += results['totals']['total'] totals['typeable_count'] += results['totals']['typeable_count'] totals['unstable_count'] += results['totals']['unstable_count'] totals['unknown_count'] += results['totals']['unknown_count'] return {'items': items, 'totals': totals} HTML_TEMPLATE = """ fx-82AU Plus II 2nd Spelling Hackstring Generator

fx-82AU Plus II 2nd Spelling Hackstring Generator

{% if result %}

Hackstring (bytes):

Total bytes: {{ byte_count }}

Typeable characters: {{ typeable_count }}

Unstable needed: {{ unstable_count }}

Unknown characters: {{ unknown_count }}

{% endif %} """ @app.route('/', methods=['GET', 'POST']) def index(): result = None byte_count = 0 typeable_count = 0 unstable_count = 0 unknown_count = 0 if request.method == 'POST': input_text = request.form.get('text', '') if input_text: hack_data = create_hackstring(input_text) result = "" for item in hack_data['items']: result += f"{item['hex']} | {item['token']}" if item['unstable']: result += " (unstable)" result += "\n" byte_count = hack_data['totals']['total'] typeable_count = hack_data['totals']['typeable_count'] unstable_count = hack_data['totals']['unstable_count'] unknown_count = hack_data['totals']['unknown_count'] return render_template_string(HTML_TEMPLATE, result=result, byte_count=byte_count, typeable_count=typeable_count, unstable_count=unstable_count, unknown_count=unknown_count) if __name__ == '__main__': app.run(debug=True, port=5000)