summaryrefslogtreecommitdiff
path: root/spelling-generator.py
diff options
context:
space:
mode:
Diffstat (limited to 'spelling-generator.py')
-rw-r--r--spelling-generator.py487
1 files changed, 487 insertions, 0 deletions
diff --git a/spelling-generator.py b/spelling-generator.py
new file mode 100644
index 0000000..be8c801
--- /dev/null
+++ b/spelling-generator.py
@@ -0,0 +1,487 @@
+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 != '<UNK>':
+ 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, '<UNK>')
+ unstable = val in UNSTABLE_SET
+
+ if unstable:
+ unstable_count += 1
+ else:
+ if tok != '<UNK>':
+ 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 = """
+<!doctype html>
+<html>
+<head>
+ <title>fx-82AU Plus II 2nd Spelling Hackstring Generator</title>
+ <style>
+ body { font-family: monospace; margin: 40px; background: #0f0f0f; color: #eee; }
+ input, button { font-size: 16px; padding: 8px; }
+ textarea { width: 100%; max-width: 800px; height: 300px; font-family: monospace; background: #1e1e1e; color: #0f0; border: 1px solid #333; font-size: 16px; }
+ .output { margin-top: 20px; }
+ </style>
+</head>
+<body>
+ <h1>fx-82AU Plus II 2nd Spelling Hackstring Generator</h1>
+ <form method="post">
+ <input type="text" name="text" placeholder="Enter text (max 64 chars)" size="40" value="{{ request.form.get('text', '') }}">
+ <button type="submit">Generate Hackstring</button>
+ </form>
+ {% if result %}
+ <div class="output">
+ <h3>Hackstring (bytes):</h3>
+ <textarea readonly>{{ result }}</textarea>
+ <p><strong>Total bytes:</strong> {{ byte_count }}</p>
+ <p><strong>Typeable characters:</strong> {{ typeable_count }}</p>
+ <p><strong>Unstable needed:</strong> {{ unstable_count }}</p>
+ <p><strong>Unknown characters:</strong> {{ unknown_count }}</p>
+ </div>
+ {% endif %}
+</body>
+</html>
+"""
+
[email protected]('/', 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)