{"lib/package.json": "{\n  \"name\": \"sic1asm\",\n  \"version\": \"0.0.1\",\n  \"description\": \"Single Instruction Computer, Mark 1 (SIC-1) assembler and emulator\",\n  \"main\": \"sic1asm.js\",\n  \"scripts\": {\n    \"test\": \"mocha --require ts-node/register test/*.spec.ts\",\n    \"watch:test\": \"npx mocha --watch --require ts-node/register test/*.spec.ts --watch --watch-extensions ts\",\n    \"build\": \"copy /y package.json dist && tsc -p .\",\n    \"watch\": \"tsc -w -p .\"\n  },\n  \"author\": {\n    \"name\": \"Jared Krinke\"\n  },\n  \"devDependencies\": {\n    \"@types/mocha\": \"^5.2.7\",\n    \"@types/node\": \"^13.1.8\",\n    \"mocha\": \"6\",\n    \"ts-node\": \"^8.6.2\",\n    \"typescript\": \"^3.7.5\"\n  },\n  \"files\": [\n    \"sic1asm.js\",\n    \"sic1asm.d.ts\"\n  ]\n}\n", "lib/tsconfig.json": "{\n    \"compilerOptions\": {\n        \"module\": \"commonjs\",\n        \"target\": \"ES2017\",\n        \"esModuleInterop\": true,\n        \"strict\": true,\n        \"outDir\": \"dist\",\n        \"declaration\": true\n    },\n    \"files\": [\n        \"src/sic1asm.ts\"\n    ]\n}", "lib/test/sic1asm.spec.ts": "import \"mocha\";\nimport * as assert from \"assert\";\nimport * as sic1 from \"../src/sic1asm\";\nconst { Tokenizer, TokenType, Assembler, Emulator, CompilationError, Constants } = sic1;\n\ndescribe(\"SIC-1 Assembler\", () => {\n    describe(\"Tokenizer\", () => {\n        it(\"Empty line\", () => {\n            assert.deepStrictEqual(Tokenizer.tokenizeLine(\"\"), []);\n        });\n\n        it(\"White space\", () => {\n            assert.deepStrictEqual(Tokenizer.tokenizeLine(\"   \"), [\n                { tokenType: TokenType.whiteSpace, raw: \"   \" },\n            ]);\n        });\n\n        it(\"Instruction\", () => {\n            assert.deepStrictEqual(Tokenizer.tokenizeLine(\"subleq 0, @one, @two+3\"), [\n                { tokenType: TokenType.command, raw: \"subleq\" },\n                { tokenType: TokenType.whiteSpace, raw: \" \" },\n                { tokenType: TokenType.numberLiteral, raw: \"0\" },\n                { tokenType: TokenType.comma, raw: \",\" },\n                { tokenType: TokenType.whiteSpace, raw: \" \" },\n                { tokenType: TokenType.reference, raw: \"@one\", groups: { name: \"one\" } },\n                { tokenType: TokenType.comma, raw: \",\" },\n                { tokenType: TokenType.whiteSpace, raw: \" \" },\n                { tokenType: TokenType.reference, raw: \"@two+3\", groups: { name: \"two\", offset: \"+3\" } },\n            ]);\n        });\n\n        it(\"Instruction with breakpoint\", () => {\n            assert.deepStrictEqual(Tokenizer.tokenizeLine(\"!subleq 0, @one, @two+3\"), [\n                { tokenType: TokenType.exclamationMark, raw: \"!\" },\n                { tokenType: TokenType.command, raw: \"subleq\" },\n                { tokenType: TokenType.whiteSpace, raw: \" \" },\n                { tokenType: TokenType.numberLiteral, raw: \"0\" },\n                { tokenType: TokenType.comma, raw: \",\" },\n                { tokenType: TokenType.whiteSpace, raw: \" \" },\n                { tokenType: TokenType.reference, raw: \"@one\", groups: { name: \"one\" } },\n                { tokenType: TokenType.comma, raw: \",\" },\n                { tokenType: TokenType.whiteSpace, raw: \" \" },\n                { tokenType: TokenType.reference, raw: \"@two+3\", groups: { name: \"two\", offset: \"+3\" } },\n            ]);\n        });\n\n        it(\"Variable\", () => {\n            assert.deepStrictEqual(Tokenizer.tokenizeLine(\"@var: .data 7; Comment\"), [\n                { tokenType: TokenType.label, raw: \"@var:\", groups: { name: \"var\" } },\n                { tokenType: TokenType.whiteSpace, raw: \" \" },\n                { tokenType: TokenType.command, raw: \".data\" },\n                { tokenType: TokenType.whiteSpace, raw: \" \" },\n                { tokenType: TokenType.numberLiteral, raw: \"7\" },\n            ]);\n        });\n\n        it(\"Variable with number label\", () => {\n            assert.deepStrictEqual(Tokenizer.tokenizeLine(\"@0:.data 7; Comment\"), [\n                { tokenType: TokenType.label, raw: \"@0:\", groups: { name: \"0\" } },\n                { tokenType: TokenType.command, raw: \".data\" },\n                { tokenType: TokenType.whiteSpace, raw: \" \" },\n                { tokenType: TokenType.numberLiteral, raw: \"7\" },\n            ]);\n        });\n\n        it(\"Variable with non-BMP label\", () => {\n            assert.deepStrictEqual(Tokenizer.tokenizeLine(\"@🜂:.data 7; Comment\"), [\n                { tokenType: TokenType.label, raw: \"@🜂:\", groups: { name: \"🜂\" } },\n                { tokenType: TokenType.command, raw: \".data\" },\n                { tokenType: TokenType.whiteSpace, raw: \" \" },\n                { tokenType: TokenType.numberLiteral, raw: \"7\" },\n            ]);\n        });\n\n        it(\"Character\", () => {\n            assert.deepStrictEqual(Tokenizer.tokenizeLine(\".data 'H'\"), [\n                { tokenType: TokenType.command, raw: \".data\" },\n                { tokenType: TokenType.whiteSpace, raw: \" \" },\n                { tokenType: TokenType.characterLiteral, raw: \"'H'\", groups: { character: \"H\" } },\n            ]);\n        });\n\n        it(\"Character (negated)\", () => {\n            assert.deepStrictEqual(Tokenizer.tokenizeLine(\".data -'H'\"), [\n                { tokenType: TokenType.command, raw: \".data\" },\n                { tokenType: TokenType.whiteSpace, raw: \" \" },\n                { tokenType: TokenType.characterLiteral, raw: \"-'H'\", groups: { character: \"H\" } },\n            ]);\n        });\n\n        it(\"Escaped character\", () => {\n            assert.deepStrictEqual(Tokenizer.tokenizeLine(\".data '\\\\n'\"), [\n                { tokenType: TokenType.command, raw: \".data\" },\n                { tokenType: TokenType.whiteSpace, raw: \" \" },\n                { tokenType: TokenType.characterLiteral, raw: \"'\\\\n'\", groups: { character: \"\\\\n\" } },\n            ]);\n        });\n\n        it(\"String\", () => {\n            assert.deepStrictEqual(Tokenizer.tokenizeLine(\".data \\\"with \\\\\\\"quotes\\\\\\\"\\\"\"), [\n                { tokenType: TokenType.command, raw: \".data\" },\n                { tokenType: TokenType.whiteSpace, raw: \" \" },\n                { tokenType: TokenType.stringLiteral, raw: \"\\\"with \\\\\\\"quotes\\\\\\\"\\\"\", groups: { characters: \"with \\\\\\\"quotes\\\\\\\"\" } },\n            ]);\n        });\n\n        it(\"String (negated)\", () => {\n            assert.deepStrictEqual(Tokenizer.tokenizeLine(\".data -\\\"with \\\\\\\"quotes\\\\\\\"\\\"\"), [\n                { tokenType: TokenType.command, raw: \".data\" },\n                { tokenType: TokenType.whiteSpace, raw: \" \" },\n                { tokenType: TokenType.stringLiteral, raw: \"-\\\"with \\\\\\\"quotes\\\\\\\"\\\"\", groups: { characters: \"with \\\\\\\"quotes\\\\\\\"\" } },\n            ]);\n        });\n    });\n\n    describe(\"Valid lines\", () => {\n        it(\"subleq 2 constants\", () => {\n            const parsed = Assembler.parseLine(\"subleq 1, 2\");\n            assert.equal(parsed.command, sic1.Command.subleqInstruction);\n            assert.deepStrictEqual(parsed.expressions, [1, 2]);\n        });\n\n        it(\"subleq 2 constants with comment\", () => {\n            const parsed = Assembler.parseLine(\"subleq 1, 2;, 5\");\n            assert.equal(parsed.command, sic1.Command.subleqInstruction);\n            assert.deepStrictEqual(parsed.expressions, [1, 2]);\n        });\n\n        it(\"subleq 3 constants\", () => {\n            const parsed = Assembler.parseLine(\"subleq 1, 2, 4\");\n            assert.equal(parsed.command, sic1.Command.subleqInstruction);\n            assert.deepStrictEqual(parsed.expressions, [1, 2, 4]);\n        });\n\n        it(\"subleq no commas\", () => {\n            const parsed = Assembler.parseLine(\"subleq 2 3 4\");\n            assert.equal(parsed.command, sic1.Command.subleqInstruction);\n            assert.deepStrictEqual(parsed.expressions, [2, 3, 4]);\n        });\n\n        it(\"subleq trailing tab\", () => {\n            const parsed = Assembler.parseLine(\"subleq 2 3 4\\t\");\n            assert.equal(parsed.command, sic1.Command.subleqInstruction);\n            assert.deepStrictEqual(parsed.expressions, [2, 3, 4]);\n        });\n\n        it(\"subleq trailing space\", () => {\n            const parsed = Assembler.parseLine(\"subleq 2 3 4   \");\n            assert.equal(parsed.command, sic1.Command.subleqInstruction);\n            assert.deepStrictEqual(parsed.expressions, [2, 3, 4]);\n        });\n\n        it(\"subleq only commas\", () => {\n            const parsed = Assembler.parseLine(\"subleq 2,3,4\");\n            assert.equal(parsed.command, sic1.Command.subleqInstruction);\n            assert.deepStrictEqual(parsed.expressions, [2, 3, 4]);\n        });\n\n        it(\"subleq spaces and commas\", () => {\n            const parsed = Assembler.parseLine(\"subleq 2 , 3 , 4\");\n            assert.equal(parsed.command, sic1.Command.subleqInstruction);\n            assert.deepStrictEqual(parsed.expressions, [2, 3, 4]);\n        });\n\n        it(\"subleq inline labels\", () => {\n            const parsed = Assembler.parseLine(\"@command1:@command2:subleq @inline0:2, @inline1:3 @inline2:@inline2_2: @inline2_3: 4\");\n            assert.equal(parsed.command, sic1.Command.subleqInstruction);\n            assert.deepStrictEqual(parsed.expressions, [2, 3, 4]);\n            assert.deepStrictEqual(parsed.labelDefinitions, [\n                { label: \"command1\", offset: 0 },\n                { label: \"command2\", offset: 0 },\n                { label: \"inline0\", offset: 0, inline: true },\n                { label: \"inline1\", offset: 1, inline: true },\n                { label: \"inline2\", offset: 2, inline: true },\n                { label: \"inline2_2\", offset: 2, inline: true },\n                { label: \"inline2_3\", offset: 2, inline: true },\n            ]);\n        });\n\n        it(\"subleq with breakpoint\", () => {\n            const parsed = Assembler.parseLine(\"!subleq 2 3 4\");\n            assert.equal(parsed.command, sic1.Command.subleqInstruction);\n            assert.deepStrictEqual(parsed.expressions, [2, 3, 4]);\n            assert.ok(parsed.breakpoint);\n        });\n\n        it(\"subleq with breakpoint and space first\", () => {\n            const parsed = Assembler.parseLine(\" ! subleq 2 3 4\");\n            assert.equal(parsed.command, sic1.Command.subleqInstruction);\n            assert.deepStrictEqual(parsed.expressions, [2, 3, 4]);\n            assert.ok(parsed.breakpoint);\n        });\n\n        it(\"subleq 2 references\", () => {\n            const line = \"subleq @one, @two\";\n            const parsed = Assembler.parseLine(line);\n            assert.equal(parsed.command, sic1.Command.subleqInstruction);\n            assert.deepStrictEqual(parsed.expressions, [\n                { label: \"one\", offset: 0, context: { sourceLineNumber: 1, sourceLine: line } },\n                { label: \"two\", offset: 0, context: { sourceLineNumber: 1, sourceLine: line } },\n            ]);\n        });\n\n        it(\"subleq 3 references\", () => {\n            const line = \"subleq @one, @two, @three\";\n            const parsed = Assembler.parseLine(line);\n            assert.equal(parsed.command, sic1.Command.subleqInstruction);\n            assert.deepStrictEqual(parsed.expressions, [\n                { label: \"one\", offset: 0, context: { sourceLineNumber: 1, sourceLine: line } },\n                { label: \"two\", offset: 0, context: { sourceLineNumber: 1, sourceLine: line } },\n                { label: \"three\", offset: 0, context: { sourceLineNumber: 1, sourceLine: line } },\n            ]);\n        });\n\n        it(\"subleq 3 references with offsets\", () => {\n            const line = \"subleq @one+1, @two-1, @three+9\";\n            const parsed = Assembler.parseLine(line);\n            assert.equal(parsed.command, sic1.Command.subleqInstruction);\n            assert.deepStrictEqual(parsed.expressions, [\n                { label: \"one\", offset: 1, context: { sourceLineNumber: 1, sourceLine: line } },\n                { label: \"two\", offset: -1, context: { sourceLineNumber: 1, sourceLine: line } },\n                { label: \"three\", offset: 9, context: { sourceLineNumber: 1, sourceLine: line } },\n            ]);\n        });\n\n        it(\"subleq 3 references with offsets, no commas\", () => {\n            const line = \"subleq @one+1 @two-1 @three+9\";\n            const parsed = Assembler.parseLine(line);\n            assert.equal(parsed.command, sic1.Command.subleqInstruction);\n            assert.deepStrictEqual(parsed.expressions, [\n                { label: \"one\", offset: 1, context: { sourceLineNumber: 1, sourceLine: line } },\n                { label: \"two\", offset: -1, context: { sourceLineNumber: 1, sourceLine: line } },\n                { label: \"three\", offset: 9, context: { sourceLineNumber: 1, sourceLine: line } },\n            ]);\n        });\n\n        it(\".data constant\", () => {\n            const parsed = Assembler.parseLine(\".data 9\");\n            assert.equal(parsed.command, sic1.Command.dataDirective);\n            assert.deepStrictEqual(parsed.expressions, [9]);\n        });\n\n        it(\".data constant (negative)\", () => {\n            const parsed = Assembler.parseLine(\".data -9\");\n            assert.equal(parsed.command, sic1.Command.dataDirective);\n            assert.deepStrictEqual(parsed.expressions, [Assembler.signedToUnsigned(-9)]);\n        });\n\n        it(\".data character\", () => {\n            const parsed = Assembler.parseLine(\".data 'H'\");\n            assert.equal(parsed.command, sic1.Command.dataDirective);\n            assert.deepStrictEqual(parsed.expressions, [\"H\".charCodeAt(0)]);\n        });\n\n        it(\".data character (negated)\", () => {\n            const parsed = Assembler.parseLine(\".data -'H'\");\n            assert.equal(parsed.command, sic1.Command.dataDirective);\n            assert.deepStrictEqual(parsed.expressions, [(-(\"H\".charCodeAt(0))) & 0xff]);\n        });\n\n        it(\".data escaped characters\", () => {\n            assert.deepStrictEqual(Assembler.parseLine(\".data '\\\\\\\\'\").expressions, [\"\\\\\".charCodeAt(0)]);\n            assert.deepStrictEqual(Assembler.parseLine(\".data '\\\\''\").expressions, [\"'\".charCodeAt(0)]);\n            assert.deepStrictEqual(Assembler.parseLine(\".data '\\\\\\\"'\").expressions, ['\"'.charCodeAt(0)]);\n            assert.deepStrictEqual(Assembler.parseLine(\".data '\\\\0'\").expressions, [0]);\n            assert.deepStrictEqual(Assembler.parseLine(\".data '\\\\n'\").expressions, [\"\\n\".charCodeAt(0)]);\n            assert.deepStrictEqual(Assembler.parseLine(\".data -'\\\\n'\").expressions, [(-(\"\\n\".charCodeAt(0))) & 0xff]);\n        });\n\n        it(\".data string\", () => {\n            const parsed = Assembler.parseLine(\".data \\\"\\\\\\\"q\\\\\\\"\\\"\");\n            assert.equal(parsed.command, sic1.Command.dataDirective);\n            assert.deepStrictEqual(parsed.expressions, ['\"'.charCodeAt(0), 'q'.charCodeAt(0), '\"'.charCodeAt(0), 0]);\n        });\n\n        it(\".data string (empty)\", () => {\n            const parsed = Assembler.parseLine(\".data \\\"\\\"\");\n            assert.equal(parsed.command, sic1.Command.dataDirective);\n            assert.deepStrictEqual(parsed.expressions, [0]);\n        });\n\n        it(\".data string (negated)\", () => {\n            const parsed = Assembler.parseLine(\".data -\\\"\\\\\\\"'\\\\\\\"\\\"\");\n            assert.equal(parsed.command, sic1.Command.dataDirective);\n            assert.deepStrictEqual(parsed.expressions, [(-('\"'.charCodeAt(0))) & 0xff, (-(\"'\".charCodeAt(0))) & 0xff, (-('\"'.charCodeAt(0))) & 0xff, 0]);\n        });\n\n        it(\".data reference\", () => {\n            const line = \".data @one\";\n            const parsed = Assembler.parseLine(line);\n            assert.equal(parsed.command, sic1.Command.dataDirective);\n            assert.deepStrictEqual(parsed.expressions, [\n                { label: \"one\", offset: 0, context: { sourceLineNumber: 1, sourceLine: line } },\n            ]);\n        });\n\n        it(\".data reference (negated)\", () => {\n            const line = \".data -@one\";\n            const parsed = Assembler.parseLine(line);\n            assert.equal(parsed.command, sic1.Command.dataDirective);\n            assert.deepStrictEqual(parsed.expressions, [\n                { label: \"one\", offset: 0, negated: true, context: { sourceLineNumber: 1, sourceLine: line } },\n            ]);\n        });\n\n        it(\".data reference with offset\", () => {\n            const line = \".data @one-99\";\n            const parsed = Assembler.parseLine(line);\n            assert.equal(parsed.command, sic1.Command.dataDirective);\n            assert.deepStrictEqual(parsed.expressions, [\n                { label: \"one\", offset: -99, context: { sourceLineNumber: 1, sourceLine: line } },\n            ]);\n        });\n\n        it(\".data reference with offset (negated)\", () => {\n            const line = \".data -@one+99\";\n            const parsed = Assembler.parseLine(line);\n            assert.equal(parsed.command, sic1.Command.dataDirective);\n            assert.deepStrictEqual(parsed.expressions, [\n                { label: \"one\", offset: 99, negated: true, context: { sourceLineNumber: 1, sourceLine: line } },\n            ]);\n        });\n\n        it(\".data multiple values\", () => {\n            const parsed = Assembler.parseLine(\".data 1, 2\");\n            assert.equal(parsed.command, sic1.Command.dataDirective);\n            assert.deepStrictEqual(parsed.expressions, [1, 2]);\n        });\n\n        it(\".data inline labels\", () => {\n            const parsed = Assembler.parseLine(\"@command: .data @inline0:1, @inline1: 2\");\n            assert.equal(parsed.command, sic1.Command.dataDirective);\n            assert.deepStrictEqual(parsed.expressions, [1, 2]);\n            assert.deepStrictEqual(parsed.labelDefinitions, [\n                { label: \"command\", offset: 0 },\n                { label: \"inline0\", offset: 0, inline: true },\n                { label: \"inline1\", offset: 1, inline: true },\n            ]);\n        });\n\n        it(\".data inline labels for strings\", () => {\n            const parsed = Assembler.parseLine('@command: .data @inline0:\"Hi\" @inline3:\"World\", @inline9:\\'9\\' @inline10:-1');\n            assert.equal(parsed.command, sic1.Command.dataDirective);\n            assert.deepStrictEqual(parsed.expressions, [\n                \"H\".charCodeAt(0),\n                \"i\".charCodeAt(0),\n                0,\n                \"W\".charCodeAt(0),\n                \"o\".charCodeAt(0),\n                \"r\".charCodeAt(0),\n                \"l\".charCodeAt(0),\n                \"d\".charCodeAt(0),\n                0,\n                \"9\".charCodeAt(0),\n                Assembler.signedToUnsigned(-1),\n            ]);\n            assert.deepStrictEqual(parsed.labelDefinitions, [\n                { label: \"command\", offset: 0 },\n                { label: \"inline0\", offset: 0, inline: true },\n                { label: \"inline3\", offset: 3, inline: true },\n                { label: \"inline9\", offset: 9, inline: true },\n                { label: \"inline10\", offset: 10, inline: true },\n            ]);\n        });\n\n        it(\".data references, no commas\", () => {\n            const line = \".data 1 @two @three-45 @six+7\";\n            const parsed = Assembler.parseLine(line);\n            assert.equal(parsed.command, sic1.Command.dataDirective);\n            assert.deepStrictEqual(parsed.expressions, [\n                1,\n                { label: \"two\", offset: 0, context: { sourceLineNumber: 1, sourceLine: line } },\n                { label: \"three\", offset: -45, context: { sourceLineNumber: 1, sourceLine: line } },\n                { label: \"six\", offset: 7, context: { sourceLineNumber: 1, sourceLine: line } },\n            ]);\n        });\n\n        it(\".data all variations\", () => {\n            const line = \"@command: .data 1, @inline1:-2 @one, @inline3: @inline3_2: -@two @inline4:@inline4_2:@three+3, -@4-4 'a', -'A' \\\"abc\\\", -\\\"DEF\\\"\";\n            const parsed = Assembler.parseLine(line);\n            assert.equal(parsed.command, sic1.Command.dataDirective);\n            assert.deepStrictEqual(parsed.expressions, [\n                1,\n                Assembler.signedToUnsigned(-2),\n                { label: \"one\", offset: 0, context: { sourceLineNumber: 1, sourceLine: line } },\n                { label: \"two\", offset: 0, negated: true, context: { sourceLineNumber: 1, sourceLine: line } },\n                { label: \"three\", offset: 3, context: { sourceLineNumber: 1, sourceLine: line } },\n                { label: \"4\", offset: -4, negated: true, context: { sourceLineNumber: 1, sourceLine: line } },\n                \"a\".charCodeAt(0),\n                Assembler.signedToUnsigned(-\"A\".charCodeAt(0)),\n                \"a\".charCodeAt(0),\n                \"b\".charCodeAt(0),\n                \"c\".charCodeAt(0),\n                0,\n                Assembler.signedToUnsigned(-\"D\".charCodeAt(0)),\n                Assembler.signedToUnsigned(-\"E\".charCodeAt(0)),\n                Assembler.signedToUnsigned(-\"F\".charCodeAt(0)),\n                0,\n            ]);\n            assert.deepStrictEqual(parsed.labelDefinitions, [\n                { label: \"command\", offset: 0 },\n                { label: \"inline1\", offset: 1, inline: true },\n                { label: \"inline3\", offset: 3, inline: true },\n                { label: \"inline3_2\", offset: 3, inline: true },\n                { label: \"inline4\", offset: 4, inline: true },\n                { label: \"inline4_2\", offset: 4, inline: true },\n            ]);\n        });\n    });\n\n    describe(\"Invalid lines\", () => {\n        it(\"subleq no arguments\", () => {\n            assert.throws(() => Assembler.parseLine(\"subleq\"));\n        });\n\n        it(\"subleq too few arguments\", () => {\n            assert.throws(() => Assembler.parseLine(\"subleq 1\"));\n        });\n\n        it(\"subleq no spaces\", () => {\n            assert.throws(() => Assembler.parseLine(\"subleq @one@two\"));\n        });\n\n        it(\"subleq no space after command\", () => {\n            assert.throws(() => Assembler.parseLine(\"subleq@one @two\"));\n        });\n\n        it(\"subleq comma after command\", () => {\n            assert.throws(() => Assembler.parseLine(\"subleq,@one @two\"));\n        });\n\n        it(\"subleq comma after inline command\", () => {\n            assert.throws(() => Assembler.parseLine(\"subleq @one @inline:, @two\"));\n        });\n\n        it(\"subleq repeated commas\", () => {\n            assert.throws(() => Assembler.parseLine(\"subleq @one,,@two\"));\n        });\n\n        it(\"subleq repeated commas and spaces\", () => {\n            assert.throws(() => Assembler.parseLine(\"subleq @one, , @two\"));\n        });\n\n        it(\"subleq too many arguments\", () => {\n            const line = \"subleq 1, 2, 3, 4\";\n            let match = false;\n            try {\n                Assembler.parseLine(line);\n            } catch (error) {\n                if (error instanceof CompilationError) {\n                    assert.deepStrictEqual(error.context, { sourceLineNumber: 1, sourceLine: line, number: 4, rangeMin: 2, rangeMax: 3 });\n                    match = true;\n                }\n            }\n            assert.ok(match);\n        });\n\n        it(\"Invalid labels\", () => {\n            assert.throws(() => Assembler.parseLine(\"@-1 .data -1\"));\n            assert.throws(() => Assembler.parseLine(\"@! .data -1\"));\n            assert.throws(() => Assembler.parseLine(\"@@ .data -1\"));\n            assert.throws(() => Assembler.parseLine(\"@\\\\ .data -1\"));\n            assert.throws(() => Assembler.parseLine(\"@( .data -1\"));\n            assert.throws(() => Assembler.parseLine(\"@) .data -1\"));\n            assert.throws(() => Assembler.parseLine(\"@; .data -1\"));\n            assert.throws(() => Assembler.parseLine(\"@: .data -1\"));\n            assert.throws(() => Assembler.parseLine(\"@' .data -1\"));\n            assert.throws(() => Assembler.parseLine(\"@\\\" .data -1\"));\n            assert.throws(() => Assembler.parseLine(\"@, .data -1\"));\n            assert.throws(() => Assembler.parseLine(\"@+ .data -1\"));\n        });\n\n        it(\".data  no arguments\", () => {\n            assert.throws(() => Assembler.parseLine(\".data\"));\n        });\n\n        it(\".data invalid character\", () => {\n            assert.throws(() => Assembler.parseLine(\".data 'ab'\"));\n            assert.throws(() => Assembler.parseLine(\".data '''\"));\n            assert.throws(() => Assembler.parseLine(\".data ''\"));\n        });\n\n        it(\".data invalid escape characters\", () => {\n            assert.throws(() => Assembler.parseLine(\".data '\\\\t'\"));\n            assert.throws(() => Assembler.parseLine(\".data '\\\\'\"));\n            assert.throws(() => Assembler.parseLine(\".data -'\\\\'\"));\n            assert.throws(() => Assembler.parseLine(\".data ''\"));\n        });\n\n        it(\".data invalid strings\", () => {\n            assert.throws(() => Assembler.parseLine('.data \"\\\\\"'));\n            assert.throws(() => Assembler.parseLine('.data \"\\\\t\"'));\n            assert.throws(() => Assembler.parseLine('.data \"\"\"'));\n        });\n\n        it(\".data no spaces\", () => {\n            assert.throws(() => Assembler.parseLine('.data \"\"\"\"'));\n            assert.throws(() => Assembler.parseLine('.data @one@two'));\n            assert.throws(() => Assembler.parseLine('.data 0-@tmp'));\n        });\n\n        it(\"Max length\", () => {\n            const lines = [];\n            for (let i = 0; i < sic1.Constants.addressUserMax; i++) {\n                lines.push(\".data 1\");\n            }\n\n            const program = Assembler.assemble(lines);\n            assert.strictEqual(program.bytes.length, sic1.Constants.addressUserMax);\n            for (let byte of program.bytes) {\n                assert.strictEqual(byte, 1);\n            }\n        });\n\n        it(\"Breakpoint only\", () => {\n            assert.throws(() => Assembler.parseLine(\"!\"));\n        });\n\n        it(\"Breakpoint on .data\", () => {\n            assert.throws(() => Assembler.parseLine(\"!.data 0\"));\n        });\n\n        it(\"Breakpoint not at beginning\", () => {\n            assert.throws(() => Assembler.parseLine(\"subleq 1 2 3 !\"));\n        });\n    });\n\n    describe(\"Valid programs\", () => {\n        it(\"Single instruction\", () => {\n            const program = Assembler.assemble(`\n                subleq @OUT, @IN\n            `.split(\"\\n\"));\n\n            assert.deepEqual(program.bytes, [sic1.Constants.addressOutput, sic1.Constants.addressInput, 3]);\n        });\n\n        it(\"Negation loop with breakpoint\", () => {\n            const program = Assembler.assemble(`\n                @loop:\n                subleq @OUT, @IN\n                !subleq @zero, @zero, @loop\n\n                @zero: .data 0\n            `.split(\"\\n\"));\n\n            assert.deepEqual(\n                program.bytes,\n                [\n                    sic1.Constants.addressOutput, sic1.Constants.addressInput, 3,\n                    6, 6, 0,\n                    0\n                ]);\n\n            assert.deepEqual(program.variables, [ { label: \"@zero\", address: 6 } ]);\n\n            assert.strictEqual(program.sourceMap[0].command, sic1.Command.subleqInstruction);\n            assert.strictEqual(program.sourceMap[0].lineNumber, 2);\n\n            assert.strictEqual(program.sourceMap[6].command, sic1.Command.dataDirective);\n            assert.strictEqual(program.sourceMap[6].lineNumber, 5);\n            assert.strictEqual(program.sourceMap[6].source.trim(), \"@zero: .data 0\");\n\n            assert.deepStrictEqual(program.breakpoints, [3]);\n        });\n\n        it(\".data directive without label\", () => {\n            const program = Assembler.assemble(`\n                .data 0\n            `.split(\"\\n\"));\n\n            assert.deepEqual(program.bytes, [0]);\n            assert.strictEqual(program.sourceMap[0].command, sic1.Command.dataDirective);\n            assert.strictEqual(program.sourceMap[0].lineNumber, 1);\n            assert.strictEqual(program.sourceMap[0].source.trim(), \".data 0\");\n            assert.deepStrictEqual(program.variables, []);\n        });\n\n        it(\"Inline variable style\", () => {\n            const program = Assembler.assemble(`\n                .data @tmp: 0 @tmp2: 2 @three: 3\n            `.split(\"\\n\"));\n\n            assert.deepEqual(program.bytes, [0, 2, 3]);\n            assert.strictEqual(program.sourceMap[0].command, sic1.Command.dataDirective);\n            assert.strictEqual(program.sourceMap[0].lineNumber, 1);\n            assert.deepStrictEqual(program.variables, [\n                { label: \"@tmp\", address: 0 },\n                { label: \"@tmp2\", address: 1 },\n                { label: \"@three\", address: 2 },\n            ]);\n        });\n\n        it(\"Inline label in passthrough loop\", () => {\n            const program = Assembler.assemble(`\n                @loop:\n                subleq @tmp: 0, @IN\n                subleq @tmp, @IN\n                subleq @OUT, @tmp\n                subleq @tmp, @tmp, @loop\n            `.split(\"\\n\"));\n\n            assert.deepEqual(program.bytes, [0, 253, 3, 0, 253, 6, 254, 0, 9, 0, 0, 0]);\n            assert.strictEqual(program.sourceMap[0].command, sic1.Command.subleqInstruction);\n            assert.strictEqual(program.sourceMap[0].lineNumber, 2);\n            assert.strictEqual(program.sourceMap[3].command, sic1.Command.subleqInstruction);\n            assert.strictEqual(program.sourceMap[3].lineNumber, 3);\n            assert.strictEqual(program.sourceMap[6].command, sic1.Command.subleqInstruction);\n            assert.strictEqual(program.sourceMap[6].lineNumber, 4);\n            assert.strictEqual(program.sourceMap[9].command, sic1.Command.subleqInstruction);\n            assert.strictEqual(program.sourceMap[9].lineNumber, 5);\n            assert.deepStrictEqual(program.variables, [ { label: \"@tmp\", address: 0 } ]);\n        });\n    });\n\n    describe(\"Error tracing\", () => {\n        function verifyError(program: string, errorType: sic1.CompilationErrorType, errorLineNumber?: number, extraContext?: Partial<sic1.CompilationContext>) {\n            const lines = program.split(\"\\n\");\n            let match = false;\n            try {\n                Assembler.assemble(lines);\n            } catch (error) {\n                if (error instanceof CompilationError) {\n                    assert.strictEqual(error.errorType, errorType);\n                    if (errorLineNumber !== undefined) {\n                        assert.deepStrictEqual(error.context, { sourceLineNumber: errorLineNumber, sourceLine: lines[errorLineNumber - 1], ...extraContext });\n                    }\n                    match = true;\n                }\n            }\n            assert.ok(match, \"Got the expected exception\");\n        }\n\n        it(\"Invalid value\", () => {\n            verifyError(`\n                subleq @OUT, @IN\n                @zero: .data 128\n            `, \"ValueRangeError\", 3, { text: \"128\", rangeMin: -128, rangeMax: 127 });\n        });\n\n        it(\"Invalid address\", () => {\n            verifyError(`\n                subleq @OUT, @IN\n                subleq 256, @IN\n            `, \"AddressLiteralRangeError\", 3, {\n                text: \"256\",\n                rangeMin: 0,\n                rangeMax: 255,\n            });\n        });\n\n        it(\"Invalid token type for subleq\", () => {\n            verifyError(`\n                subleq 'a', 'b', 'c'\n            `, \"InvalidAddressExpressionError\", 2, { text: \"'a'\" });\n        });\n\n        it(\"Invalid argument count for subleq\", () => {\n            verifyError(`\n                subleq @OUT, @IN\n                subleq @OUT\n            `, \"InvalidSubleqArgumentCountError\", 3, { number: 1, rangeMin: 2, rangeMax: 3 });\n        });\n\n        it(\"No arguments for subleq\", () => {\n            verifyError(`\n                subleq @OUT, @IN\n                subleq\n            `, \"InvalidSubleqArgumentCountError\", 3, { number: 0, rangeMin: 2, rangeMax: 3 });\n        });\n\n        it(\"No arguments for .data\", () => {\n            verifyError(`\n                subleq @OUT, @IN\n                .data\n            `, \"InvalidDataArgumentCountError\", 3, { number: 0, rangeMin: 1 });\n        });\n\n        it(\"Invalid command\", () => {\n            verifyError(`\n                subleq @OUT, @IN\n                .duh 1\n            `, \"InvalidCommandError\", 3, { text: \".duh\" });\n        });\n\n        it(\"Label redefinition\", () => {\n            verifyError(`\n                subleq @OUT, @IN\n                @tmp: .data 5\n                @tmp: .data 6\n            `, \"LabelAlreadyDefinedError\", 4, { text: \"@tmp\" });\n        });\n\n        it(\"Label redefinition (from zero)\", () => {\n            verifyError(`\n                @tmp:\n                @loop:\n                subleq @tmp, @IN\n                subleq @tmp, @n_0\n                subleq @OUT, @tmp\n                subleq @tmp, @tmp, @loop\n            \n                @n_0: .data -'0'\n                @tmp: .data 0\n            `, \"LabelAlreadyDefinedError\", 10, { text: \"@tmp\" });\n        });\n\n        it(\"Missing label\", () => {\n            verifyError(`\n                subleq @OUT, @IN\n                subleq @zero, @zero, @loop\n\n                @zero: .data 0\n            `, \"UndefinedReferenceError\", 3, { text: \"@loop\" });\n        });\n\n        it(\"Missing variable\", () => {\n            verifyError(`\n                @loop:\n                subleq @OUT, @IN\n                subleq @zero, @zero, @loop\n            `, \"UndefinedReferenceError\", 4, { text: \"@zero\" });\n        });\n\n        it(\"Invalid offset\", () => {\n            verifyError(`\n                @loop:\n                subleq @OUT, @IN\n                subleq @OUT, @IN, @loop-1\n            `, \"AddressReferenceRangeError\", 4, { text: \"@loop-1\", number: -1, rangeMin: 0, rangeMax: 255 });\n        });\n\n        it(\"Breakpoint not on subleq instruction\", () => {\n            verifyError(`\n                !.data 1 2 3\n            `, \"InvalidBreakpointError\", 2);\n        });\n\n        it(\"Invalid escape code\", () => {\n            verifyError(`\n                .data '\\\\a'\n            `, \"InvalidEscapeCodeError\", 2, { text: \"\\\\a\" });\n        });\n\n        it(\"Invalid token\", () => {\n            verifyError(`\n                .data %\n            `, \"InvalidTokenError\", 2, { text: \"%\" });\n        });\n\n        it(\"Invalid value expression\", () => {\n            verifyError(`\n                !.data .data\n            `, \"InvalidValueExpressionError\", 2, { text: \".data\" });\n        });\n\n        it(\"Missing comma or whitespace\", () => {\n            verifyError(`\n                subleq @a@b@c\n            `, \"MissingCommaOrWhitespaceError\", 2, { text: \"@b\" });\n        });\n\n        it(\"Missing whitespace\", () => {\n            verifyError(`\n                .data'a'\n            `, \"MissingWhitespaceError\", 2, { text: \".data\" });\n        });\n\n        it(\"Too long\", () => {\n            const count = sic1.Constants.addressUserMax + 2;\n            verifyError(\".data 1\\n\".repeat(count), \"ProgramTooLargeError\");\n        });\n\n        it(\"Too long with reference\", () => {\n            // Test a wide range\n            for (let i = 0; i <= 10; i++) {\n                verifyError(\n                    `subleq @last @last @last\n                    ${\".data -1\\n\".repeat(sic1.Constants.addressUserMax + i)}\n                    @last: .data -2`, \"ProgramTooLargeError\");\n            }\n        });\n    });\n});\n\nfunction verifyProgram(inputs: number[], expectedOutputs: number[], code: string, onWriteMemory?: (address: number, byte: number) => void) {\n    let inputIndex = 0;\n    let outputIndex = 0;\n\n    const emulator = new Emulator(Assembler.assemble(code.split(\"\\n\")), {\n        readInput: () => inputs[inputIndex++],\n        writeOutput: n => assert.strictEqual(n, expectedOutputs[outputIndex++]),\n        onWriteMemory: onWriteMemory ?? undefined,\n    });\n\n    assert.strictEqual(emulator.isEmpty(), false);\n    assert.strictEqual(emulator.isRunning(), true);\n\n    let steps = 0;\n    while (outputIndex < expectedOutputs.length) {\n        if (++steps > 1000) {\n            assert.fail(\"Execution did not complete\");\n            break;\n        }\n\n        emulator.step();\n    }\n}\n\ndescribe(\"SIC-1 Emulator\", () => {\n    it(\"Empty program\", () => {\n        const emulator = new Emulator(Assembler.assemble([]), {});\n        assert.strictEqual(emulator.isEmpty(), true);\n    });\n\n    it(\"Blank line-only program\", () => {\n        const emulator = new Emulator(Assembler.assemble([\"\"]), {});\n        assert.strictEqual(emulator.isEmpty(), true);\n    });\n\n    it(\"Comment-only program\", () => {\n        const emulator = new Emulator(Assembler.assemble([\"; Nothing going on here...\"]), {});\n        assert.strictEqual(emulator.isEmpty(), true);\n    });\n\n    it(\"Negation input/output\", () => {\n        const inputs = [4, 5, 100, 101];\n        verifyProgram(\n            inputs,\n            inputs.map(n => -n),\n            `\n            @loop:\n            subleq @OUT, @IN\n            subleq @0, @0, @loop\n\n            @0: .data 0\n        `);\n    });\n\n    it(\"Negation input/output (Unicode)\", () => {\n        const inputs = [4, 5, 100, 101];\n        verifyProgram(\n            inputs,\n            inputs.map(n => -n),\n            `\n            @🜂:\n            subleq @OUT, @IN\n            subleq @0, @0, @🜂\n\n            @0: .data 0\n        `);\n    });\n\n    it(\"Writes to reserved addresses shouldn't update memory\", () => {\n        const inputs = [45, 123];\n        verifyProgram(\n            inputs,\n            [-1, -123, 0, 0],\n            `\n            subleq @IN, @one\n            subleq @OUT, @one\n            subleq @HALT, @one\n            subleq @OUT, @IN\n            subleq @OUT, @OUT\n            subleq @OUT, @HALT\n            @one: .data 1\n        `, (address, byte) => {\n            if (byte !== 0) {\n                assert.notStrictEqual(address, Constants.addressInput, \"Writes to @IN should not update memory\");\n                assert.notStrictEqual(address, Constants.addressOutput, \"Writes to @OUT should not update memory\");\n                assert.notStrictEqual(address, Constants.addressHalt, \"Writes to @HALT should not update memory\");\n            }\n        });\n    });\n\n    it(\"Using @IN in the first position should ensure a value is read, but nothing should be written\", () => {\n        const inputs = [123, 0, -1, -127, 1, 127, 34];\n        verifyProgram(\n            inputs,\n            [-34],\n            `\n            subleq @IN, @IN             ; Burn an input\n            subleq @IN, @zero, @good1   ; Input 0 should branch\n            subleq @zero, @zero, @HALT\n            @good1:\n            subleq @IN, @zero, @good2   ; Input -1 should branch\n            subleq @zero, @zero, @HALT\n            @good2:\n            subleq @IN, @zero, @good3   ; Input -127 should branch\n            subleq @zero, @zero, @HALT\n            @good3:\n            subleq @IN, @zero, @HALT    ; Input 1 should not branch\n            subleq @IN, @zero, @HALT    ; Input 127 should not branch\n            subleq @OUT, @IN\n            @zero: .data 0\n        `, (address, byte) => {\n            if (byte !== 0) {\n                assert.notStrictEqual(address, Constants.addressInput, \"Writes to @IN should not update memory\");\n            }\n        });\n    });\n\n    it(\"Negated label references\", () => {\n        verifyProgram(\n            [99],\n            [-3, 3, -4, 4, -99],\n            `\n            subleq @OUT, @pthree\n\n            @three:\n            subleq @OUT, @pnthree\n            subleq @OUT, @pthree1\n            subleq @OUT, @pnthree1\n            subleq @OUT, -@three ; @three is 3, so -@three is -3, i.e. 253, i.e. @IN\n            \n            @pthree: .data @three\n            @pnthree: .data -@three\n            @pthree1: .data @three+1\n            @pnthree1: .data -@three-1\n        `);\n    });\n\n    it(\"Callbacks\", () => {\n        let firstUpdate = true;\n        let secondUpdate = true;\n        let firstWriteAfterUpdate = true;\n        const emulator = new Emulator(Assembler.assemble(`\n            subleq @tmp, @five\n            subleq @tmp, @tmp, @HALT\n\n            @five: .data 5\n            @tmp: .data 0\n        `.split(\"\\n\")), {\n            onWriteMemory: (address, byte) => {\n                if (!firstUpdate && firstWriteAfterUpdate) {\n                    firstWriteAfterUpdate = false;\n                    assert.strictEqual(address, 7);\n                    assert.strictEqual(byte, 0xfb);\n                }\n            },\n\n            onHalt: (data) => {\n                assert.strictEqual(data.cyclesExecuted, 2);\n                assert.strictEqual(data.memoryBytesAccessed, 8);\n            },\n\n            onStateUpdated: data => {\n                if (firstUpdate) {\n                    firstUpdate = false;\n                    assert.strictEqual(data.running, true);\n                    assert.strictEqual(data.ip, 0);\n                    assert.strictEqual(data.target, 7);\n                    assert.strictEqual(data.sourceLineNumber, 1);\n                    assert.strictEqual(data.source.trim(), \"subleq @tmp, @five\");\n                    assert.strictEqual(data.cyclesExecuted, 0);\n                    assert.strictEqual(data.memoryBytesAccessed, 0);\n                    assert.deepEqual(data.variables, [\n                        { label: \"@five\", value: 5 },\n                        { label: \"@tmp\", value: 0 },\n                    ]);\n                } else if (secondUpdate) {\n                    secondUpdate = false;\n                    assert.strictEqual(data.running, true);\n                    assert.strictEqual(data.ip, 3);\n                    assert.strictEqual(data.target, 7);\n                    assert.strictEqual(data.sourceLineNumber, 2);\n                    assert.strictEqual(data.source.trim(), \"subleq @tmp, @tmp, @HALT\");\n                    assert.strictEqual(data.cyclesExecuted, 1);\n                    assert.strictEqual(data.memoryBytesAccessed, 5);\n                    assert.deepEqual(data.variables, [\n                        { label: \"@five\", value: 5 },\n                        { label: \"@tmp\", value: -5 },\n                    ]);\n                }\n            },\n        });\n\n        emulator.run();\n    });\n\n    it(\"Reset\", () => {\n        const inputs = [4, 5, 100, 101];\n        const expectedOutputs = inputs.slice();\n        const code = `\n            subleq @tmp, @IN\n            subleq @OUT, @tmp\n            subleq @zero, @zero, @HALT\n\n            @zero: .data 0\n            @tmp: .data 0 ; Note: This is NOT reset! We're relying on the reset function instead.\n        `;\n\n        let inputIndex = 0;\n        let outputIndex = 0;\n    \n        const emulator: sic1.Emulator = new Emulator(Assembler.assemble(code.split(\"\\n\")), {\n            readInput: () => inputs[inputIndex++],\n            writeOutput: n => assert.strictEqual(n, expectedOutputs[outputIndex++]),\n            onHalt: () => emulator.reset(), // Reset on halt\n        });\n    \n        let steps = 0;\n        while (outputIndex < expectedOutputs.length) {\n            if (++steps > 1000) {\n                assert.fail(\"Execution did not complete\");\n                break;\n            }\n    \n            emulator.step();\n        }\n    });\n\n    it(\"Halt\", () => {\n        for (const [program, shouldHalt] of [\n            [\"subleq 0, 0, @MAX\", false],\n            [`subleq 0, 0, ${Constants.addressInstructionMax}`, false],\n            [\"subleq 0, 0, @MAX+1\", true],\n            [\"subleq 0, 0, @MAX+2\", true],\n            [\"subleq 0, 0, @HALT\", true],\n            [`subleq 0, 0, ${Constants.addressInstructionMax + 1}`, true],\n        ] as const) {\n            const emulator = new Emulator(Assembler.assemble(program.split(\"\\n\")));\n    \n            emulator.step();\n            assert.strictEqual(emulator.isRunning(), !shouldHalt, `Should ${shouldHalt ? \"\" : \"not \"}have halted for: ${program}`);\n        }\n    });\n});\n", "lib/test/tsconfig.json": "{\n    \"compilerOptions\": {\n        \"strict\": false,\n        \"esModuleInterop\": true\n    },\n    \"files\": [\n        \"sic1asm.spec.ts\"\n    ]\n}", "lib/src/sic1asm.ts": "// Valid tokens\nexport const Syntax = {\n    subleqInstruction: \"subleq\",\n    dataDirective: \".data\",\n    referencePrefix: \"@\",\n    commentDelimiter: \";\",\n    optionalArgumentSeparator: \",\",\n};\n\nconst addressMax = 255;\nconst subleqInstructionBytes = 3;\n\nexport const Constants = {\n    // Valid values\n    valueMin: -128,\n    valueMax: 127,\n\n    // Valid addresses\n    addressMin: 0,\n    addressInstructionMax: addressMax - subleqInstructionBytes,\n    addressMax,\n\n    // Built-in addresses\n    addressUserMax: 252,\n    addressInput: 253,\n    addressOutput: 254,\n    addressHalt: 255,\n\n    subleqInstructionBytes,\n} as const;\n\nconst CompilationErrorTypes = [\n    \"AddressLiteralRangeError\",\n    \"AddressReferenceRangeError\",\n    \"InternalCompilerError\",\n    \"InvalidAddressExpressionError\",\n    \"InvalidBreakpointError\",\n    \"InvalidCommandError\",\n    \"InvalidDataArgumentCountError\",\n    \"InvalidEscapeCodeError\",\n    \"InvalidSubleqArgumentCountError\",\n    \"InvalidTokenError\",\n    \"InvalidValueExpressionError\",\n    \"LabelAlreadyDefinedError\",\n    \"MissingCommaOrWhitespaceError\",\n    \"MissingWhitespaceError\",\n    \"ProgramTooLargeError\",\n    \"UndefinedReferenceError\",\n    \"ValueRangeError\",\n] as const;\n\nexport type CompilationErrorType = typeof CompilationErrorTypes[number];\n\n// Custom error type\nexport interface CompilationContext {\n    sourceLineNumber?: number;\n    sourceLine?: string;\n    \n    // Error-specific fields\n    text?: string;\n    number?: number;\n    rangeMin?: number;\n    rangeMax?: number;\n}\n\nexport class CompilationError extends Error {\n    constructor(public errorType: CompilationErrorType, message: string, public context: CompilationContext) {\n        super(message);\n\n        // Ensure prototype is CompilationError\n        Object.setPrototypeOf(this, CompilationError.prototype);\n    }\n}\n\nexport enum Command {\n    subleqInstruction,\n    dataDirective\n}\n\nexport interface LabelReference {\n    label: string;\n    negated?: boolean;\n    offset: number;\n    context: CompilationContext;\n}\n\nexport type Expression = LabelReference | number;\n\nexport interface LabelDefinition {\n    label: string;\n    offset: number;\n    inline?: boolean;\n}\n\nexport interface ParsedLine {\n    labelDefinitions: LabelDefinition[];\n    command?: Command;\n    expressions: Expression[];\n    breakpoint?: boolean;\n}\n\nexport interface SourceMapEntry {\n    lineNumber: number;\n    command: Command;\n    source: string;\n}\n\nexport interface VariableDefinition {\n    label: string;\n    address: number;\n}\n\nexport interface AssembledProgram {\n    bytes: number[];\n    sourceMap: SourceMapEntry[];\n    variables: VariableDefinition[];\n    breakpoints: number[];\n}\n\nexport enum TokenType {\n    label,\n    command,\n\n    // Expressions\n    numberLiteral,\n    characterLiteral,\n    reference,\n    stringLiteral,\n\n    // Syntax\n    comma,\n    exclamationMark,\n    whiteSpace,\n\n    // Ignored\n    comment,\n}\n\ninterface TokenGroups {\n    [key: string]: string;\n}\n\nexport interface Token {\n    tokenType: TokenType;\n    groups?: TokenGroups;\n    raw: string;\n}\n\ninterface TokenizerRuleDefinition {\n    tokenType: TokenType;\n    pattern: string;\n    groups?: string[];\n    discard?: boolean;\n}\n\ninterface TokenizerRule {\n    tokenType: TokenType;\n    regExp: RegExp;\n    groups?: string[];\n    discard?: boolean;\n}\n\nexport class Tokenizer {\n    private static readonly commandPattern = \"[_a-zA-Z][_a-zA-Z0-9]*\";\n    private static readonly whitespaceCharacters = \"\\f\\n\\r\\t\\v\\u0020\\u00a0\\u1680\\u2000-\\u200a\\u2028\\u2029\\u202f\\u205f\\u3000\\ufeff\";\n\n    // List of reserved characters that *may not* be used in identifiers (because they have, or may eventually have,\n    // another meaning).\n    //\n    // Note: \"-\" must be last, and this should only be used at the end of a character class. Rough explanation of the\n    // contents: breakpoint symbol, label symbol, escape symbol, parentheses (not used, but maybe could be someday),\n    // comment symbol, label definition symbol, character and string markers, (optional) argument separator, and\n    // offset indicators\n    private static readonly reservedCharacters = `!@\\\\\\\\();:'\",+-`;\n\n    private static readonly identifierPattern = `[^${Tokenizer.whitespaceCharacters}${Tokenizer.reservedCharacters}]+`;\n    private static readonly numberWithoutSignPattern = \"[0-9]+\";\n    private static readonly printableCharacterPattern = \"[ -~]\";\n    private static readonly printableCharactersExceptApostropheAndBackslashPattern = \"[ -&(-[\\\\]-~]\";\n    private static readonly printableCharactersExceptQuoteAndBackslashPattern = \"[ !#-[\\\\]-~]\";\n    private static readonly referencePattern = `${Syntax.referencePrefix}(${Tokenizer.identifierPattern})`;\n\n    private static readonly ruleDefinitions: TokenizerRuleDefinition[] = [\n        { tokenType: TokenType.whiteSpace, pattern: \"\\\\s+\" },\n        { tokenType: TokenType.comma, pattern: Syntax.optionalArgumentSeparator },\n        { tokenType: TokenType.exclamationMark, pattern: \"!\" },\n        { tokenType: TokenType.command, pattern: `[.]?${Tokenizer.commandPattern}` },\n        { tokenType: TokenType.numberLiteral, pattern: `-?${Tokenizer.numberWithoutSignPattern}` },\n        { tokenType: TokenType.characterLiteral, pattern: `-?'(${Tokenizer.printableCharactersExceptApostropheAndBackslashPattern}|\\\\\\\\${Tokenizer.printableCharacterPattern})'`, groups: [\"character\"] },\n        { tokenType: TokenType.stringLiteral, pattern: `-?\"((${Tokenizer.printableCharactersExceptQuoteAndBackslashPattern}|\\\\\\\\${Tokenizer.printableCharacterPattern})*)\"`, groups: [\"characters\"] },\n        { tokenType: TokenType.label, pattern: `${Tokenizer.referencePattern}:`, groups: [\"name\"] },\n        { tokenType: TokenType.reference, pattern: `(-?)${Tokenizer.referencePattern}([+-]${Tokenizer.numberWithoutSignPattern})?`, groups: [\"negation\", \"name\", \"offset\"] },\n        { tokenType: TokenType.comment, pattern: `${Syntax.commentDelimiter}.*$`, discard: true },\n    ];\n\n    private static readonly rules: TokenizerRule[] = Tokenizer.ruleDefinitions.map(def => Tokenizer.createRule(def));\n\n    private static createRule(definition: TokenizerRuleDefinition): TokenizerRule {\n        return {\n            tokenType: definition.tokenType,\n            regExp: new RegExp(`^${definition.pattern}`),\n            groups: definition.groups,\n            discard: definition.discard,\n        };\n    }\n\n    private static createToken(rule: TokenizerRule, matchedGroups: RegExpExecArray): Token {\n        const token: Token = {\n            tokenType: rule.tokenType,\n            raw: matchedGroups[0],\n        };\n\n        let groups: TokenGroups | undefined;\n        if (rule.groups) {\n            groups = {};\n            for (let i = 0; i < rule.groups.length; i++) {\n                if (i + 1 < matchedGroups.length && matchedGroups[i + 1]) {\n                    groups[rule.groups[i]] = matchedGroups[i + 1];\n                }\n            }\n            token.groups = groups;\n        }\n\n        return token;\n    }\n\n    public static tokenizeLine(line: string, context?: CompilationContext): Token[] {\n        const tokens: Token[] = [];\n        while (line.length > 0) {\n            let matched = false;\n            for (const rule of Tokenizer.rules) {\n                const matchedGroups = rule.regExp.exec(line);\n                if (matchedGroups) {\n                    // Discard whitespace, comments, etc.\n                    if (rule.discard !== true) {\n                        tokens.push(Tokenizer.createToken(rule, matchedGroups));\n                    }\n\n                    matched = true;\n                    line = line.substr(matchedGroups[0].length);\n                    break;\n                }\n            }\n\n            if (!matched) {\n                const errorContext: CompilationContext = {\n                    ...context,\n                    text: line,\n                };\n\n                throw new CompilationError(\"InvalidTokenError\", `Invalid token: \"${errorContext.text}\"`, errorContext);\n            }\n        }\n        return tokens;\n    }\n}\n\nexport class Assembler {\n    private static readonly CommandStringToCommand: { [commandName: string]: Command } = {\n        [Syntax.subleqInstruction]: Command.subleqInstruction,\n        [Syntax.dataDirective]: Command.dataDirective,\n    }\n\n    private static isValidNumber(str: string, min: number, max: number): boolean {\n        const value = parseInt(str);\n        return !isNaN(value) && value >= min && value <= max;\n    }\n\n    private static isValidValue(str: string): boolean {\n        return Assembler.isValidNumber(str, Constants.valueMin, Constants.valueMax);\n    }\n\n    private static isValidAddress(str: string): boolean {\n        return Assembler.isValidNumber(str, Constants.addressMin, Constants.addressMax);\n    }\n\n    private static isLabelReference(expression: Expression): expression is LabelReference {\n        return typeof(expression) === \"object\";\n    }\n\n    private static parseAddress(str: string, context: CompilationContext) : number {\n        if (Assembler.isValidAddress(str)) {\n            return parseInt(str);\n        } else {\n            const errorContext: CompilationContext = {\n                ...context,\n                text: str,\n                rangeMin: Constants.addressMin,\n                rangeMax: Constants.addressMax,\n            }\n\n            throw new CompilationError(\"AddressLiteralRangeError\", `Invalid argument: \"${errorContext.text}\" (must be an integer on the range [${errorContext.rangeMin}, ${errorContext.rangeMax}])`, errorContext);\n        }\n    }\n\n    private static parseEscapeCode(escapeCharacter: string, context?: CompilationContext): string {\n        switch (escapeCharacter) {\n            case \"0\":\n                return \"\\0\";\n\n            case \"n\":\n                return \"\\n\";\n\n            case \"\\\\\":\n            case \"'\":\n            case '\"':\n                return escapeCharacter;\n\n            default:\n                {\n                    const errorContext: CompilationContext = {\n                        ...context,\n                        text: `\\\\${escapeCharacter}`,\n                    }\n\n                    throw new CompilationError(\"InvalidEscapeCodeError\", `Invalid escape code: \"${errorContext.text}\"`, errorContext);\n                }\n        }\n    }\n\n    private static parseReference(token: Token, context: CompilationContext): Expression {\n        if (token.groups) {\n            const { name, offset, negation } = token.groups;\n            return {\n                label: name,\n                offset: offset ? parseInt(offset) : 0,\n                ...((negation === \"-\" ? { negated: true } : {})),\n                context,\n            };\n        }\n\n        const errorContext: CompilationContext = {\n            ...context,\n            text: token.raw,\n        };\n\n        throw new CompilationError(\"InternalCompilerError\", `Internal compiler error on token: \"${errorContext.text}\"`, errorContext);\n    }\n\n    private static parseValueExpression(token: Token, context: CompilationContext): Expression | number[] {\n        switch (token.tokenType) {\n            case TokenType.numberLiteral:\n                return Assembler.parseValue(token, context);\n\n            case TokenType.characterLiteral:\n                return Assembler.parseCharacter(token, context);\n\n            case TokenType.reference:\n                return Assembler.parseReference(token, context);\n\n            case TokenType.stringLiteral:\n                return Assembler.parseString(token, context);\n\n            default:\n                {\n                    const errorContext: CompilationContext = {\n                        ...context,\n                        text: token.raw,\n                    }\n\n                    throw new CompilationError(\"InvalidValueExpressionError\", `Expected number, character, string, or reference, but got: \"${errorContext.text}\"`, errorContext);\n                }\n        }\n    }\n\n    private static parseAddressExpression(token: Token, context: CompilationContext): Expression {\n        switch (token.tokenType) {\n            case TokenType.numberLiteral:\n                return Assembler.parseAddress(token.raw, context);\n\n            case TokenType.reference:\n                return Assembler.parseReference(token, context);\n\n            default:\n                {\n                    const errorContext: CompilationContext = {\n                        ...context,\n                        text: token.raw,\n                    }\n\n                    throw new CompilationError(\"InvalidAddressExpressionError\", `Expected number literal or reference, but got: \"${errorContext.text}\"`, errorContext);\n                }\n        }\n    }\n\n    private static parseLineInternal(tokens: Token[], context: CompilationContext): ParsedLine {\n        const labelDefinitions: LabelDefinition[] = [];\n        const expressions: Expression[] = [];\n        let index = 0;\n        let offset = 0;\n        \n        function skipWhiteSpace() {\n            while ((index < tokens.length) && (tokens[index].tokenType === TokenType.whiteSpace)) {\n                index++;\n            }\n        }\n\n        function addLabelDefinitions(base?: Partial<LabelDefinition>) {\n            while (index < tokens.length) {\n                const tokenType = tokens[index].tokenType;\n                if (tokenType === TokenType.label) {\n                    const token = tokens[index];\n                    labelDefinitions.push({\n                        label: token.groups![\"name\"],\n                        offset,\n                        ...base,\n                    });\n    \n                    index++;\n                } else if (tokenType === TokenType.whiteSpace) {\n                    index++;\n                } else {\n                    break;\n                }\n            }\n        }\n\n        // Check for persistent breakpoint indicator at the beginning of the line\n        skipWhiteSpace();\n        let breakpoint: boolean | undefined;\n        if (index < tokens.length && tokens[index].tokenType === TokenType.exclamationMark) {\n            breakpoint = true;\n            index++;\n        }\n\n        // Check for label(s)\n        addLabelDefinitions();\n\n        // Check for command\n        skipWhiteSpace();\n        let command: Command | undefined;\n        if (index < tokens.length) {\n            const commandName = tokens[index++].raw;\n            command = Assembler.CommandStringToCommand[commandName];\n            if (command === undefined) {\n                const errorContext: CompilationContext = {\n                    ...context,\n                    text: commandName,\n                };\n\n                throw new CompilationError(\"InvalidCommandError\", `Unknown command: \"${errorContext.text}\" (valid commands are: \"subleq\" and \".data\")`, errorContext);\n            }\n    \n            // Add arguments\n            let argumentCount = 0;\n            while (index < tokens.length) {\n                // Check for required whitespace/comma\n                if (expressions.length === 0) {\n                    // Whitespace required after command\n                    if (tokens[index].tokenType !== TokenType.whiteSpace) {\n                        const errorContext: CompilationContext = {\n                            ...context,\n                            text: commandName,\n                        };\n\n                        throw new CompilationError(\"MissingWhitespaceError\", `Whitespace is required after \"${errorContext.text}\"`, errorContext);\n                    }\n                } else {\n                    // Whitespace or comma required between arguments\n                    if (index < tokens.length) {\n                        const tokenType = tokens[index].tokenType;\n                        if (tokenType !== TokenType.comma && tokenType !== TokenType.whiteSpace) {\n                            const errorContext: CompilationContext = {\n                                ...context,\n                                text: tokens[index].raw,\n                            };\n    \n                            throw new CompilationError(\"MissingCommaOrWhitespaceError\", `Whitespace or comma required before argument: \"${errorContext.text}\"`, errorContext);\n                        }\n                    }\n    \n                    skipWhiteSpace();\n                    if (index < tokens.length && tokens[index].tokenType === TokenType.comma) {\n                        index++;\n                    }\n                }\n    \n                // Add any inline labels\n                addLabelDefinitions({ inline: true });\n    \n                // Parse the argument\n                if (index < tokens.length) {\n                    switch (command) {\n                        case Command.subleqInstruction:\n                            expressions.push(Assembler.parseAddressExpression(tokens[index], context));\n                            offset++;\n                            break;\n    \n                        case Command.dataDirective:\n                            const parsedValueExpression = Assembler.parseValueExpression(tokens[index], context);\n                            if (Array.isArray(parsedValueExpression)) {\n                                expressions.push(...parsedValueExpression);\n                                offset += parsedValueExpression.length;\n                            } else {\n                                expressions.push(parsedValueExpression);\n                                offset++;\n                            }\n                            break;\n                    }\n\n                    argumentCount++;\n                    index++;\n                }\n            }\n\n            // Check argument count\n            switch (command) {\n                case Command.subleqInstruction:\n                    if (argumentCount < 2 || argumentCount > 3) {\n                        const errorContext: CompilationContext = {\n                            ...context,\n                            number: argumentCount,\n                            rangeMin: 2,\n                            rangeMax: 3,\n                        };\n\n                        throw new CompilationError(\"InvalidSubleqArgumentCountError\", `Invalid number of arguments for \"subleq\": ${errorContext.number} (must be between ${errorContext.rangeMin} and ${errorContext.rangeMax}, inclusive)`, errorContext);\n                    }\n                    break;\n\n                case Command.dataDirective:\n                    if (argumentCount <= 0) {\n                        const errorContext: CompilationContext = {\n                            ...context,\n                            number: argumentCount,\n                            rangeMin: 1,\n                        };\n\n                        throw new CompilationError(\"InvalidDataArgumentCountError\", `Invalid number of arguments for \".data\": ${errorContext.number} (must have at least 1 argument)`, errorContext);\n                    }\n                    break;\n            }\n        }\n\n        if (breakpoint && command !== Command.subleqInstruction) {\n            throw new CompilationError(\"InvalidBreakpointError\", \"Breakpoints are only supported on subleq instructions\", context);\n        }\n\n        return {\n            labelDefinitions,\n            command,\n            expressions,\n            breakpoint,\n        };\n    };\n\n    public static unsignedToSigned(unsigned: number): number {\n        let signed = unsigned & 0x7f;\n        signed += (unsigned & 0x80) ? -128 : 0;\n        return signed;\n    }\n\n    public static signedToUnsigned(signed: number): number {\n        return signed & 0xff;\n    }\n\n    public static parseValue(token: Token, context?: CompilationContext): number {\n        const str = token.raw;\n        if (Assembler.isValidValue(str)) {\n            return Assembler.signedToUnsigned(parseInt(str));\n        } else {\n            const errorContext: CompilationContext = {\n                ...context,\n                text: str,\n                rangeMin: Constants.valueMin,\n                rangeMax: Constants.valueMax,\n            };\n\n            throw new CompilationError(\"ValueRangeError\", `Invalid argument: ${errorContext.text} (must be an integer on the range [${errorContext.rangeMin}, ${errorContext.rangeMax}])`, errorContext);\n        }\n    }\n\n    public static parseCharacter(token: Token, context?: CompilationContext): number {\n        if (!token.groups) {\n            const errorContext: CompilationContext = {\n                ...context,\n                text: token.raw,\n            };\n    \n            throw new CompilationError(\"InternalCompilerError\", `Internal compiler error on token: \"${errorContext.text}\"`, errorContext);\n        }\n\n        const str = token.groups.character;\n        let value: number;\n        if (str[0] === \"\\\\\") {\n            value = Assembler.parseEscapeCode(str[1], context).charCodeAt(0);\n        } else {\n            value = str.charCodeAt(0);\n        }\n\n        if (token.raw[0] === \"-\") {\n            value = Assembler.signedToUnsigned(-value);\n        }\n\n        return value;\n    }\n\n    public static parseString(token: Token, context?: CompilationContext): number[] {\n        if (!token.groups) {\n            const errorContext: CompilationContext = {\n                ...context,\n                text: token.raw,\n            };\n    \n            throw new CompilationError(\"InternalCompilerError\", `Internal compiler error on token: \"${errorContext.text}\"`, errorContext);\n        }\n\n        const input = token.groups.characters;\n        const output: number[] = [];\n        if (input) {\n            for (let i = 0; i < input.length; i++) {\n                const character = input[i];\n                if (character === \"\\\\\") {\n                    const escapeCharacter = input[++i];\n                    output.push(Assembler.parseEscapeCode(escapeCharacter, context).charCodeAt(0));\n                } else {\n                    output.push(character.charCodeAt(0));\n                }\n            }\n\n            // Negate, if needed\n            if (token.raw[0] === \"-\") {\n                for (let i = 0; i < output.length; i++) {\n                    output[i] = Assembler.signedToUnsigned(-output[i]);\n                }\n            }\n        }\n\n        // Terminating zero\n        output.push(0);\n\n        return output;\n    }\n\n    public static parseLine(line: string) {\n        const context = {\n            sourceLineNumber: 1,\n            sourceLine: line,\n        };\n\n        const tokens = Tokenizer.tokenizeLine(line, context);\n        return Assembler.parseLineInternal(tokens, context);\n    }\n\n    public static assemble(lines: string[]): AssembledProgram {\n        const variables: VariableDefinition[] = [];\n        let address = 0;\n        let labels: {[name: string]: number} = {};\n\n        labels[`MAX`] = Constants.addressUserMax;\n        labels[`IN`] = Constants.addressInput;\n        labels[`OUT`] = Constants.addressOutput;\n        labels[`HALT`] = Constants.addressHalt;\n\n        const breakpoints: number[] = [];\n\n        // Correlate address to source line\n        const sourceMap: SourceMapEntry[] = [];\n\n        // Parse expressions (note: this can include unresolved references)\n        const expressions: Expression[] = [];\n        for (let i = 0; i < lines.length; i++) {\n            const line = lines[i];\n            if (line.length > 0) {\n                const context: CompilationContext = {\n                    sourceLineNumber: i + 1,\n                    sourceLine: line,\n                };\n\n                const tokens = Tokenizer.tokenizeLine(line, context);\n                const assembledLine = Assembler.parseLineInternal(tokens, context);\n\n                // Add breakpoint, if desired\n                if (assembledLine.breakpoint) {\n                    breakpoints.push(address);\n                }\n\n                // Add labels, if present\n                for (const { label, offset, inline } of assembledLine.labelDefinitions) {\n                    if (labels[label] !== undefined) {\n                        const errorContext: CompilationContext = {\n                            ...context,\n                            text: `${Syntax.referencePrefix}${label}`,\n                        };\n\n                        throw new CompilationError(\"LabelAlreadyDefinedError\", `Label already defined: \"${errorContext.text}\"`, errorContext);\n                    }\n\n                    const labelAddress = address + offset;\n                    labels[label] = labelAddress;\n\n                    // Variables are labels defined on a \".data\" directive or as *any* inline label\n                    if (inline || assembledLine.command === Command.dataDirective) {\n                        variables.push({\n                            label: `${Syntax.referencePrefix}${label}`,\n                            address: labelAddress,\n                        });\n                    }\n                }\n\n                // Fill in optional addresses\n                const lineExpressions = assembledLine.expressions;\n                if (assembledLine.command !== undefined) {\n                    if (lineExpressions.length > 0) {\n                        lineExpressions.forEach(e => expressions.push(e));\n\n                        let nextAddress = address;\n                        switch (assembledLine.command) {\n                            case Command.subleqInstruction:\n                                nextAddress += Constants.subleqInstructionBytes;\n                                if (lineExpressions.length < 3) {\n                                    expressions.push(nextAddress);\n                                }\n                                break;\n\n                            case Command.dataDirective:\n                                nextAddress += lineExpressions.length;\n                                break;\n                        }\n\n                        // Update source map\n                        // TODO: Consider supporting multiple values/strings in the source map and variable stuff\n                        if (nextAddress !== address) {\n                            sourceMap[address] = {\n                                lineNumber: i,\n                                command: assembledLine.command,\n                                source: line,\n                            };\n\n                            address = nextAddress;\n                        }\n                    } else {\n                        // Should not be possible\n                        const errorContext: CompilationContext = {\n                            ...context,\n                            text: \"(unknown)\",\n                        };\n                \n                        throw new CompilationError(\"InternalCompilerError\", `Internal compiler error on token: \"${errorContext.text}\"`, errorContext);\n                    }\n                }\n            }\n        }\n\n        if (address - 1 > Constants.addressUserMax) {\n            const errorContext: CompilationContext = {\n                number: address,\n                rangeMax: Constants.addressUserMax + 1,\n            };\n\n            throw new CompilationError(\"ProgramTooLargeError\", `Program is too long (maximum size: ${errorContext.rangeMax} bytes; program size: ${errorContext.number} bytes)`, errorContext);\n        }\n\n        // Resolve all values\n        const bytes = [];\n        for (let i = 0; i < expressions.length; i++) {\n            const expression = expressions[i];\n            let expressionValue: number;\n            if (Assembler.isLabelReference(expression)) {\n                expressionValue = labels[expression.label];\n                if (expressionValue === undefined) {\n                    const errorContext: CompilationContext = {\n                        ...(expression.context),\n                        text: `${Syntax.referencePrefix}${expression.label}`,\n                    };\n\n                    throw new CompilationError(\"UndefinedReferenceError\", `Undefined reference: \"${errorContext.text}\"`, errorContext);\n                }\n\n                if (expression.negated) {\n                    expressionValue = Assembler.signedToUnsigned(-expressionValue);\n                }\n\n                expressionValue += expression.offset;\n\n                if (expressionValue < 0 || expressionValue > Constants.addressMax) {\n                    const errorContext: CompilationContext = {\n                        ...(expression.context),\n                        text: `${Syntax.referencePrefix}${expression.label}${expression.offset >= 0 ? \"+\" : \"\"}${expression.offset}`,\n                        number: expressionValue,\n                        rangeMin: Constants.addressMin,\n                        rangeMax: Constants.addressMax,\n                    }\n                    throw new CompilationError(\"AddressReferenceRangeError\", `Address \"${errorContext.text}\" (${errorContext.number}) is outside of valid range of [${errorContext.rangeMin}, ${errorContext.rangeMax}]`, errorContext);\n                }\n            } else {\n                expressionValue = expression;\n            }\n\n            bytes.push(expressionValue);\n        }\n\n        return {\n            bytes,\n            sourceMap,\n            variables,\n            breakpoints,\n        };\n    };\n}\n\nexport interface Variable {\n    label: string;\n    value: number;\n}\n\nexport interface HaltData {\n    cyclesExecuted: number;\n    memoryBytesAccessed: number;\n}\n\nexport interface StateUpdatedData {\n    running: boolean;\n    ip: number;\n    target: number;\n    sourceLineNumber: number;\n    source: string;\n    cyclesExecuted: number;\n    memoryBytesAccessed: number;\n    variables: Variable[];\n}\n\nexport interface EmulatorOptions {\n    readInput?: () => number;\n    writeOutput?: (value: number) => void;\n\n    onHalt?: (data: HaltData) => void;\n    onWriteMemory?: (address: number, byte: number) => void;\n    onStateUpdated?: (data: StateUpdatedData) => void;\n}\n\nexport class Emulator {\n    // State\n    private running = true;\n    private ip = 0;\n\n    // Memory\n    private memory: number[] = [];\n    private initialMemorySnapshot: number[];\n\n    // Metrics\n\n    // Memory access\n    private memoryAccessed: boolean[] = [];\n    private memoryBytesAccessed = 0;\n\n    // Cycle count\n    private cyclesExecuted = 0;\n\n    constructor(private program: AssembledProgram, private callbacks: EmulatorOptions = {}) {\n        const bytes = this.program.bytes;\n        for (let i = 0; i <= Constants.addressMax; i++) {\n            const value = (i < bytes.length) ? bytes[i] : 0;\n            this.memory[i] = value;\n\n            if (this.callbacks.onWriteMemory) {\n                this.callbacks.onWriteMemory(i, value);\n            }\n        }\n\n        // Save initial memory to support resetting\n        this.initialMemorySnapshot = this.memory.slice();\n\n        // Emit initial state info\n        this.stateUpdated();\n    }\n\n    private stateUpdated(): void {\n        if (this.callbacks.onStateUpdated) {\n            // Find source info in source map\n            const sourceMap = this.program.sourceMap;\n            const ip = this.ip;\n            let sourceLineNumber = 0;\n            let source = \"?\";\n            const sourceMapEntry = sourceMap[ip];\n            if (sourceMapEntry) {\n                // Exact match in the source map\n                sourceLineNumber = sourceMapEntry.lineNumber;\n                source = sourceMapEntry.source;\n            } else {\n                // No match in the source map; use the previous line number\n                for (let i = ip; i >= 0; i--) {\n                    const previousEntry = sourceMap[i];\n                    if (previousEntry) {\n                        sourceLineNumber = previousEntry.lineNumber;\n                        break;\n                    }\n                }\n            }\n\n            const variables: Variable[] = [];\n            for (let i = 0; i < this.program.variables.length; i++) {\n                variables.push({\n                    label: this.program.variables[i].label,\n                    value: Assembler.unsignedToSigned(this.memory[this.program.variables[i].address])\n                });\n            }\n\n            this.callbacks.onStateUpdated({\n                running: this.running,\n                ip,\n                target: this.memory[ip],\n                sourceLineNumber,\n                source,\n                cyclesExecuted: this.cyclesExecuted,\n                memoryBytesAccessed: this.memoryBytesAccessed,\n                variables\n            });\n        }\n    }\n\n    private accessMemory(address: number): void {\n        if (!this.memoryAccessed[address]) {\n            this.memoryBytesAccessed++;\n        }\n\n        this.memoryAccessed[address] = true;\n    };\n\n    private readMemory(address: number): number {\n        this.accessMemory(address);\n        return this.memory[address];\n    };\n\n    private writeMemory(address: number, value: number): void {\n        this.accessMemory(address);\n        this.memory[address] = value;\n        if (this.callbacks.onWriteMemory) {\n            this.callbacks.onWriteMemory(address, value);\n        }\n    };\n\n    public isEmpty(): boolean {\n        for (const byte of this.memory) {\n            if (byte !== 0) {\n                return false;\n            }\n        }\n        return true;\n    }\n\n    public isRunning(): boolean {\n        return this.ip >= 0 && (this.ip <= Constants.addressInstructionMax);\n    };\n\n    public getCyclesExecuted(): number {\n        return this.cyclesExecuted;\n    }\n\n    public getMemoryBytesAccessed(): number {\n        return this.memoryBytesAccessed;\n    }\n\n    public step(): void {\n        if (this.isRunning()) {\n            const a = this.readMemory(this.ip++);\n            const b = this.readMemory(this.ip++);\n            const c = this.readMemory(this.ip++);\n\n            // Read operands\n            let input = 0;\n            if (a === Constants.addressInput || b === Constants.addressInput) {\n                this.accessMemory(Constants.addressInput);\n                if (this.callbacks.readInput) {\n                    input = this.callbacks.readInput();\n                }\n            }\n\n            const av = (a === Constants.addressInput) ? input : this.readMemory(a);\n            const bv = (b === Constants.addressInput) ? input : this.readMemory(b);\n\n            // Arithmetic (wraps around on overflow)\n            const result = (av - bv) & 0xff;\n\n            // Write result\n            const resultSigned = Assembler.unsignedToSigned(result);\n            switch (a) {\n                case Constants.addressInput:\n                case Constants.addressHalt:\n                    break;\n\n                case Constants.addressOutput:\n                    this.accessMemory(Constants.addressOutput);\n                    if (this.callbacks.writeOutput) {\n                        this.callbacks.writeOutput(resultSigned);\n                    }\n                    break;\n    \n                default:\n                    this.writeMemory(a, result);\n                    break;\n            }\n\n            // Branch, if necessary\n            if (resultSigned <= 0) {\n                this.ip = c;\n            }\n\n            this.cyclesExecuted++;\n            this.running = this.isRunning();\n            this.stateUpdated();\n\n            if (this.callbacks.onHalt && !this.running) {\n                this.callbacks.onHalt({\n                    cyclesExecuted: this.cyclesExecuted,\n                    memoryBytesAccessed: this.memoryBytesAccessed,\n                });\n            }\n        }\n    };\n\n    public run(): void {\n        while (this.running) {\n            this.step();\n        }\n    };\n\n    /** Resets the emulator's memory back to its initial state. */\n    public reset(): void {\n        // Reset state\n        this.running = true;\n        this.ip = 0;\n        this.memoryAccessed = [];\n        this.memoryBytesAccessed = 0;\n        this.cyclesExecuted = 0;\n\n        // Reset memory\n        for (let i = 0; i <= Constants.addressMax; i++) {\n            const value = this.initialMemorySnapshot[i];\n            if (this.memory[i] !== value) {\n                this.memory[i] = value;\n                if (this.callbacks.onWriteMemory) {\n                    this.callbacks.onWriteMemory(i, value);\n                }\n            }\n        }\n\n        // Broadcast the update\n        this.stateUpdated();\n    }\n}\n", "sic1/client/index.html": "<!DOCTYPE html>\n<html>\n    <head>\n        <meta charset=\"utf-8\">\n        <title>SIC-1</title>\n        <meta name=\"viewport\" content=\"width=device-width, initial-scale=1, shrink-to-fit=no\" />\n        <link rel=\"stylesheet\" href=\"css/main.css\" />\n        <link rel=\"shortcut icon\" href=\"favicon.svg\" />\n    </head>\n    <body>\n        <div id=\"root\"></div>\n        <script type=\"module\" src=\"ts/main.tsx\"></script>\n    </body>\n</html>", "sic1/client/package-lock.json": "{\n  \"name\": \"sic1-client\",\n  \"version\": \"1.11.6\",\n  \"lockfileVersion\": 3,\n  \"requires\": true,\n  \"packages\": {\n    \"\": {\n      \"name\": \"sic1-client\",\n      \"version\": \"1.11.6\",\n      \"dependencies\": {\n        \"backtrace-js\": \"^1.1.3\",\n        \"crs_queue\": \"^3.2.1\",\n        \"lz-string\": \"^1.4.4\",\n        \"react\": \"^18.2.0\",\n        \"react-dom\": \"^18.2.0\",\n        \"react-intl\": \"^6.5.5\",\n        \"react16\": \"^1.0.0\"\n      },\n      \"devDependencies\": {\n        \"@formatjs/cli\": \"^6.2.4\",\n        \"@types/adm-zip\": \"^0.5.5\",\n        \"@types/lz-string\": \"^1.3.34\",\n        \"@types/mocha\": \"^7.0.1\",\n        \"@types/node\": \"^13.7.0\",\n        \"adm-zip\": \"^0.5.10\",\n        \"md2jsx\": \"^1.1.0\",\n        \"mocha\": \"^10.2.0\",\n        \"parcel\": \"^2.11.0\",\n        \"parcel-namer-hashless\": \"^1.0.3\",\n        \"process\": \"^0.11.10\",\n        \"ts-node\": \"^10.9.2\",\n        \"typescript\": \"^5.3.3\"\n      }\n    },\n    \"node_modules/@cspotcode/source-map-support\": {\n      \"version\": \"0.8.1\",\n      \"resolved\": \"https://registry.npmjs.org/@cspotcode/source-map-support/-/source-map-support-0.8.1.tgz\",\n      \"integrity\": \"sha512-IchNf6dN4tHoMFIn/7OE8LWZ19Y6q/67Bmf6vnGREv8RSbBVb9LPJxEcnwrcwX6ixSvaiGoomAUvu4YSxXrVgw==\",\n      \"dev\": true,\n      \"license\": \"MIT\",\n      \"dependencies\": {\n        \"@jridgewell/trace-mapping\": \"0.3.9\"\n      },\n      \"engines\": {\n        \"node\": \">=12\"\n      }\n    },\n    \"node_modules/@formatjs/cli\": {\n      \"version\": \"6.12.2\",\n      \"resolved\": \"https://registry.npmjs.org/@formatjs/cli/-/cli-6.12.2.tgz\",\n      \"integrity\": \"sha512-y215aarLZXei3u1WDRAiet/VajgvUXzvz4ifPENDSPXfIog0aBJKtFvIU7EWbcFWy7rstbn5GcwwQW4F1G3TJg==\",\n      \"dev\": true,\n      \"license\": \"MIT\",\n      \"bin\": {\n        \"formatjs\": \"bin/formatjs\"\n      },\n      \"engines\": {\n        \"node\": \">= 16\"\n      },\n      \"peerDependencies\": {\n        \"@glimmer/syntax\": \"^0.84.3 || ^0.95.0\",\n        \"@vue/compiler-core\": \"3.5.27\",\n        \"content-tag\": \"^4.1.0\",\n        \"vue\": \"3.5.27\"\n      },\n      \"peerDependenciesMeta\": {\n        \"@glimmer/env\": {\n          \"optional\": true\n        },\n        \"@glimmer/reference\": {\n          \"optional\": true\n        },\n        \"@glimmer/syntax\": {\n          \"optional\": true\n        },\n        \"@glimmer/validator\": {\n          \"optional\": true\n        },\n        \"@vue/compiler-core\": {\n          \"optional\": true\n        },\n        \"content-tag\": {\n          \"optional\": true\n        },\n        \"vue\": {\n          \"optional\": true\n        }\n      }\n    },\n    \"node_modules/@formatjs/ecma402-abstract\": {\n      \"version\": \"2.2.4\",\n      \"resolved\": \"https://registry.npmjs.org/@formatjs/ecma402-abstract/-/ecma402-abstract-2.2.4.tgz\",\n      \"integrity\": \"sha512-lFyiQDVvSbQOpU+WFd//ILolGj4UgA/qXrKeZxdV14uKiAUiPAtX6XAn7WBCRi7Mx6I7EybM9E5yYn4BIpZWYg==\",\n      \"license\": \"MIT\",\n      \"dependencies\": {\n        \"@formatjs/fast-memoize\": \"2.2.3\",\n        \"@formatjs/intl-localematcher\": \"0.5.8\",\n        \"tslib\": \"2\"\n      }\n    },\n    \"node_modules/@formatjs/fast-memoize\": {\n      \"version\": \"2.2.3\",\n      \"resolved\": \"https://registry.npmjs.org/@formatjs/fast-memoize/-/fast-memoize-2.2.3.tgz\",\n      \"integrity\": \"sha512-3jeJ+HyOfu8osl3GNSL4vVHUuWFXR03Iz9jjgI7RwjG6ysu/Ymdr0JRCPHfF5yGbTE6JCrd63EpvX1/WybYRbA==\",\n      \"license\": \"MIT\",\n      \"dependencies\": {\n        \"tslib\": \"2\"\n      }\n    },\n    \"node_modules/@formatjs/icu-messageformat-parser\": {\n      \"version\": \"2.9.4\",\n      \"resolved\": \"https://registry.npmjs.org/@formatjs/icu-messageformat-parser/-/icu-messageformat-parser-2.9.4.tgz\",\n      \"integrity\": \"sha512-Tbvp5a9IWuxUcpWNIW6GlMQYEc4rwNHR259uUFoKWNN1jM9obf9Ul0e+7r7MvFOBNcN+13K7NuKCKqQiAn1QEg==\",\n      \"license\": \"MIT\",\n      \"dependencies\": {\n        \"@formatjs/ecma402-abstract\": \"2.2.4\",\n        \"@formatjs/icu-skeleton-parser\": \"1.8.8\",\n        \"tslib\": \"2\"\n      }\n    },\n    \"node_modules/@formatjs/icu-skeleton-parser\": {\n      \"version\": \"1.8.8\",\n      \"resolved\": \"https://registry.npmjs.org/@formatjs/icu-skeleton-parser/-/icu-skeleton-parser-1.8.8.tgz\",\n      \"integrity\": \"sha512-vHwK3piXwamFcx5YQdCdJxUQ1WdTl6ANclt5xba5zLGDv5Bsur7qz8AD7BevaKxITwpgDeU0u8My3AIibW9ywA==\",\n      \"license\": \"MIT\",\n      \"dependencies\": {\n        \"@formatjs/ecma402-abstract\": \"2.2.4\",\n        \"tslib\": \"2\"\n      }\n    },\n    \"node_modules/@formatjs/intl\": {\n      \"version\": \"2.10.15\",\n      \"resolved\": \"https://registry.npmjs.org/@formatjs/intl/-/intl-2.10.15.tgz\",\n      \"integrity\": \"sha512-i6+xVqT+6KCz7nBfk4ybMXmbKO36tKvbMKtgFz9KV+8idYFyFbfwKooYk8kGjyA5+T5f1kEPQM5IDLXucTAQ9g==\",\n      \"license\": \"MIT\",\n      \"dependencies\": {\n        \"@formatjs/ecma402-abstract\": \"2.2.4\",\n        \"@formatjs/fast-memoize\": \"2.2.3\",\n        \"@formatjs/icu-messageformat-parser\": \"2.9.4\",\n        \"@formatjs/intl-displaynames\": \"6.8.5\",\n        \"@formatjs/intl-listformat\": \"7.7.5\",\n        \"intl-messageformat\": \"10.7.7\",\n        \"tslib\": \"2\"\n      },\n      \"peerDependencies\": {\n        \"typescript\": \"^4.7 || 5\"\n      },\n      \"peerDependenciesMeta\": {\n        \"typescript\": {\n          \"optional\": true\n        }\n      }\n    },\n    \"node_modules/@formatjs/intl-displaynames\": {\n      \"version\": \"6.8.5\",\n      \"resolved\": \"https://registry.npmjs.org/@formatjs/intl-displaynames/-/intl-displaynames-6.8.5.tgz\",\n      \"integrity\": \"sha512-85b+GdAKCsleS6cqVxf/Aw/uBd+20EM0wDpgaxzHo3RIR3bxF4xCJqH/Grbzx8CXurTgDDZHPdPdwJC+May41w==\",\n      \"license\": \"MIT\",\n      \"dependencies\": {\n        \"@formatjs/ecma402-abstract\": \"2.2.4\",\n        \"@formatjs/intl-localematcher\": \"0.5.8\",\n        \"tslib\": \"2\"\n      }\n    },\n    \"node_modules/@formatjs/intl-listformat\": {\n      \"version\": \"7.7.5\",\n      \"resolved\": \"https://registry.npmjs.org/@formatjs/intl-listformat/-/intl-listformat-7.7.5.tgz\",\n      \"integrity\": \"sha512-Wzes10SMNeYgnxYiKsda4rnHP3Q3II4XT2tZyOgnH5fWuHDtIkceuWlRQNsvrI3uiwP4hLqp2XdQTCsfkhXulg==\",\n      \"license\": \"MIT\",\n      \"dependencies\": {\n        \"@formatjs/ecma402-abstract\": \"2.2.4\",\n        \"@formatjs/intl-localematcher\": \"0.5.8\",\n        \"tslib\": \"2\"\n      }\n    },\n    \"node_modules/@formatjs/intl-localematcher\": {\n      \"version\": \"0.5.8\",\n      \"resolved\": \"https://registry.npmjs.org/@formatjs/intl-localematcher/-/intl-localematcher-0.5.8.tgz\",\n      \"integrity\": \"sha512-I+WDNWWJFZie+jkfkiK5Mp4hEDyRSEvmyfYadflOno/mmKJKcB17fEpEH0oJu/OWhhCJ8kJBDz2YMd/6cDl7Mg==\",\n      \"license\": \"MIT\",\n      \"dependencies\": {\n        \"tslib\": \"2\"\n      }\n    },\n    \"node_modules/@jridgewell/resolve-uri\": {\n      \"version\": \"3.1.2\",\n      \"resolved\": \"https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.2.tgz\",\n      \"integrity\": \"sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw==\",\n      \"dev\": true,\n      \"license\": \"MIT\",\n      \"engines\": {\n        \"node\": \">=6.0.0\"\n      }\n    },\n    \"node_modules/@jridgewell/sourcemap-codec\": {\n      \"version\": \"1.6.0\",\n      \"resolved\": \"https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.6.0.tgz\",\n      \"integrity\": \"sha512-T7jf+5zgsZHwNJ4lvQ7/aezbyk0nNX+zJVWpmHA7VYsEx7a7qr5Rg5IbtJFqkgze5Y2sruq1RUY8Q837Od7iFw==\",\n      \"dev\": true,\n      \"license\": \"MIT\"\n    },\n    \"node_modules/@jridgewell/trace-mapping\": {\n      \"version\": \"0.3.9\",\n      \"resolved\": \"https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.9.tgz\",\n      \"integrity\": \"sha512-3Belt6tdc8bPgAtbcmdtNJlirVoTmEb5e2gC94PnkwEW9jI6CAHUeoG85tjWP5WquqfavoMtMwiG4P926ZKKuQ==\",\n      \"dev\": true,\n      \"license\": \"MIT\",\n      \"dependencies\": {\n        \"@jridgewell/resolve-uri\": \"^3.0.3\",\n        \"@jridgewell/sourcemap-codec\": \"^1.4.10\"\n      }\n    },\n    \"node_modules/@lezer/common\": {\n      \"version\": \"1.5.4\",\n      \"resolved\": \"https://registry.npmjs.org/@lezer/common/-/common-1.5.4.tgz\",\n      \"integrity\": \"sha512-xt3Q4z64xM+xhg4M7NXqw1N//1O74bUFo5kz6fwMeC4qwxSuRdwkYSmjcqCEEKYkNw5e67f2hcNqBoNERAEU0w==\",\n      \"dev\": true,\n      \"license\": \"MIT\"\n    },\n    \"node_modules/@lezer/lr\": {\n      \"version\": \"1.4.11\",\n      \"resolved\": \"https://registry.npmjs.org/@lezer/lr/-/lr-1.4.11.tgz\",\n      \"integrity\": \"sha512-UwgZcl1R66H2hDzBrA7kWyYmX6s8p5TQ+e/t7CuvgCtBEPxbEPaHYHu+pJBvTvDotEJpuQkJjbXuHiw5Cixxgw==\",\n      \"dev\": true,\n      \"license\": \"MIT\",\n      \"dependencies\": {\n        \"@lezer/common\": \"^1.0.0\"\n      }\n    },\n    \"node_modules/@lmdb/lmdb-darwin-arm64\": {\n      \"version\": \"2.8.5\",\n      \"resolved\": \"https://registry.npmjs.org/@lmdb/lmdb-darwin-arm64/-/lmdb-darwin-arm64-2.8.5.tgz\",\n      \"integrity\": \"sha512-KPDeVScZgA1oq0CiPBcOa3kHIqU+pTOwRFDIhxvmf8CTNvqdZQYp5cCKW0bUk69VygB2PuTiINFWbY78aR2pQw==\",\n      \"cpu\": [\n        \"arm64\"\n      ],\n      \"dev\": true,\n      \"license\": \"MIT\",\n      \"optional\": true,\n      \"os\": [\n        \"darwin\"\n      ]\n    },\n    \"node_modules/@lmdb/lmdb-darwin-x64\": {\n      \"version\": \"2.8.5\",\n      \"resolved\": \"https://registry.npmjs.org/@lmdb/lmdb-darwin-x64/-/lmdb-darwin-x64-2.8.5.tgz\",\n      \"integrity\": \"sha512-w/sLhN4T7MW1nB3R/U8WK5BgQLz904wh+/SmA2jD8NnF7BLLoUgflCNxOeSPOWp8geP6nP/+VjWzZVip7rZ1ug==\",\n      \"cpu\": [\n        \"x64\"\n      ],\n      \"dev\": true,\n      \"license\": \"MIT\",\n      \"optional\": true,\n      \"os\": [\n        \"darwin\"\n      ]\n    },\n    \"node_modules/@lmdb/lmdb-linux-arm\": {\n      \"version\": \"2.8.5\",\n      \"resolved\": \"https://registry.npmjs.org/@lmdb/lmdb-linux-arm/-/lmdb-linux-arm-2.8.5.tgz\",\n      \"integrity\": \"sha512-c0TGMbm2M55pwTDIfkDLB6BpIsgxV4PjYck2HiOX+cy/JWiBXz32lYbarPqejKs9Flm7YVAKSILUducU9g2RVg==\",\n      \"cpu\": [\n        \"arm\"\n      ],\n      \"dev\": true,\n      \"license\": \"MIT\",\n      \"optional\": true,\n      \"os\": [\n        \"linux\"\n      ]\n    },\n    \"node_modules/@lmdb/lmdb-linux-arm64\": {\n      \"version\": \"2.8.5\",\n      \"resolved\": \"https://registry.npmjs.org/@lmdb/lmdb-linux-arm64/-/lmdb-linux-arm64-2.8.5.tgz\",\n      \"integrity\": \"sha512-vtbZRHH5UDlL01TT5jB576Zox3+hdyogvpcbvVJlmU5PdL3c5V7cj1EODdh1CHPksRl+cws/58ugEHi8bcj4Ww==\",\n      \"cpu\": [\n        \"arm64\"\n      ],\n      \"dev\": true,\n      \"license\": \"MIT\",\n      \"optional\": true,\n      \"os\": [\n        \"linux\"\n      ]\n    },\n    \"node_modules/@lmdb/lmdb-linux-x64\": {\n      \"version\": \"2.8.5\",\n      \"resolved\": \"https://registry.npmjs.org/@lmdb/lmdb-linux-x64/-/lmdb-linux-x64-2.8.5.tgz\",\n      \"integrity\": \"sha512-Xkc8IUx9aEhP0zvgeKy7IQ3ReX2N8N1L0WPcQwnZweWmOuKfwpS3GRIYqLtK5za/w3E60zhFfNdS+3pBZPytqQ==\",\n      \"cpu\": [\n        \"x64\"\n      ],\n      \"dev\": true,\n      \"license\": \"MIT\",\n      \"optional\": true,\n      \"os\": [\n        \"linux\"\n      ]\n    },\n    \"node_modules/@lmdb/lmdb-win32-x64\": {\n      \"version\": \"2.8.5\",\n      \"resolved\": \"https://registry.npmjs.org/@lmdb/lmdb-win32-x64/-/lmdb-win32-x64-2.8.5.tgz\",\n      \"integrity\": \"sha512-4wvrf5BgnR8RpogHhtpCPJMKBmvyZPhhUtEwMJbXh0ni2BucpfF07jlmyM11zRqQ2XIq6PbC2j7W7UCCcm1rRQ==\",\n      \"cpu\": [\n        \"x64\"\n      ],\n      \"dev\": true,\n      \"license\": \"MIT\",\n      \"optional\": true,\n      \"os\": [\n        \"win32\"\n      ]\n    },\n    \"node_modules/@mischnic/json-sourcemap\": {\n      \"version\": \"0.1.1\",\n      \"resolved\": \"https://registry.npmjs.org/@mischnic/json-sourcemap/-/json-sourcemap-0.1.1.tgz\",\n      \"integrity\": \"sha512-iA7+tyVqfrATAIsIRWQG+a7ZLLD0VaOCKV2Wd/v4mqIU3J9c4jx9p7S0nw1XH3gJCKNBOOwACOPYYSUu9pgT+w==\",\n      \"dev\": true,\n      \"license\": \"MIT\",\n      \"dependencies\": {\n        \"@lezer/common\": \"^1.0.0\",\n        \"@lezer/lr\": \"^1.0.0\",\n        \"json5\": \"^2.2.1\"\n      },\n      \"engines\": {\n        \"node\": \">=12.0.0\"\n      }\n    },\n    \"node_modules/@msgpackr-extract/msgpackr-extract-darwin-arm64\": {\n      \"version\": \"3.0.4\",\n      \"resolved\": \"https://registry.npmjs.org/@msgpackr-extract/msgpackr-extract-darwin-arm64/-/msgpackr-extract-darwin-arm64-3.0.4.tgz\",\n      \"integrity\": \"sha512-LCkGo6JDfaBhgST7UpPWgNgLINpcpabaHfyz5OBx75nUYxBsaEPxjnyNjWpeb/xBup/682QnBfRBy2/LvPutZQ==\",\n      \"cpu\": [\n        \"arm64\"\n      ],\n      \"dev\": true,\n      \"license\": \"MIT\",\n      \"optional\": true,\n      \"os\": [\n        \"darwin\"\n      ]\n    },\n    \"node_modules/@msgpackr-extract/msgpackr-extract-darwin-x64\": {\n      \"version\": \"3.0.4\",\n      \"resolved\": \"https://registry.npmjs.org/@msgpackr-extract/msgpackr-extract-darwin-x64/-/msgpackr-extract-darwin-x64-3.0.4.tgz\",\n      \"integrity\": \"sha512-zExlW9zUJKZH/tOtVMttwjKa4Xm/3KcNjnE3dPN92uCktwavMxpgCA3MoJK/DOnTWsQgo224OaST27/mPNAf+w==\",\n      \"cpu\": [\n        \"x64\"\n      ],\n      \"dev\": true,\n      \"license\": \"MIT\",\n      \"optional\": true,\n      \"os\": [\n        \"darwin\"\n      ]\n    },\n    \"node_modules/@msgpackr-extract/msgpackr-extract-linux-arm\": {\n      \"version\": \"3.0.4\",\n      \"resolved\": \"https://registry.npmjs.org/@msgpackr-extract/msgpackr-extract-linux-arm/-/msgpackr-extract-linux-arm-3.0.4.tgz\",\n      \"integrity\": \"sha512-Tg3yX65f5GbtXLkrYEHE5oibZG9epyYWas7FogTTEJeDEF9JlXJzKgXaNhT3UXlTOeA+AfZpYZYZ0uPj7Cfquw==\",\n      \"cpu\": [\n        \"arm\"\n      ],\n      \"dev\": true,\n      \"license\": \"MIT\",\n      \"optional\": true,\n      \"os\": [\n        \"linux\"\n      ]\n    },\n    \"node_modules/@msgpackr-extract/msgpackr-extract-linux-arm64\": {\n      \"version\": \"3.0.4\",\n      \"resolved\": \"https://registry.npmjs.org/@msgpackr-extract/msgpackr-extract-linux-arm64/-/msgpackr-extract-linux-arm64-3.0.4.tgz\",\n      \"integrity\": \"sha512-dgX0P/9wGPJeHFBG+ZmhgE6bmtMt7NP5CRBGyyktpopdk/mW4POnrpQsSLtKI1dwpc+pPLuXHDh6vvskyQE/sw==\",\n      \"cpu\": [\n        \"arm64\"\n      ],\n      \"dev\": true,\n      \"license\": \"MIT\",\n      \"optional\": true,\n      \"os\": [\n        \"linux\"\n      ]\n    },\n    \"node_modules/@msgpackr-extract/msgpackr-extract-linux-x64\": {\n      \"version\": \"3.0.4\",\n      \"resolved\": \"https://registry.npmjs.org/@msgpackr-extract/msgpackr-extract-linux-x64/-/msgpackr-extract-linux-x64-3.0.4.tgz\",\n      \"integrity\": \"sha512-8TNXMEjJc3QEy7R/x1INhgiU+XakDAFUzBhaz7+Rbrs8NH5UQeHQxxmzsSBJGyV6I1jW79undiQm8tOI+D+8FQ==\",\n      \"cpu\": [\n        \"x64\"\n      ],\n      \"dev\": true,\n      \"license\": \"MIT\",\n      \"optional\": true,\n      \"os\": [\n        \"linux\"\n      ]\n    },\n    \"node_modules/@msgpackr-extract/msgpackr-extract-win32-x64\": {\n      \"version\": \"3.0.4\",\n      \"resolved\": \"https://registry.npmjs.org/@msgpackr-extract/msgpackr-extract-win32-x64/-/msgpackr-extract-win32-x64-3.0.4.tgz\",\n      \"integrity\": \"sha512-CmCXPQrkbwExx3j946/PtHWHbYJiCRBRDl4BlkRQcJB/YOwQxJRTpoo7aTsortjgoJ1x7opzTSxn7C+ASSLVjQ==\",\n      \"cpu\": [\n        \"x64\"\n      ],\n      \"dev\": true,\n      \"license\": \"MIT\",\n      \"optional\": true,\n      \"os\": [\n        \"win32\"\n      ]\n    },\n    \"node_modules/@parcel/bundler-default\": {\n      \"version\": \"2.16.4\",\n      \"resolved\": \"https://registry.npmjs.org/@parcel/bundler-default/-/bundler-default-2.16.4.tgz\",\n      \"integrity\": \"sha512-Nb8peNvhfm1+660CLwssWh4weY+Mv6vEGS6GPKqzJmTMw50udi0eS1YuWFzvmhSiu1KsYcUD37mqQ1LuIDtWoA==\",\n      \"dev\": true,\n      \"license\": \"MIT\",\n      \"dependencies\": {\n        \"@parcel/diagnostic\": \"2.16.4\",\n        \"@parcel/graph\": \"3.6.4\",\n        \"@parcel/plugin\": \"2.16.4\",\n        \"@parcel/rust\": \"2.16.4\",\n        \"@parcel/utils\": \"2.16.4\",\n        \"nullthrows\": \"^1.1.1\"\n      },\n      \"engines\": {\n        \"node\": \">= 16.0.0\",\n        \"parcel\": \"^2.16.4\"\n      },\n      \"funding\": {\n        \"type\": \"opencollective\",\n        \"url\": \"https://opencollective.com/parcel\"\n      }\n    },\n    \"node_modules/@parcel/cache\": {\n      \"version\": \"2.16.4\",\n      \"resolved\": \"https://registry.npmjs.org/@parcel/cache/-/cache-2.16.4.tgz\",\n      \"integrity\": \"sha512-+uCyeElSga2MBbmbXpIj/WVKH7TByCrKaxtHbelfKKIJpYMgEHVjO4cuc7GUfTrUAmRUS8ZGvnX7Etgq6/jQhw==\",\n      \"dev\": true,\n      \"license\": \"MIT\",\n      \"dependencies\": {\n        \"@parcel/fs\": \"2.16.4\",\n        \"@parcel/logger\": \"2.16.4\",\n        \"@parcel/utils\": \"2.16.4\",\n        \"lmdb\": \"2.8.5\"\n      },\n      \"engines\": {\n        \"node\": \">= 16.0.0\"\n      },\n      \"funding\": {\n        \"type\": \"opencollective\",\n        \"url\": \"https://opencollective.com/parcel\"\n      },\n      \"peerDependencies\": {\n        \"@parcel/core\": \"^2.16.4\"\n      }\n    },\n    \"node_modules/@parcel/codeframe\": {\n      \"version\": \"2.16.4\",\n      \"resolved\": \"https://registry.npmjs.org/@parcel/codeframe/-/codeframe-2.16.4.tgz\",\n      \"integrity\": \"sha512-s64aMfOJoPrXhKH+Y98ahX0O8aXWvTR+uNlOaX4yFkpr4FFDnviLcGngDe/Yo4Qq2FJZ0P6dNswbJTUH9EGxkQ==\",\n      \"dev\": true,\n      \"license\": \"MIT\",\n      \"dependencies\": {\n        \"chalk\": \"^4.1.2\"\n      },\n      \"engines\": {\n        \"node\": \">= 16.0.0\"\n      },\n      \"funding\": {\n        \"type\": \"opencollective\",\n        \"url\": \"https://opencollective.com/parcel\"\n      }\n    },\n    \"node_modules/@parcel/compressor-raw\": {\n      \"version\": \"2.16.4\",\n      \"resolved\": \"https://registry.npmjs.org/@parcel/compressor-raw/-/compressor-raw-2.16.4.tgz\",\n      \"integrity\": \"sha512-IK8IpNhw61B2HKgA1JhGhO9y+ZJFRZNTEmvhN1NdLdPqvgEXm2EunT+m6D9z7xeoeT6XnUKqM0eRckEdD0OXbA==\",\n      \"dev\": true,\n      \"license\": \"MIT\",\n      \"dependencies\": {\n        \"@parcel/plugin\": \"2.16.4\"\n      },\n      \"engines\": {\n        \"node\": \">= 16.0.0\",\n        \"parcel\": \"^2.16.4\"\n      },\n      \"funding\": {\n        \"type\": \"opencollective\",\n        \"url\": \"https://opencollective.com/parcel\"\n      }\n    },\n    \"node_modules/@parcel/config-default\": {\n      \"version\": \"2.16.4\",\n      \"resolved\": \"https://registry.npmjs.org/@parcel/config-default/-/config-default-2.16.4.tgz\",\n      \"integrity\": \"sha512-kBxuTY/5trEVnvXk92l7LVkYjNuz3SaqWymFhPjEnc8GY4ZVdcWrWdXWTB9hUhpmRYJctFCyGvM0nN05JTiM2g==\",\n      \"dev\": true,\n      \"license\": \"MIT\",\n      \"dependencies\": {\n        \"@parcel/bundler-default\": \"2.16.4\",\n        \"@parcel/compressor-raw\": \"2.16.4\",\n        \"@parcel/namer-default\": \"2.16.4\",\n        \"@parcel/optimizer-css\": \"2.16.4\",\n        \"@parcel/optimizer-html\": \"2.16.4\",\n        \"@parcel/optimizer-image\": \"2.16.4\",\n        \"@parcel/optimizer-svg\": \"2.16.4\",\n        \"@parcel/optimizer-swc\": \"2.16.4\",\n        \"@parcel/packager-css\": \"2.16.4\",\n        \"@parcel/packager-html\": \"2.16.4\",\n        \"@parcel/packager-js\": \"2.16.4\",\n        \"@parcel/packager-raw\": \"2.16.4\",\n        \"@parcel/packager-svg\": \"2.16.4\",\n        \"@parcel/packager-wasm\": \"2.16.4\",\n        \"@parcel/reporter-dev-server\": \"2.16.4\",\n        \"@parcel/resolver-default\": \"2.16.4\",\n        \"@parcel/runtime-browser-hmr\": \"2.16.4\",\n        \"@parcel/runtime-js\": \"2.16.4\",\n        \"@parcel/runtime-rsc\": \"2.16.4\",\n        \"@parcel/runtime-service-worker\": \"2.16.4\",\n        \"@parcel/transformer-babel\": \"2.16.4\",\n        \"@parcel/transformer-css\": \"2.16.4\",\n        \"@parcel/transformer-html\": \"2.16.4\",\n        \"@parcel/transformer-image\": \"2.16.4\",\n        \"@parcel/transformer-js\": \"2.16.4\",\n        \"@parcel/transformer-json\": \"2.16.4\",\n        \"@parcel/transformer-node\": \"2.16.4\",\n        \"@parcel/transformer-postcss\": \"2.16.4\",\n        \"@parcel/transformer-posthtml\": \"2.16.4\",\n        \"@parcel/transformer-raw\": \"2.16.4\",\n        \"@parcel/transformer-react-refresh-wrap\": \"2.16.4\",\n        \"@parcel/transformer-svg\": \"2.16.4\"\n      },\n      \"funding\": {\n        \"type\": \"opencollective\",\n        \"url\": \"https://opencollective.com/parcel\"\n      },\n      \"peerDependencies\": {\n        \"@parcel/core\": \"^2.16.4\"\n      }\n    },\n    \"node_modules/@parcel/core\": {\n      \"version\": \"2.16.4\",\n      \"resolved\": \"https://registry.npmjs.org/@parcel/core/-/core-2.16.4.tgz\",\n      \"integrity\": \"sha512-a0CgrW5A5kwuSu5J1RFRoMQaMs9yagvfH2jJMYVw56+/7NRI4KOtu612SG9Y1ERWfY55ZwzyFxtLWvD6LO+Anw==\",\n      \"dev\": true,\n      \"license\": \"MIT\",\n      \"dependencies\": {\n        \"@mischnic/json-sourcemap\": \"^0.1.1\",\n        \"@parcel/cache\": \"2.16.4\",\n        \"@parcel/diagnostic\": \"2.16.4\",\n        \"@parcel/events\": \"2.16.4\",\n        \"@parcel/feature-flags\": \"2.16.4\",\n        \"@parcel/fs\": \"2.16.4\",\n        \"@parcel/graph\": \"3.6.4\",\n        \"@parcel/logger\": \"2.16.4\",\n        \"@parcel/package-manager\": \"2.16.4\",\n        \"@parcel/plugin\": \"2.16.4\",\n        \"@parcel/profiler\": \"2.16.4\",\n        \"@parcel/rust\": \"2.16.4\",\n        \"@parcel/source-map\": \"^2.1.1\",\n        \"@parcel/types\": \"2.16.4\",\n        \"@parcel/utils\": \"2.16.4\",\n        \"@parcel/workers\": \"2.16.4\",\n        \"base-x\": \"^3.0.11\",\n        \"browserslist\": \"^4.24.5\",\n        \"clone\": \"^2.1.2\",\n        \"dotenv\": \"^16.5.0\",\n        \"dotenv-expand\": \"^11.0.7\",\n        \"json5\": \"^2.2.3\",\n        \"msgpackr\": \"^1.11.2\",\n        \"nullthrows\": \"^1.1.1\",\n        \"semver\": \"^7.7.1\"\n      },\n      \"engines\": {\n        \"node\": \">= 16.0.0\"\n      },\n      \"funding\": {\n        \"type\": \"opencollective\",\n        \"url\": \"https://opencollective.com/parcel\"\n      }\n    },\n    \"node_modules/@parcel/diagnostic\": {\n      \"version\": \"2.16.4\",\n      \"resolved\": \"https://registry.npmjs.org/@parcel/diagnostic/-/diagnostic-2.16.4.tgz\",\n      \"integrity\": \"sha512-YN5CfX7lFd6yRLxyZT4Sj3sR6t7nnve4TdXSIqapXzQwL7Bw+sj79D95wTq2rCm3mzk5SofGxFAXul2/nG6gcQ==\",\n      \"dev\": true,\n      \"license\": \"MIT\",\n      \"dependencies\": {\n        \"@mischnic/json-sourcemap\": \"^0.1.1\",\n        \"nullthrows\": \"^1.1.1\"\n      },\n      \"engines\": {\n        \"node\": \">= 16.0.0\"\n      },\n      \"funding\": {\n        \"type\": \"opencollective\",\n        \"url\": \"https://opencollective.com/parcel\"\n      }\n    },\n    \"node_modules/@parcel/error-overlay\": {\n      \"version\": \"2.16.4\",\n      \"resolved\": \"https://registry.npmjs.org/@parcel/error-overlay/-/error-overlay-2.16.4.tgz\",\n      \"integrity\": \"sha512-e8KYKnMsfmQnqIhsUWBUZAXlDK30wkxsAGle1tZ0gOdoplaIdVq/WjGPatHLf6igLM76c3tRn2vw8jZFput0jw==\",\n      \"dev\": true,\n      \"license\": \"MIT\",\n      \"engines\": {\n        \"node\": \">= 16.0.0\"\n      },\n      \"funding\": {\n        \"type\": \"opencollective\",\n        \"url\": \"https://opencollective.com/parcel\"\n      }\n    },\n    \"node_modules/@parcel/events\": {\n      \"version\": \"2.16.4\",\n      \"resolved\": \"https://registry.npmjs.org/@parcel/events/-/events-2.16.4.tgz\",\n      \"integrity\": \"sha512-slWQkBRAA7o0cN0BLEd+yCckPmlVRVhBZn5Pn6ktm4EzEtrqoMzMeJOxxH8TXaRzrQDYnTcnYIHFgXWd4kkUfg==\",\n      \"dev\": true,\n      \"license\": \"MIT\",\n      \"engines\": {\n        \"node\": \">= 16.0.0\"\n      },\n      \"funding\": {\n        \"type\": \"opencollective\",\n        \"url\": \"https://opencollective.com/parcel\"\n      }\n    },\n    \"node_modules/@parcel/feature-flags\": {\n      \"version\": \"2.16.4\",\n      \"resolved\": \"https://registry.npmjs.org/@parcel/feature-flags/-/feature-flags-2.16.4.tgz\",\n      \"integrity\": \"sha512-nYdx53siKPLYikHHxfzgjzzgxdrjquK6DMnuSgOTyIdRG4VHdEN0+NqKijRLuVgiUFo/dtxc2h+amwqFENMw8w==\",\n      \"dev\": true,\n      \"license\": \"MIT\",\n      \"engines\": {\n        \"node\": \">= 16.0.0\"\n      },\n      \"funding\": {\n        \"type\": \"opencollective\",\n        \"url\": \"https://opencollective.com/parcel\"\n      }\n    },\n    \"node_modules/@parcel/fs\": {\n      \"version\": \"2.16.4\",\n      \"resolved\": \"https://registry.npmjs.org/@parcel/fs/-/fs-2.16.4.tgz\",\n      \"integrity\": \"sha512-maCMOiVn7oJYZlqlfxgLne8n6tSktIT1k0AeyBp4UGWCXyeJUJ+nL7QYShFpKNLtMLeF0cEtgwRAknWzbcDS1g==\",\n      \"dev\": true,\n      \"license\": \"MIT\",\n      \"dependencies\": {\n        \"@parcel/feature-flags\": \"2.16.4\",\n        \"@parcel/rust\": \"2.16.4\",\n        \"@parcel/types-internal\": \"2.16.4\",\n        \"@parcel/utils\": \"2.16.4\",\n        \"@parcel/watcher\": \"^2.0.7\",\n        \"@parcel/workers\": \"2.16.4\"\n      },\n      \"engines\": {\n        \"node\": \">= 16.0.0\"\n      },\n      \"funding\": {\n        \"type\": \"opencollective\",\n        \"url\": \"https://opencollective.com/parcel\"\n      },\n      \"peerDependencies\": {\n        \"@parcel/core\": \"^2.16.4\"\n      }\n    },\n    \"node_modules/@parcel/graph\": {\n      \"version\": \"3.6.4\",\n      \"resolved\": \"https://registry.npmjs.org/@parcel/graph/-/graph-3.6.4.tgz\",\n      \"integrity\": \"sha512-Cj9yV+/k88kFhE+D+gz0YuNRpvNOCVDskO9pFqkcQhGbsGq6kg2XpZ9V7HlYraih31xf8Vb589bZOwjKIiHixQ==\",\n      \"dev\": true,\n      \"license\": \"MIT\",\n      \"dependencies\": {\n        \"@parcel/feature-flags\": \"2.16.4\",\n        \"nullthrows\": \"^1.1.1\"\n      },\n      \"engines\": {\n        \"node\": \">= 16.0.0\"\n      },\n      \"funding\": {\n        \"type\": \"opencollective\",\n        \"url\": \"https://opencollective.com/parcel\"\n      }\n    },\n    \"node_modules/@parcel/logger\": {\n      \"version\": \"2.16.4\",\n      \"resolved\": \"https://registry.npmjs.org/@parcel/logger/-/logger-2.16.4.tgz\",\n      \"integrity\": \"sha512-QR8QLlKo7xAy9JBpPDAh0RvluaixqPCeyY7Fvo2K7hrU3r85vBNNi06pHiPbWoDmB4x1+QoFwMaGnJOHR+/fMA==\",\n      \"dev\": true,\n      \"license\": \"MIT\",\n      \"dependencies\": {\n        \"@parcel/diagnostic\": \"2.16.4\",\n        \"@parcel/events\": \"2.16.4\"\n      },\n      \"engines\": {\n        \"node\": \">= 16.0.0\"\n      },\n      \"funding\": {\n        \"type\": \"opencollective\",\n        \"url\": \"https://opencollective.com/parcel\"\n      }\n    },\n    \"node_modules/@parcel/markdown-ansi\": {\n      \"version\": \"2.16.4\",\n      \"resolved\": \"https://registry.npmjs.org/@parcel/markdown-ansi/-/markdown-ansi-2.16.4.tgz\",\n      \"integrity\": \"sha512-0+oQApAVF3wMcQ6d1ZfZ0JsRzaMUYj9e4U+naj6YEsFsFGOPp+pQYKXBf1bobQeeB7cPKPT3SUHxFqced722Hw==\",\n      \"dev\": true,\n      \"license\": \"MIT\",\n      \"dependencies\": {\n        \"chalk\": \"^4.1.2\"\n      },\n      \"engines\": {\n        \"node\": \">= 16.0.0\"\n      },\n      \"funding\": {\n        \"type\": \"opencollective\",\n        \"url\": \"https://opencollective.com/parcel\"\n      }\n    },\n    \"node_modules/@parcel/namer-default\": {\n      \"version\": \"2.16.4\",\n      \"resolved\": \"https://registry.npmjs.org/@parcel/namer-default/-/namer-default-2.16.4.tgz\",\n      \"integrity\": \"sha512-CE+0lFg881sJq575EXxj2lKUn81tsS5itpNUUErHxit195m3PExyAhoXM6ed/SXxwi+uv+T5FS/jjDLBNuUFDA==\",\n      \"dev\": true,\n      \"license\": \"MIT\",\n      \"dependencies\": {\n        \"@parcel/diagnostic\": \"2.16.4\",\n        \"@parcel/plugin\": \"2.16.4\",\n        \"nullthrows\": \"^1.1.1\"\n      },\n      \"engines\": {\n        \"node\": \">= 16.0.0\",\n        \"parcel\": \"^2.16.4\"\n      },\n      \"funding\": {\n        \"type\": \"opencollective\",\n        \"url\": \"https://opencollective.com/parcel\"\n      }\n    },\n    \"node_modules/@parcel/node-resolver-core\": {\n      \"version\": \"3.7.4\",\n      \"resolved\": \"https://registry.npmjs.org/@parcel/node-resolver-core/-/node-resolver-core-3.7.4.tgz\",\n      \"integrity\": \"sha512-b3VDG+um6IWW5CTod6M9hQsTX5mdIelKmam7mzxzgqg4j5hnycgTWqPMc9UxhYoUY/Q/PHfWepccNcKtvP5JiA==\",\n      \"dev\": true,\n      \"license\": \"MIT\",\n      \"dependencies\": {\n        \"@mischnic/json-sourcemap\": \"^0.1.1\",\n        \"@parcel/diagnostic\": \"2.16.4\",\n        \"@parcel/fs\": \"2.16.4\",\n        \"@parcel/rust\": \"2.16.4\",\n        \"@parcel/utils\": \"2.16.4\",\n        \"nullthrows\": \"^1.1.1\",\n        \"semver\": \"^7.7.1\"\n      },\n      \"engines\": {\n        \"node\": \">= 16.0.0\"\n      },\n      \"funding\": {\n        \"type\": \"opencollective\",\n        \"url\": \"https://opencollective.com/parcel\"\n      }\n    },\n    \"node_modules/@parcel/optimizer-css\": {\n      \"version\": \"2.16.4\",\n      \"resolved\": \"https://registry.npmjs.org/@parcel/optimizer-css/-/optimizer-css-2.16.4.tgz\",\n      \"integrity\": \"sha512-aqdXCtmvpcXYgJFGk2DtXF34wuM2TD1fZorKMrJdKB9sSkWVRs1tq6RAXQrbi0ZPDH9wfE/9An3YdkTex7RHuQ==\",\n      \"dev\": true,\n      \"license\": \"MIT\",\n      \"dependencies\": {\n        \"@parcel/diagnostic\": \"2.16.4\",\n        \"@parcel/plugin\": \"2.16.4\",\n        \"@parcel/source-map\": \"^2.1.1\",\n        \"@parcel/utils\": \"2.16.4\",\n        \"browserslist\": \"^4.24.5\",\n        \"lightningcss\": \"^1.30.1\",\n        \"nullthrows\": \"^1.1.1\"\n      },\n      \"engines\": {\n        \"node\": \">= 16.0.0\",\n        \"parcel\": \"^2.16.4\"\n      },\n      \"funding\": {\n        \"type\": \"opencollective\",\n        \"url\": \"https://opencollective.com/parcel\"\n      }\n    },\n    \"node_modules/@parcel/optimizer-html\": {\n      \"version\": \"2.16.4\",\n      \"resolved\": \"https://registry.npmjs.org/@parcel/optimizer-html/-/optimizer-html-2.16.4.tgz\",\n      \"integrity\": \"sha512-vg/R2uuSni+NYYUUV8m+5bz8p5zBv8wc/nNleoBnGuCDwn7uaUwTZ8Gt9CjZO8jjG0xCLILoc/TW+e2FF3pfgQ==\",\n      \"dev\": true,\n      \"license\": \"MIT\",\n      \"dependencies\": {\n        \"@parcel/plugin\": \"2.16.4\",\n        \"@parcel/rust\": \"2.16.4\",\n        \"@parcel/utils\": \"2.16.4\"\n      },\n      \"engines\": {\n        \"node\": \">= 16.0.0\",\n        \"parcel\": \"^2.16.4\"\n      },\n      \"funding\": {\n        \"type\": \"opencollective\",\n        \"url\": \"https://opencollective.com/parcel\"\n      }\n    },\n    \"node_modules/@parcel/optimizer-image\": {\n      \"version\": \"2.16.4\",\n      \"resolved\": \"https://registry.npmjs.org/@parcel/optimizer-image/-/optimizer-image-2.16.4.tgz\",\n      \"integrity\": \"sha512-2RV54WnvMYr18lxSx7Zlx/DXpJwMzOiPxDnoFyvaUoYutvgHO6chtcgFgh1Bvw/PoI95vYzlTkZ8QfUOk5A0JA==\",\n      \"dev\": true,\n      \"license\": \"MIT\",\n      \"dependencies\": {\n        \"@parcel/diagnostic\": \"2.16.4\",\n        \"@parcel/plugin\": \"2.16.4\",\n        \"@parcel/rust\": \"2.16.4\",\n        \"@parcel/utils\": \"2.16.4\",\n        \"@parcel/workers\": \"2.16.4\"\n      },\n      \"engines\": {\n        \"node\": \">= 16.0.0\",\n        \"parcel\": \"^2.16.4\"\n      },\n      \"funding\": {\n        \"type\": \"opencollective\",\n        \"url\": \"https://opencollective.com/parcel\"\n      },\n      \"peerDependencies\": {\n        \"@parcel/core\": \"^2.16.4\"\n      }\n    },\n    \"node_modules/@parcel/optimizer-svg\": {\n      \"version\": \"2.16.4\",\n      \"resolved\": \"https://registry.npmjs.org/@parcel/optimizer-svg/-/optimizer-svg-2.16.4.tgz\",\n      \"integrity\": \"sha512-22+BqIffCrVErg8y2XwhasbTaFNn75OKXZ3KTDBIfOSAZKLUKs1iHfDXETzTRN7cVcS+Q36/6EHd7N/RA8i1fg==\",\n      \"dev\": true,\n      \"license\": \"MIT\",\n      \"dependencies\": {\n        \"@parcel/plugin\": \"2.16.4\",\n        \"@parcel/rust\": \"2.16.4\",\n        \"@parcel/utils\": \"2.16.4\"\n      },\n      \"engines\": {\n        \"node\": \">= 16.0.0\",\n        \"parcel\": \"^2.16.4\"\n      },\n      \"funding\": {\n        \"type\": \"opencollective\",\n        \"url\": \"https://opencollective.com/parcel\"\n      }\n    },\n    \"node_modules/@parcel/optimizer-swc\": {\n      \"version\": \"2.16.4\",\n      \"resolved\": \"https://registry.npmjs.org/@parcel/optimizer-swc/-/optimizer-swc-2.16.4.tgz\",\n      \"integrity\": \"sha512-+URqwnB6u1gqaLbG1O1DDApH+UVj4WCbK9No1fdxLBxQ9a84jyli25o1kK1hYB9Nb/JMyYNnEBfvYUW6RphOxw==\",\n      \"dev\": true,\n      \"license\": \"MIT\",\n      \"dependencies\": {\n        \"@parcel/diagnostic\": \"2.16.4\",\n        \"@parcel/plugin\": \"2.16.4\",\n        \"@parcel/source-map\": \"^2.1.1\",\n        \"@parcel/utils\": \"2.16.4\",\n        \"@swc/core\": \"^1.11.24\",\n        \"nullthrows\": \"^1.1.1\"\n      },\n      \"engines\": {\n        \"node\": \">= 16.0.0\",\n        \"parcel\": \"^2.16.4\"\n      },\n      \"funding\": {\n        \"type\": \"opencollective\",\n        \"url\": \"https://opencollective.com/parcel\"\n      }\n    },\n    \"node_modules/@parcel/package-manager\": {\n      \"version\": \"2.16.4\",\n      \"resolved\": \"https://registry.npmjs.org/@parcel/package-manager/-/package-manager-2.16.4.tgz\",\n      \"integrity\": \"sha512-obWv9gZgdnkT3Kd+fBkKjhdNEY7zfOP5gVaox5i4nQstVCaVnDlMv5FwLEXwehL+WbwEcGyEGGxOHHkAFKk7Cg==\",\n      \"dev\": true,\n      \"license\": \"MIT\",\n      \"dependencies\": {\n        \"@parcel/diagnostic\": \"2.16.4\",\n        \"@parcel/fs\": \"2.16.4\",\n        \"@parcel/logger\": \"2.16.4\",\n        \"@parcel/node-resolver-core\": \"3.7.4\",\n        \"@parcel/types\": \"2.16.4\",\n        \"@parcel/utils\": \"2.16.4\",\n        \"@parcel/workers\": \"2.16.4\",\n        \"@swc/core\": \"^1.11.24\",\n        \"semver\": \"^7.7.1\"\n      },\n      \"engines\": {\n        \"node\": \">= 16.0.0\"\n      },\n      \"funding\": {\n        \"type\": \"opencollective\",\n        \"url\": \"https://opencollective.com/parcel\"\n      },\n      \"peerDependencies\": {\n        \"@parcel/core\": \"^2.16.4\"\n      }\n    },\n    \"node_modules/@parcel/packager-css\": {\n      \"version\": \"2.16.4\",\n      \"resolved\": \"https://registry.npmjs.org/@parcel/packager-css/-/packager-css-2.16.4.tgz\",\n      \"integrity\": \"sha512-rWRtfiX+VVIOZvq64jpeNUKkvWAbnokfHQsk/js1s5jD4ViNQgPcNLiRaiIANjymqL6+dQqWvGUSW2a5FAZYfg==\",\n      \"dev\": true,\n      \"license\": \"MIT\",\n      \"dependencies\": {\n        \"@parcel/diagnostic\": \"2.16.4\",\n        \"@parcel/plugin\": \"2.16.4\",\n        \"@parcel/source-map\": \"^2.1.1\",\n        \"@parcel/utils\": \"2.16.4\",\n        \"lightningcss\": \"^1.30.1\",\n        \"nullthrows\": \"^1.1.1\"\n      },\n      \"engines\": {\n        \"node\": \">= 16.0.0\",\n        \"parcel\": \"^2.16.4\"\n      },\n      \"funding\": {\n        \"type\": \"opencollective\",\n        \"url\": \"https://opencollective.com/parcel\"\n      }\n    },\n    \"node_modules/@parcel/packager-html\": {\n      \"version\": \"2.16.4\",\n      \"resolved\": \"https://registry.npmjs.org/@parcel/packager-html/-/packager-html-2.16.4.tgz\",\n      \"integrity\": \"sha512-AWo5f6SSqBsg2uWOsX0gPX8hCx2iE6GYLg2Z4/cDy2mPlwDICN8/bxItEztSZFmObi+ti26eetBKRDxAUivyIQ==\",\n      \"dev\": true,\n      \"license\": \"MIT\",\n      \"dependencies\": {\n        \"@parcel/plugin\": \"2.16.4\",\n        \"@parcel/rust\": \"2.16.4\",\n        \"@parcel/types\": \"2.16.4\",\n        \"@parcel/utils\": \"2.16.4\"\n      },\n      \"engines\": {\n        \"node\": \">= 16.0.0\",\n        \"parcel\": \"^2.16.4\"\n      },\n      \"funding\": {\n        \"type\": \"opencollective\",\n        \"url\": \"https://opencollective.com/parcel\"\n      }\n    },\n    \"node_modules/@parcel/packager-js\": {\n      \"version\": \"2.16.4\",\n      \"resolved\": \"https://registry.npmjs.org/@parcel/packager-js/-/packager-js-2.16.4.tgz\",\n      \"integrity\": \"sha512-L2o39f/fhta+hxto7w8OTUKdstY+te5BmHZREckbQm0KTBg93BG7jB0bfoxLSZF0d8uuAYIVXjzeHNqha+du1g==\",\n      \"dev\": true,\n      \"license\": \"MIT\",\n      \"dependencies\": {\n        \"@parcel/diagnostic\": \"2.16.4\",\n        \"@parcel/plugin\": \"2.16.4\",\n        \"@parcel/rust\": \"2.16.4\",\n        \"@parcel/source-map\": \"^2.1.1\",\n        \"@parcel/types\": \"2.16.4\",\n        \"@parcel/utils\": \"2.16.4\",\n        \"globals\": \"^13.24.0\",\n        \"nullthrows\": \"^1.1.1\"\n      },\n      \"engines\": {\n        \"node\": \">= 16.0.0\",\n        \"parcel\": \"^2.16.4\"\n      },\n      \"funding\": {\n        \"type\": \"opencollective\",\n        \"url\": \"https://opencollective.com/parcel\"\n      }\n    },\n    \"node_modules/@parcel/packager-raw\": {\n      \"version\": \"2.16.4\",\n      \"resolved\": \"https://registry.npmjs.org/@parcel/packager-raw/-/packager-raw-2.16.4.tgz\",\n      \"integrity\": \"sha512-A9j60G9OmbTkEeE4WRMXCiErEprHLs9NkUlC4HXCxmSrPMOVaMaMva2LdejE3A9kujZqYtYfuc8+a+jN+Nro4w==\",\n      \"dev\": true,\n      \"license\": \"MIT\",\n      \"dependencies\": {\n        \"@parcel/plugin\": \"2.16.4\"\n      },\n      \"engines\": {\n        \"node\": \">= 16.0.0\",\n        \"parcel\": \"^2.16.4\"\n      },\n      \"funding\": {\n        \"type\": \"opencollective\",\n        \"url\": \"https://opencollective.com/parcel\"\n      }\n    },\n    \"node_modules/@parcel/packager-svg\": {\n      \"version\": \"2.16.4\",\n      \"resolved\": \"https://registry.npmjs.org/@parcel/packager-svg/-/packager-svg-2.16.4.tgz\",\n      \"integrity\": \"sha512-LT9l7eInFrAZJ6w3mYzAUgDq3SIzYbbQyW46Dz26M9lJQbf6uCaATUTac3BEHegW0ikDuw4OOGHK41BVqeeusg==\",\n      \"dev\": true,\n      \"license\": \"MIT\",\n      \"dependencies\": {\n        \"@parcel/plugin\": \"2.16.4\",\n        \"@parcel/rust\": \"2.16.4\",\n        \"@parcel/types\": \"2.16.4\",\n        \"@parcel/utils\": \"2.16.4\"\n      },\n      \"engines\": {\n        \"node\": \">= 16.0.0\",\n        \"parcel\": \"^2.16.4\"\n      },\n      \"funding\": {\n        \"type\": \"opencollective\",\n        \"url\": \"https://opencollective.com/parcel\"\n      }\n    },\n    \"node_modules/@parcel/packager-wasm\": {\n      \"version\": \"2.16.4\",\n      \"resolved\": \"https://registry.npmjs.org/@parcel/packager-wasm/-/packager-wasm-2.16.4.tgz\",\n      \"integrity\": \"sha512-AY96Aqu/RpmaSZK2RGkIrZWjAperDw8DAlxLAiaP1D/RPVnikZtl5BmcUt/Wz3PrzG7/q9ZVqqKkWsLmhkjXZQ==\",\n      \"dev\": true,\n      \"license\": \"MIT\",\n      \"dependencies\": {\n        \"@parcel/plugin\": \"2.16.4\"\n      },\n      \"engines\": {\n        \"node\": \">=16.0.0\",\n        \"parcel\": \"^2.16.4\"\n      },\n      \"funding\": {\n        \"type\": \"opencollective\",\n        \"url\": \"https://opencollective.com/parcel\"\n      }\n    },\n    \"node_modules/@parcel/plugin\": {\n      \"version\": \"2.16.4\",\n      \"resolved\": \"https://registry.npmjs.org/@parcel/plugin/-/plugin-2.16.4.tgz\",\n      \"integrity\": \"sha512-aN2VQoRGC1eB41ZCDbPR/Sp0yKOxe31oemzPx1nJzOuebK2Q6FxSrJ9Bjj9j/YCaLzDtPwelsuLOazzVpXJ6qg==\",\n      \"dev\": true,\n      \"license\": \"MIT\",\n      \"dependencies\": {\n        \"@parcel/types\": \"2.16.4\"\n      },\n      \"engines\": {\n        \"node\": \">= 16.0.0\"\n      },\n      \"funding\": {\n        \"type\": \"opencollective\",\n        \"url\": \"https://opencollective.com/parcel\"\n      }\n    },\n    \"node_modules/@parcel/profiler\": {\n      \"version\": \"2.16.4\",\n      \"resolved\": \"https://registry.npmjs.org/@parcel/profiler/-/profiler-2.16.4.tgz\",\n      \"integrity\": \"sha512-R3JhfcnoReTv2sVFHPR2xKZvs3d3IRrBl9sWmAftbIJFwT4rU70/W7IdwfaJVkD/6PzHq9mcgOh1WKL4KAxPdA==\",\n      \"dev\": true,\n      \"license\": \"MIT\",\n      \"dependencies\": {\n        \"@parcel/diagnostic\": \"2.16.4\",\n        \"@parcel/events\": \"2.16.4\",\n        \"@parcel/types-internal\": \"2.16.4\",\n        \"chrome-trace-event\": \"^1.0.2\"\n      },\n      \"engines\": {\n        \"node\": \">= 16.0.0\"\n      },\n      \"funding\": {\n        \"type\": \"opencollective\",\n        \"url\": \"https://opencollective.com/parcel\"\n      }\n    },\n    \"node_modules/@parcel/reporter-cli\": {\n      \"version\": \"2.16.4\",\n      \"resolved\": \"https://registry.npmjs.org/@parcel/reporter-cli/-/reporter-cli-2.16.4.tgz\",\n      \"integrity\": \"sha512-DQx9TwcTZrDv828+tcwEi//xyW7OHTGzGX1+UEVxPp0mSzuOmDn0zfER8qNIqGr1i4D/FXhb5UJQDhGHV8mOpQ==\",\n      \"dev\": true,\n      \"license\": \"MIT\",\n      \"dependencies\": {\n        \"@parcel/plugin\": \"2.16.4\",\n        \"@parcel/types\": \"2.16.4\",\n        \"@parcel/utils\": \"2.16.4\",\n        \"chalk\": \"^4.1.2\",\n        \"term-size\": \"^2.2.1\"\n      },\n      \"engines\": {\n        \"node\": \">= 16.0.0\",\n        \"parcel\": \"^2.16.4\"\n      },\n      \"funding\": {\n        \"type\": \"opencollective\",\n        \"url\": \"https://opencollective.com/parcel\"\n      }\n    },\n    \"node_modules/@parcel/reporter-dev-server\": {\n      \"version\": \"2.16.4\",\n      \"resolved\": \"https://registry.npmjs.org/@parcel/reporter-dev-server/-/reporter-dev-server-2.16.4.tgz\",\n      \"integrity\": \"sha512-YWvay25htQDifpDRJ0+yFh6xUxKnbfeJxYkPYyuXdxpEUhq4T0UWW0PbPCN/wFX7StgeUTXq5Poeo/+eys9m3w==\",\n      \"dev\": true,\n      \"license\": \"MIT\",\n      \"dependencies\": {\n        \"@parcel/codeframe\": \"2.16.4\",\n        \"@parcel/plugin\": \"2.16.4\",\n        \"@parcel/source-map\": \"^2.1.1\",\n        \"@parcel/utils\": \"2.16.4\"\n      },\n      \"engines\": {\n        \"node\": \">= 16.0.0\",\n        \"parcel\": \"^2.16.4\"\n      },\n      \"funding\": {\n        \"type\": \"opencollective\",\n        \"url\": \"https://opencollective.com/parcel\"\n      }\n    },\n    \"node_modules/@parcel/reporter-tracer\": {\n      \"version\": \"2.16.4\",\n      \"resolved\": \"https://registry.npmjs.org/@parcel/reporter-tracer/-/reporter-tracer-2.16.4.tgz\",\n      \"integrity\": \"sha512-JKnlXpPepak0/ZybmZn9JtyjJiDBWYrt7ZUlXQhQb0xzNcd/k+RqfwVkTKIwyFHsWtym0cwibkvsi2bWFzS7tw==\",\n      \"dev\": true,\n      \"license\": \"MIT\",\n      \"dependencies\": {\n        \"@parcel/plugin\": \"2.16.4\",\n        \"@parcel/utils\": \"2.16.4\",\n        \"chrome-trace-event\": \"^1.0.3\",\n        \"nullthrows\": \"^1.1.1\"\n      },\n      \"engines\": {\n        \"node\": \">= 16.0.0\",\n        \"parcel\": \"^2.16.4\"\n      },\n      \"funding\": {\n        \"type\": \"opencollective\",\n        \"url\": \"https://opencollective.com/parcel\"\n      }\n    },\n    \"node_modules/@parcel/resolver-default\": {\n      \"version\": \"2.16.4\",\n      \"resolved\": \"https://registry.npmjs.org/@parcel/resolver-default/-/resolver-default-2.16.4.tgz\",\n      \"integrity\": \"sha512-wJe9XQS0hn/t32pntQpJbls3ZL8mGVVhK9L7s7BTmZT9ufnvP2nif1psJz/nbgnP9LF6mLSk43OdMJKpoStsjQ==\",\n      \"dev\": true,\n      \"license\": \"MIT\",\n      \"dependencies\": {\n        \"@parcel/node-resolver-core\": \"3.7.4\",\n        \"@parcel/plugin\": \"2.16.4\"\n      },\n      \"engines\": {\n        \"node\": \">= 16.0.0\",\n        \"parcel\": \"^2.16.4\"\n      },\n      \"funding\": {\n        \"type\": \"opencollective\",\n        \"url\": \"https://opencollective.com/parcel\"\n      }\n    },\n    \"node_modules/@parcel/runtime-browser-hmr\": {\n      \"version\": \"2.16.4\",\n      \"resolved\": \"https://registry.npmjs.org/@parcel/runtime-browser-hmr/-/runtime-browser-hmr-2.16.4.tgz\",\n      \"integrity\": \"sha512-asx7p3NjUSfibI3bC7+8+jUIGHWVk2Zuq9SjJGCGDt+auT9A4uSGljnsk1BWWPqqZ0WILubq4czSAqm0+wt4cw==\",\n      \"dev\": true,\n      \"license\": \"MIT\",\n      \"dependencies\": {\n        \"@parcel/plugin\": \"2.16.4\",\n        \"@parcel/utils\": \"2.16.4\"\n      },\n      \"engines\": {\n        \"node\": \">= 16.0.0\",\n        \"parcel\": \"^2.16.4\"\n      },\n      \"funding\": {\n        \"type\": \"opencollective\",\n        \"url\": \"https://opencollective.com/parcel\"\n      }\n    },\n    \"node_modules/@parcel/runtime-js\": {\n      \"version\": \"2.16.4\",\n      \"resolved\": \"https://registry.npmjs.org/@parcel/runtime-js/-/runtime-js-2.16.4.tgz\",\n      \"integrity\": \"sha512-gUKmsjg+PULQBu2QbX0QKll9tXSqHPO8NrfxHwWb2lz5xDKDos1oV0I7BoMWbHhUHkoToXZrm654oGViujtVUA==\",\n      \"dev\": true,\n      \"license\": \"MIT\",\n      \"dependencies\": {\n        \"@parcel/diagnostic\": \"2.16.4\",\n        \"@parcel/plugin\": \"2.16.4\",\n        \"@parcel/utils\": \"2.16.4\",\n        \"nullthrows\": \"^1.1.1\"\n      },\n      \"engines\": {\n        \"node\": \">= 16.0.0\",\n        \"parcel\": \"^2.16.4\"\n      },\n      \"funding\": {\n        \"type\": \"opencollective\",\n        \"url\": \"https://opencollective.com/parcel\"\n      }\n    },\n    \"node_modules/@parcel/runtime-rsc\": {\n      \"version\": \"2.16.4\",\n      \"resolved\": \"https://registry.npmjs.org/@parcel/runtime-rsc/-/runtime-rsc-2.16.4.tgz\",\n      \"integrity\": \"sha512-CHkotYE/cNiUjJmrc5FD9YhlFp1UF5wMNNJmoWaL40eBzsqcaV0sSn5V3bNapwewn3wrMYgdPgvOTHfaZaG73A==\",\n      \"dev\": true,\n      \"license\": \"MIT\",\n      \"dependencies\": {\n        \"@parcel/plugin\": \"2.16.4\",\n        \"@parcel/rust\": \"2.16.4\",\n        \"@parcel/utils\": \"2.16.4\",\n        \"nullthrows\": \"^1.1.1\"\n      },\n      \"engines\": {\n        \"node\": \">= 12.0.0\",\n        \"parcel\": \"^2.16.4\"\n      },\n      \"funding\": {\n        \"type\": \"opencollective\",\n        \"url\": \"https://opencollective.com/parcel\"\n      }\n    },\n    \"node_modules/@parcel/runtime-service-worker\": {\n      \"version\": \"2.16.4\",\n      \"resolved\": \"https://registry.npmjs.org/@parcel/runtime-service-worker/-/runtime-service-worker-2.16.4.tgz\",\n      \"integrity\": \"sha512-FT0Q58bf5Re+dq5cL2XHbxqHHFZco6qtRijeVpT3TSPMRPlniMArypSytTeZzVNL7h/hxjWsNu7fRuC0yLB5hA==\",\n      \"dev\": true,\n      \"license\": \"MIT\",\n      \"dependencies\": {\n        \"@parcel/plugin\": \"2.16.4\",\n        \"@parcel/utils\": \"2.16.4\",\n        \"nullthrows\": \"^1.1.1\"\n      },\n      \"engines\": {\n        \"node\": \">= 16.0.0\",\n        \"parcel\": \"^2.16.4\"\n      },\n      \"funding\": {\n        \"type\": \"opencollective\",\n        \"url\": \"https://opencollective.com/parcel\"\n      }\n    },\n    \"node_modules/@parcel/rust\": {\n      \"version\": \"2.16.4\",\n      \"resolved\": \"https://registry.npmjs.org/@parcel/rust/-/rust-2.16.4.tgz\",\n      \"integrity\": \"sha512-RBMKt9rCdv6jr4vXG6LmHtxzO5TuhQvXo1kSoSIF7fURRZ81D1jzBtLxwLmfxCPsofJNqWwdhy5vIvisX+TLlQ==\",\n      \"dev\": true,\n      \"license\": \"MIT\",\n      \"engines\": {\n        \"node\": \">= 16.0.0\"\n      },\n      \"funding\": {\n        \"type\": \"opencollective\",\n        \"url\": \"https://opencollective.com/parcel\"\n      },\n      \"optionalDependencies\": {\n        \"@parcel/rust-darwin-arm64\": \"2.16.4\",\n        \"@parcel/rust-darwin-x64\": \"2.16.4\",\n        \"@parcel/rust-linux-arm-gnueabihf\": \"2.16.4\",\n        \"@parcel/rust-linux-arm64-gnu\": \"2.16.4\",\n        \"@parcel/rust-linux-arm64-musl\": \"2.16.4\",\n        \"@parcel/rust-linux-x64-gnu\": \"2.16.4\",\n        \"@parcel/rust-linux-x64-musl\": \"2.16.4\",\n        \"@parcel/rust-win32-x64-msvc\": \"2.16.4\"\n      },\n      \"peerDependencies\": {\n        \"napi-wasm\": \"^1.1.2\"\n      },\n      \"peerDependenciesMeta\": {\n        \"napi-wasm\": {\n          \"optional\": true\n        }\n      }\n    },\n    \"node_modules/@parcel/rust-darwin-arm64\": {\n      \"version\": \"2.16.4\",\n      \"resolved\": \"https://registry.npmjs.org/@parcel/rust-darwin-arm64/-/rust-darwin-arm64-2.16.4.tgz\",\n      \"integrity\": \"sha512-P3Se36H9EO1fOlwXqQNQ+RsVKTGn5ztRSUGbLcT8ba6oOMmU1w7J4R810GgsCbwCuF10TJNUMkuD3Q2Sz15Q3Q==\",\n      \"cpu\": [\n        \"arm64\"\n      ],\n      \"dev\": true,\n      \"license\": \"MIT\",\n      \"optional\": true,\n      \"os\": [\n        \"darwin\"\n      ],\n      \"engines\": {\n        \"node\": \">= 10\"\n      },\n      \"funding\": {\n        \"type\": \"opencollective\",\n        \"url\": \"https://opencollective.com/parcel\"\n      }\n    },\n    \"node_modules/@parcel/rust-darwin-x64\": {\n      \"version\": \"2.16.4\",\n      \"resolved\": \"https://registry.npmjs.org/@parcel/rust-darwin-x64/-/rust-darwin-x64-2.16.4.tgz\",\n      \"integrity\": \"sha512-8aNKNyPIx3EthYpmVJevIdHmFsOApXAEYGi3HU69jTxLgSIfyEHDdGE9lEsMvhSrd/SSo4/euAtiV+pqK04wnA==\",\n      \"cpu\": [\n        \"x64\"\n      ],\n      \"dev\": true,\n      \"license\": \"MIT\",\n      \"optional\": true,\n      \"os\": [\n        \"darwin\"\n      ],\n      \"engines\": {\n        \"node\": \">= 10\"\n      },\n      \"funding\": {\n        \"type\": \"opencollective\",\n        \"url\": \"https://opencollective.com/parcel\"\n      }\n    },\n    \"node_modules/@parcel/rust-linux-arm-gnueabihf\": {\n      \"version\": \"2.16.4\",\n      \"resolved\": \"https://registry.npmjs.org/@parcel/rust-linux-arm-gnueabihf/-/rust-linux-arm-gnueabihf-2.16.4.tgz\",\n      \"integrity\": \"sha512-QrvqiSHaWRLc0JBHgUHVvDthfWSkA6AFN+ikV1UGENv4j2r/QgvuwJiG0VHrsL6pH5dRqj0vvngHzEgguke9DA==\",\n      \"cpu\": [\n        \"arm\"\n      ],\n      \"dev\": true,\n      \"license\": \"MIT\",\n      \"optional\": true,\n      \"os\": [\n        \"linux\"\n      ],\n      \"engines\": {\n        \"node\": \">= 10\"\n      },\n      \"funding\": {\n        \"type\": \"opencollective\",\n        \"url\": \"https://opencollective.com/parcel\"\n      }\n    },\n    \"node_modules/@parcel/rust-linux-arm64-gnu\": {\n      \"version\": \"2.16.4\",\n      \"resolved\": \"https://registry.npmjs.org/@parcel/rust-linux-arm64-gnu/-/rust-linux-arm64-gnu-2.16.4.tgz\",\n      \"integrity\": \"sha512-f3gBWQHLHRUajNZi3SMmDQiEx54RoRbXtZYQNuBQy7+NolfFcgb1ik3QhkT7xovuTF/LBmaqP3UFy0PxvR/iwQ==\",\n      \"cpu\": [\n        \"arm64\"\n      ],\n      \"dev\": true,\n      \"license\": \"MIT\",\n      \"optional\": true,\n      \"os\": [\n        \"linux\"\n      ],\n      \"engines\": {\n        \"node\": \">= 10\"\n      },\n      \"funding\": {\n        \"type\": \"opencollective\",\n        \"url\": \"https://opencollective.com/parcel\"\n      }\n    },\n    \"node_modules/@parcel/rust-linux-arm64-musl\": {\n      \"version\": \"2.16.4\",\n      \"resolved\": \"https://registry.npmjs.org/@parcel/rust-linux-arm64-musl/-/rust-linux-arm64-musl-2.16.4.tgz\",\n      \"integrity\": \"sha512-cwml18RNKsBwHyZnrZg4jpecXkWjaY/mCArocWUxkFXjjB97L56QWQM9W86f2/Y3HcFcnIGJwx1SDDKJrV6OIA==\",\n      \"cpu\": [\n        \"arm64\"\n      ],\n      \"dev\": true,\n      \"license\": \"MIT\",\n      \"optional\": true,\n      \"os\": [\n        \"linux\"\n      ],\n      \"engines\": {\n        \"node\": \">= 10\"\n      },\n      \"funding\": {\n        \"type\": \"opencollective\",\n        \"url\": \"https://opencollective.com/parcel\"\n      }\n    },\n    \"node_modules/@parcel/rust-linux-x64-gnu\": {\n      \"version\": \"2.16.4\",\n      \"resolved\": \"https://registry.npmjs.org/@parcel/rust-linux-x64-gnu/-/rust-linux-x64-gnu-2.16.4.tgz\",\n      \"integrity\": \"sha512-0xIjQaN8hiG0F9R8coPYidHslDIrbfOS/qFy5GJNbGA3S49h61wZRBMQqa7JFW4+2T8R0J9j0SKHhLXpbLXrIg==\",\n      \"cpu\": [\n        \"x64\"\n      ],\n      \"dev\": true,\n      \"license\": \"MIT\",\n      \"optional\": true,\n      \"os\": [\n        \"linux\"\n      ],\n      \"engines\": {\n        \"node\": \">= 10\"\n      },\n      \"funding\": {\n        \"type\": \"opencollective\",\n        \"url\": \"https://opencollective.com/parcel\"\n      }\n    },\n    \"node_modules/@parcel/rust-linux-x64-musl\": {\n      \"version\": \"2.16.4\",\n      \"resolved\": \"https://registry.npmjs.org/@parcel/rust-linux-x64-musl/-/rust-linux-x64-musl-2.16.4.tgz\",\n      \"integrity\": \"sha512-fYn21GIecHK9RoZPKwT9NOwxwl3Gy3RYPR6zvsUi0+hpFo19Ph9EzFXN3lT8Pi5KiwQMCU4rsLb5HoWOBM1FeA==\",\n      \"cpu\": [\n        \"x64\"\n      ],\n      \"dev\": true,\n      \"license\": \"MIT\",\n      \"optional\": true,\n      \"os\": [\n        \"linux\"\n      ],\n      \"engines\": {\n        \"node\": \">= 10\"\n      },\n      \"funding\": {\n        \"type\": \"opencollective\",\n        \"url\": \"https://opencollective.com/parcel\"\n      }\n    },\n    \"node_modules/@parcel/rust-win32-x64-msvc\": {\n      \"version\": \"2.16.4\",\n      \"resolved\": \"https://registry.npmjs.org/@parcel/rust-win32-x64-msvc/-/rust-win32-x64-msvc-2.16.4.tgz\",\n      \"integrity\": \"sha512-TcpWC3I1mJpfP2++018lgvM7UX0P8IrzNxceBTHUKEIDMwmAYrUKAQFiaU0j1Ldqk6yP8SPZD3cvphumsYpJOQ==\",\n      \"cpu\": [\n        \"x64\"\n      ],\n      \"dev\": true,\n      \"license\": \"MIT\",\n      \"optional\": true,\n      \"os\": [\n        \"win32\"\n      ],\n      \"engines\": {\n        \"node\": \">= 10\"\n      },\n      \"funding\": {\n        \"type\": \"opencollective\",\n        \"url\": \"https://opencollective.com/parcel\"\n      }\n    },\n    \"node_modules/@parcel/source-map\": {\n      \"version\": \"2.1.1\",\n      \"resolved\": \"https://registry.npmjs.org/@parcel/source-map/-/source-map-2.1.1.tgz\",\n      \"integrity\": \"sha512-Ejx1P/mj+kMjQb8/y5XxDUn4reGdr+WyKYloBljpppUy8gs42T+BNoEOuRYqDVdgPc6NxduzIDoJS9pOFfV5Ew==\",\n      \"dev\": true,\n      \"license\": \"MIT\",\n      \"dependencies\": {\n        \"detect-libc\": \"^1.0.3\"\n      },\n      \"engines\": {\n        \"node\": \"^12.18.3 || >=14\"\n      }\n    },\n    \"node_modules/@parcel/transformer-babel\": {\n      \"version\": \"2.16.4\",\n      \"resolved\": \"https://registry.npmjs.org/@parcel/transformer-babel/-/transformer-babel-2.16.4.tgz\",\n      \"integrity\": \"sha512-CMDUOQYX7+cmeyHxHSFnoPcwvXNL7rRFE+Q06uVFzsYYiVhbwGF/1J5Bx4cW3Froumqla4YTytTsEteJEybkdA==\",\n      \"dev\": true,\n      \"license\": \"MIT\",\n      \"dependencies\": {\n        \"@parcel/diagnostic\": \"2.16.4\",\n        \"@parcel/plugin\": \"2.16.4\",\n        \"@parcel/source-map\": \"^2.1.1\",\n        \"@parcel/utils\": \"2.16.4\",\n        \"browserslist\": \"^4.24.5\",\n        \"json5\": \"^2.2.3\",\n        \"nullthrows\": \"^1.1.1\",\n        \"semver\": \"^7.7.1\"\n      },\n      \"engines\": {\n        \"node\": \">= 16.0.0\",\n        \"parcel\": \"^2.16.4\"\n      },\n      \"funding\": {\n        \"type\": \"opencollective\",\n        \"url\": \"https://opencollective.com/parcel\"\n      }\n    },\n    \"node_modules/@parcel/transformer-css\": {\n      \"version\": \"2.16.4\",\n      \"resolved\": \"https://registry.npmjs.org/@parcel/transformer-css/-/transformer-css-2.16.4.tgz\",\n      \"integrity\": \"sha512-VG/+DbDci2HKe20GFRDs65ZQf5GUFfnmZAa1BhVl/MO+ijT3XC3eoVUy5cExRkq4VLcPY4ytL0g/1T2D6x7lBQ==\",\n      \"dev\": true,\n      \"license\": \"MIT\",\n      \"dependencies\": {\n        \"@parcel/diagnostic\": \"2.16.4\",\n        \"@parcel/plugin\": \"2.16.4\",\n        \"@parcel/source-map\": \"^2.1.1\",\n        \"@parcel/utils\": \"2.16.4\",\n        \"browserslist\": \"^4.24.5\",\n        \"lightningcss\": \"^1.30.1\",\n        \"nullthrows\": \"^1.1.1\"\n      },\n      \"engines\": {\n        \"node\": \">= 16.0.0\",\n        \"parcel\": \"^2.16.4\"\n      },\n      \"funding\": {\n        \"type\": \"opencollective\",\n        \"url\": \"https://opencollective.com/parcel\"\n      }\n    },\n    \"node_modules/@parcel/transformer-html\": {\n      \"version\": \"2.16.4\",\n      \"resolved\": \"https://registry.npmjs.org/@parcel/transformer-html/-/transformer-html-2.16.4.tgz\",\n      \"integrity\": \"sha512-w6JErYTeNS+KAzUAER18NHFIFFvxiLGd4Fht1UYcb/FDjJdLAMB/FljyEs0Rto/WAhZ2D0MuSL25HQh837R62g==\",\n      \"dev\": true,\n      \"license\": \"MIT\",\n      \"dependencies\": {\n        \"@parcel/diagnostic\": \"2.16.4\",\n        \"@parcel/plugin\": \"2.16.4\",\n        \"@parcel/rust\": \"2.16.4\"\n      },\n      \"engines\": {\n        \"node\": \">= 16.0.0\",\n        \"parcel\": \"^2.16.4\"\n      },\n      \"funding\": {\n        \"type\": \"opencollective\",\n        \"url\": \"https://opencollective.com/parcel\"\n      }\n    },\n    \"node_modules/@parcel/transformer-image\": {\n      \"version\": \"2.16.4\",\n      \"resolved\": \"https://registry.npmjs.org/@parcel/transformer-image/-/transformer-image-2.16.4.tgz\",\n      \"integrity\": \"sha512-ZzIn3KvvRqMfcect4Dy+57C9XoQXZhpVJKBdQWMp9wM1qJEgsVgGDcaSBYCs/UYSKMRMP6Wm20pKCt408RkQzg==\",\n      \"dev\": true,\n      \"license\": \"MIT\",\n      \"dependencies\": {\n        \"@parcel/plugin\": \"2.16.4\",\n        \"@parcel/utils\": \"2.16.4\",\n        \"@parcel/workers\": \"2.16.4\",\n        \"nullthrows\": \"^1.1.1\"\n      },\n      \"engines\": {\n        \"node\": \">= 16.0.0\",\n        \"parcel\": \"^2.16.4\"\n      },\n      \"peerDependencies\": {\n        \"@parcel/core\": \"^2.16.4\"\n      }\n    },\n    \"node_modules/@parcel/transformer-js\": {\n      \"version\": \"2.16.4\",\n      \"resolved\": \"https://registry.npmjs.org/@parcel/transformer-js/-/transformer-js-2.16.4.tgz\",\n      \"integrity\": \"sha512-FD2fdO6URwAGBPidb3x1dDgLBt972mko0LelcSU05aC/pcKaV9mbCtINbPul1MlStzkxDelhuImcCYIyerheVQ==\",\n      \"dev\": true,\n      \"license\": \"MIT\",\n      \"dependencies\": {\n        \"@parcel/diagnostic\": \"2.16.4\",\n        \"@parcel/plugin\": \"2.16.4\",\n        \"@parcel/rust\": \"2.16.4\",\n        \"@parcel/source-map\": \"^2.1.1\",\n        \"@parcel/utils\": \"2.16.4\",\n        \"@parcel/workers\": \"2.16.4\",\n        \"@swc/helpers\": \"^0.5.0\",\n        \"browserslist\": \"^4.24.5\",\n        \"nullthrows\": \"^1.1.1\",\n        \"regenerator-runtime\": \"^0.14.1\",\n        \"semver\": \"^7.7.1\"\n      },\n      \"engines\": {\n        \"node\": \">= 16.0.0\",\n        \"parcel\": \"^2.16.4\"\n      },\n      \"funding\": {\n        \"type\": \"opencollective\",\n        \"url\": \"https://opencollective.com/parcel\"\n      },\n      \"peerDependencies\": {\n        \"@parcel/core\": \"^2.16.4\"\n      }\n    },\n    \"node_modules/@parcel/transformer-json\": {\n      \"version\": \"2.16.4\",\n      \"resolved\": \"https://registry.npmjs.org/@parcel/transformer-json/-/transformer-json-2.16.4.tgz\",\n      \"integrity\": \"sha512-pB3ZNqgokdkBCJ+4G0BrPYcIkyM9K1HVk0GvjzcLEFDKsoAp8BGEM68FzagFM/nVq9anYTshIaoh349GK0M/bg==\",\n      \"dev\": true,\n      \"license\": \"MIT\",\n      \"dependencies\": {\n        \"@parcel/plugin\": \"2.16.4\",\n        \"json5\": \"^2.2.3\"\n      },\n      \"engines\": {\n        \"node\": \">= 16.0.0\",\n        \"parcel\": \"^2.16.4\"\n      },\n      \"funding\": {\n        \"type\": \"opencollective\",\n        \"url\": \"https://opencollective.com/parcel\"\n      }\n    },\n    \"node_modules/@parcel/transformer-node\": {\n      \"version\": \"2.16.4\",\n      \"resolved\": \"https://registry.npmjs.org/@parcel/transformer-node/-/transformer-node-2.16.4.tgz\",\n      \"integrity\": \"sha512-7t43CPGfMJk1LqFokwxHSsRi+kKC2QvDXaMtqiMShmk50LCwn81WgzuFvNhMwf6lSiBihWupGwF3Fqksg+aisg==\",\n      \"dev\": true,\n      \"license\": \"MIT\",\n      \"dependencies\": {\n        \"@parcel/plugin\": \"2.16.4\"\n      },\n      \"engines\": {\n        \"node\": \">= 16.0.0\",\n        \"parcel\": \"^2.16.4\"\n      },\n      \"funding\": {\n        \"type\": \"opencollective\",\n        \"url\": \"https://opencollective.com/parcel\"\n      }\n    },\n    \"node_modules/@parcel/transformer-postcss\": {\n      \"version\": \"2.16.4\",\n      \"resolved\": \"https://registry.npmjs.org/@parcel/transformer-postcss/-/transformer-postcss-2.16.4.tgz\",\n      \"integrity\": \"sha512-jfmh9ho03H+qwz9S1b/a/oaOmgfMovtHKYDweIGMjKULKIee3AFRqo8RZIOuUMjDuqHWK8SqQmjery4syFV3Xw==\",\n      \"dev\": true,\n      \"license\": \"MIT\",\n      \"dependencies\": {\n        \"@parcel/diagnostic\": \"2.16.4\",\n        \"@parcel/plugin\": \"2.16.4\",\n        \"@parcel/rust\": \"2.16.4\",\n        \"@parcel/utils\": \"2.16.4\",\n        \"clone\": \"^2.1.2\",\n        \"nullthrows\": \"^1.1.1\",\n        \"postcss-value-parser\": \"^4.2.0\",\n        \"semver\": \"^7.7.1\"\n      },\n      \"engines\": {\n        \"node\": \">= 16.0.0\",\n        \"parcel\": \"^2.16.4\"\n      },\n      \"funding\": {\n        \"type\": \"opencollective\",\n        \"url\": \"https://opencollective.com/parcel\"\n      }\n    },\n    \"node_modules/@parcel/transformer-posthtml\": {\n      \"version\": \"2.16.4\",\n      \"resolved\": \"https://registry.npmjs.org/@parcel/transformer-posthtml/-/transformer-posthtml-2.16.4.tgz\",\n      \"integrity\": \"sha512-+GXsmGx1L25KQGQnwclgEuQe1t4QU+IoDkgN+Ikj+EnQCOWG4/ts2VpMBeqP5F18ZT4cCSRafj6317o/2lSGJg==\",\n      \"dev\": true,\n      \"license\": \"MIT\",\n      \"dependencies\": {\n        \"@parcel/plugin\": \"2.16.4\",\n        \"@parcel/utils\": \"2.16.4\"\n      },\n      \"engines\": {\n        \"node\": \">= 16.0.0\",\n        \"parcel\": \"^2.16.4\"\n      },\n      \"funding\": {\n        \"type\": \"opencollective\",\n        \"url\": \"https://opencollective.com/parcel\"\n      }\n    },\n    \"node_modules/@parcel/transformer-raw\": {\n      \"version\": \"2.16.4\",\n      \"resolved\": \"https://registry.npmjs.org/@parcel/transformer-raw/-/transformer-raw-2.16.4.tgz\",\n      \"integrity\": \"sha512-7WDUPq+bW11G9jKxaQIVL+NPGolV99oq/GXhpjYip0SaGaLzRCW7gEk60cftuk0O7MsDaX5jcAJm3G/AX+LJKg==\",\n      \"dev\": true,\n      \"license\": \"MIT\",\n      \"dependencies\": {\n        \"@parcel/plugin\": \"2.16.4\"\n      },\n      \"engines\": {\n        \"node\": \">= 16.0.0\",\n        \"parcel\": \"^2.16.4\"\n      },\n      \"funding\": {\n        \"type\": \"opencollective\",\n        \"url\": \"https://opencollective.com/parcel\"\n      }\n    },\n    \"node_modules/@parcel/transformer-react-refresh-wrap\": {\n      \"version\": \"2.16.4\",\n      \"resolved\": \"https://registry.npmjs.org/@parcel/transformer-react-refresh-wrap/-/transformer-react-refresh-wrap-2.16.4.tgz\",\n      \"integrity\": \"sha512-MiLNZrsGQJTANKKa4lzZyUbGj/en0Hms474mMdQkCBFg6GmjfmXwaMMgtTfPA3ZwSp2+3LeObCyca/f9B2gBZQ==\",\n      \"dev\": true,\n      \"license\": \"MIT\",\n      \"dependencies\": {\n        \"@parcel/error-overlay\": \"2.16.4\",\n        \"@parcel/plugin\": \"2.16.4\",\n        \"@parcel/utils\": \"2.16.4\",\n        \"react-refresh\": \"^0.16.0\"\n      },\n      \"engines\": {\n        \"node\": \">= 16.0.0\",\n        \"parcel\": \"^2.16.4\"\n      },\n      \"funding\": {\n        \"type\": \"opencollective\",\n        \"url\": \"https://opencollective.com/parcel\"\n      }\n    },\n    \"node_modules/@parcel/transformer-svg\": {\n      \"version\": \"2.16.4\",\n      \"resolved\": \"https://registry.npmjs.org/@parcel/transformer-svg/-/transformer-svg-2.16.4.tgz\",\n      \"integrity\": \"sha512-0dm4cQr/WpfQP6N0xjFtwdLTxcONDfoLgTOMk4eNUWydHipSgmLtvUk/nOc/FWkwztRScfAObtZXOiPOd3Oy9A==\",\n      \"dev\": true,\n      \"license\": \"MIT\",\n      \"dependencies\": {\n        \"@parcel/diagnostic\": \"2.16.4\",\n        \"@parcel/plugin\": \"2.16.4\",\n        \"@parcel/rust\": \"2.16.4\"\n      },\n      \"engines\": {\n        \"node\": \">= 16.0.0\",\n        \"parcel\": \"^2.16.4\"\n      },\n      \"funding\": {\n        \"type\": \"opencollective\",\n        \"url\": \"https://opencollective.com/parcel\"\n      }\n    },\n    \"node_modules/@parcel/types\": {\n      \"version\": \"2.16.4\",\n      \"resolved\": \"https://registry.npmjs.org/@parcel/types/-/types-2.16.4.tgz\",\n      \"integrity\": \"sha512-ctx4mBskZHXeDVHg4OjMwx18jfYH9BzI/7yqbDQVGvd5lyA+/oVVzYdpele2J2i2sSaJ87cA8nb57GDQ8kHAqA==\",\n      \"dev\": true,\n      \"license\": \"MIT\",\n      \"dependencies\": {\n        \"@parcel/types-internal\": \"2.16.4\",\n        \"@parcel/workers\": \"2.16.4\"\n      }\n    },\n    \"node_modules/@parcel/types-internal\": {\n      \"version\": \"2.16.4\",\n      \"resolved\": \"https://registry.npmjs.org/@parcel/types-internal/-/types-internal-2.16.4.tgz\",\n      \"integrity\": \"sha512-PE6Qmt5cjzBxX+6MPLiF7r+twoC+V9Skt3zyuBQ+H1c0i9o07Bbz2NKX10nvlPukfmW6Fu/1RvTLkzBZR1bU6A==\",\n      \"dev\": true,\n      \"license\": \"MIT\",\n      \"dependencies\": {\n        \"@parcel/diagnostic\": \"2.16.4\",\n        \"@parcel/feature-flags\": \"2.16.4\",\n        \"@parcel/source-map\": \"^2.1.1\",\n        \"utility-types\": \"^3.11.0\"\n      }\n    },\n    \"node_modules/@parcel/utils\": {\n      \"version\": \"2.16.4\",\n      \"resolved\": \"https://registry.npmjs.org/@parcel/utils/-/utils-2.16.4.tgz\",\n      \"integrity\": \"sha512-lkmxQHcHyOWZLbV8t+h2CGZIkPiBurLm/TS5wNT7+tq0qt9KbVwL7FP2K93TbXhLMGTmpI79Bf3qKniPM167Mw==\",\n      \"dev\": true,\n      \"license\": \"MIT\",\n      \"dependencies\": {\n        \"@parcel/codeframe\": \"2.16.4\",\n        \"@parcel/diagnostic\": \"2.16.4\",\n        \"@parcel/logger\": \"2.16.4\",\n        \"@parcel/markdown-ansi\": \"2.16.4\",\n        \"@parcel/rust\": \"2.16.4\",\n        \"@parcel/source-map\": \"^2.1.1\",\n        \"chalk\": \"^4.1.2\",\n        \"nullthrows\": \"^1.1.1\"\n      },\n      \"engines\": {\n        \"node\": \">= 16.0.0\"\n      },\n      \"funding\": {\n        \"type\": \"opencollective\",\n        \"url\": \"https://opencollective.com/parcel\"\n      }\n    },\n    \"node_modules/@parcel/watcher\": {\n      \"version\": \"2.6.0\",\n      \"resolved\": \"https://registry.npmjs.org/@parcel/watcher/-/watcher-2.6.0.tgz\",\n      \"integrity\": \"sha512-7FNeNl8NCE7aINx7WXiKQrPYZWC/hvrTsmk6zmxbI7LTXE7hVek/n8AfVgpe2y82zl3w0HvCHN0bVKMBoJcC0w==\",\n      \"dev\": true,\n      \"hasInstallScript\": true,\n      \"license\": \"MIT\",\n      \"dependencies\": {\n        \"detect-libc\": \"^2.0.3\",\n        \"is-glob\": \"^4.0.3\",\n        \"node-addon-api\": \"^7.0.0\",\n        \"picomatch\": \"^4.0.4\"\n      },\n      \"engines\": {\n        \"node\": \">= 10.0.0\"\n      },\n      \"funding\": {\n        \"type\": \"opencollective\",\n        \"url\": \"https://opencollective.com/parcel\"\n      },\n      \"optionalDependencies\": {\n        \"@parcel/watcher-android-arm64\": \"2.6.0\",\n        \"@parcel/watcher-darwin-arm64\": \"2.6.0\",\n        \"@parcel/watcher-darwin-x64\": \"2.6.0\",\n        \"@parcel/watcher-freebsd-x64\": \"2.6.0\",\n        \"@parcel/watcher-linux-arm-glibc\": \"2.6.0\",\n        \"@parcel/watcher-linux-arm-musl\": \"2.6.0\",\n        \"@parcel/watcher-linux-arm64-glibc\": \"2.6.0\",\n        \"@parcel/watcher-linux-arm64-musl\": \"2.6.0\",\n        \"@parcel/watcher-linux-x64-glibc\": \"2.6.0\",\n        \"@parcel/watcher-linux-x64-musl\": \"2.6.0\",\n        \"@parcel/watcher-win32-arm64\": \"2.6.0\",\n        \"@parcel/watcher-win32-x64\": \"2.6.0\"\n      }\n    },\n    \"node_modules/@parcel/watcher-android-arm64\": {\n      \"version\": \"2.6.0\",\n      \"resolved\": \"https://registry.npmjs.org/@parcel/watcher-android-arm64/-/watcher-android-arm64-2.6.0.tgz\",\n      \"integrity\": \"sha512-trgpLSCKRC/huFjXX/Smh+0sWe4+YtKfktIToiMl59ghz7z+qkH6kMvNnUbLyRs9N11t8l4svSCs1+5B3rOAhA==\",\n      \"cpu\": [\n        \"arm64\"\n      ],\n      \"dev\": true,\n      \"license\": \"MIT\",\n      \"optional\": true,\n      \"os\": [\n        \"android\"\n      ],\n      \"engines\": {\n        \"node\": \">= 10.0.0\"\n      },\n      \"funding\": {\n        \"type\": \"opencollective\",\n        \"url\": \"https://opencollective.com/parcel\"\n      }\n    },\n    \"node_modules/@parcel/watcher-darwin-arm64\": {\n      \"version\": \"2.6.0\",\n      \"resolved\": \"https://registry.npmjs.org/@parcel/watcher-darwin-arm64/-/watcher-darwin-arm64-2.6.0.tgz\",\n      \"integrity\": \"sha512-Y3QV0gl7Q1zbfueunkWIERICbEojQFCgpyG7YqOGNFLsckXyI1xu9mAIUpKY9QBYzBtSkN8dBPwd3yiAO9ovMw==\",\n      \"cpu\": [\n        \"arm64\"\n      ],\n      \"dev\": true,\n      \"license\": \"MIT\",\n      \"optional\": true,\n      \"os\": [\n        \"darwin\"\n      ],\n      \"engines\": {\n        \"node\": \">= 10.0.0\"\n      },\n      \"funding\": {\n        \"type\": \"opencollective\",\n        \"url\": \"https://opencollective.com/parcel\"\n      }\n    },\n    \"node_modules/@parcel/watcher-darwin-x64\": {\n      \"version\": \"2.6.0\",\n      \"resolved\": \"https://registry.npmjs.org/@parcel/watcher-darwin-x64/-/watcher-darwin-x64-2.6.0.tgz\",\n      \"integrity\": \"sha512-Ohv6OpzhUfKYD7Beb8kDvG0jbIxORCYY1JRdZnaBtnjjkJxgD7ZVL0nw2sCYd0yTMKTvz3nnTnOF3cDifK+kvw==\",\n      \"cpu\": [\n        \"x64\"\n      ],\n      \"dev\": true,\n      \"license\": \"MIT\",\n      \"optional\": true,\n      \"os\": [\n        \"darwin\"\n      ],\n      \"engines\": {\n        \"node\": \">= 10.0.0\"\n      },\n      \"funding\": {\n        \"type\": \"opencollective\",\n        \"url\": \"https://opencollective.com/parcel\"\n      }\n    },\n    \"node_modules/@parcel/watcher-freebsd-x64\": {\n      \"version\": \"2.6.0\",\n      \"resolved\": \"https://registry.npmjs.org/@parcel/watcher-freebsd-x64/-/watcher-freebsd-x64-2.6.0.tgz\",\n      \"integrity\": \"sha512-5HmXvDgs8VK+74jF9y9/2FE3/OnlcKmc56tjmSrEuZjpSZOGL+fvAu+HKJBdPs9uwoP2hE6TlSUpXZ/C5jUFmQ==\",\n      \"cpu\": [\n        \"x64\"\n      ],\n      \"dev\": true,\n      \"license\": \"MIT\",\n      \"optional\": true,\n      \"os\": [\n        \"freebsd\"\n      ],\n      \"engines\": {\n        \"node\": \">= 10.0.0\"\n      },\n      \"funding\": {\n        \"type\": \"opencollective\",\n        \"url\": \"https://opencollective.com/parcel\"\n      }\n    },\n    \"node_modules/@parcel/watcher-linux-arm-glibc\": {\n      \"version\": \"2.6.0\",\n      \"resolved\": \"https://registry.npmjs.org/@parcel/watcher-linux-arm-glibc/-/watcher-linux-arm-glibc-2.6.0.tgz\",\n      \"integrity\": \"sha512-Ps/hui3A+vMbjdqlqAowK2ZL8+BO8dBjxeWXj6npTBs3jx4wWmbPpaLuqwrQrSqIVMCnpWo238bJ1U37GhQOYg==\",\n      \"cpu\": [\n        \"arm\"\n      ],\n      \"dev\": true,\n      \"license\": \"MIT\",\n      \"optional\": true,\n      \"os\": [\n        \"linux\"\n      ],\n      \"engines\": {\n        \"node\": \">= 10.0.0\"\n      },\n      \"funding\": {\n        \"type\": \"opencollective\",\n        \"url\": \"https://opencollective.com/parcel\"\n      }\n    },\n    \"node_modules/@parcel/watcher-linux-arm-musl\": {\n      \"version\": \"2.6.0\",\n      \"resolved\": \"https://registry.npmjs.org/@parcel/watcher-linux-arm-musl/-/watcher-linux-arm-musl-2.6.0.tgz\",\n      \"integrity\": \"sha512-9c6AUHgHoG+IY88MRIHupztQiQnrbqHYQjkM2btA+Bf/wQnQMuiD0Wfk1EVv3TlNT3x41uU71rn6E4xh/+zvkw==\",\n      \"cpu\": [\n        \"arm\"\n      ],\n      \"dev\": true,\n      \"license\": \"MIT\",\n      \"optional\": true,\n      \"os\": [\n        \"linux\"\n      ],\n      \"engines\": {\n        \"node\": \">= 10.0.0\"\n      },\n      \"funding\": {\n        \"type\": \"opencollective\",\n        \"url\": \"https://opencollective.com/parcel\"\n      }\n    },\n    \"node_modules/@parcel/watcher-linux-arm64-glibc\": {\n      \"version\": \"2.6.0\",\n      \"resolved\": \"https://registry.npmjs.org/@parcel/watcher-linux-arm64-glibc/-/watcher-linux-arm64-glibc-2.6.0.tgz\",\n      \"integrity\": \"sha512-yHRqS2owEXe6Hic9z6Mh1ECsCd+ODVOGvZDyciqRd21+v+o+DnXMOrw50DSpIG2sb8GPEaPPmfeCAWKPJdq46g==\",\n      \"cpu\": [\n        \"arm64\"\n      ],\n      \"dev\": true,\n      \"license\": \"MIT\",\n      \"optional\": true,\n      \"os\": [\n        \"linux\"\n      ],\n      \"engines\": {\n        \"node\": \">= 10.0.0\"\n      },\n      \"funding\": {\n        \"type\": \"opencollective\",\n        \"url\": \"https://opencollective.com/parcel\"\n      }\n    },\n    \"node_modules/@parcel/watcher-linux-arm64-musl\": {\n      \"version\": \"2.6.0\",\n      \"resolved\": \"https://registry.npmjs.org/@parcel/watcher-linux-arm64-musl/-/watcher-linux-arm64-musl-2.6.0.tgz\",\n      \"integrity\": \"sha512-WhB2e/V7rqdHHWZusBSPuy5Ei8S6lSz6FE5TKKQz5h3a0O+C+mhY7vxU9b/stqvMb8beLnPY82ZrFTLKs+SrKA==\",\n      \"cpu\": [\n        \"arm64\"\n      ],\n      \"dev\": true,\n      \"license\": \"MIT\",\n      \"optional\": true,\n      \"os\": [\n        \"linux\"\n      ],\n      \"engines\": {\n        \"node\": \">= 10.0.0\"\n      },\n      \"funding\": {\n        \"type\": \"opencollective\",\n        \"url\": \"https://opencollective.com/parcel\"\n      }\n    },\n    \"node_modules/@parcel/watcher-linux-x64-glibc\": {\n      \"version\": \"2.6.0\",\n      \"resolved\": \"https://registry.npmjs.org/@parcel/watcher-linux-x64-glibc/-/watcher-linux-x64-glibc-2.6.0.tgz\",\n      \"integrity\": \"sha512-ulGE6x6Oz6iAwg75T8YQSoguBWasniIbX+QWpaYPcCnDOpdWX3k+4xbEYPZVLxOuoJI+svJJPD3sEj8G7lrQ3A==\",\n      \"cpu\": [\n        \"x64\"\n      ],\n      \"dev\": true,\n      \"license\": \"MIT\",\n      \"optional\": true,\n      \"os\": [\n        \"linux\"\n      ],\n      \"engines\": {\n        \"node\": \">= 10.0.0\"\n      },\n      \"funding\": {\n        \"type\": \"opencollective\",\n        \"url\": \"https://opencollective.com/parcel\"\n      }\n    },\n    \"node_modules/@parcel/watcher-linux-x64-musl\": {\n      \"version\": \"2.6.0\",\n      \"resolved\": \"https://registry.npmjs.org/@parcel/watcher-linux-x64-musl/-/watcher-linux-x64-musl-2.6.0.tgz\",\n      \"integrity\": \"sha512-tkBYKt7YQrjIJWYDnto2YgO8MRkjlMTSNoRHzsXinBqbLdeOM3L32wPZJvIZxqaLMfSlS/4sUjH/6STVP/XDLw==\",\n      \"cpu\": [\n        \"x64\"\n      ],\n      \"dev\": true,\n      \"license\": \"MIT\",\n      \"optional\": true,\n      \"os\": [\n        \"linux\"\n      ],\n      \"engines\": {\n        \"node\": \">= 10.0.0\"\n      },\n      \"funding\": {\n        \"type\": \"opencollective\",\n        \"url\": \"https://opencollective.com/parcel\"\n      }\n    },\n    \"node_modules/@parcel/watcher-win32-arm64\": {\n      \"version\": \"2.6.0\",\n      \"resolved\": \"https://registry.npmjs.org/@parcel/watcher-win32-arm64/-/watcher-win32-arm64-2.6.0.tgz\",\n      \"integrity\": \"sha512-gIZAP23jaHjGWasY/TY6yL7NHFClf0Ga7FN+iINvk+KN94rhm94lYZhFsbYFNcA04/onvGD9kKmiJLJB2HbNwQ==\",\n      \"cpu\": [\n        \"arm64\"\n      ],\n      \"dev\": true,\n      \"license\": \"MIT\",\n      \"optional\": true,\n      \"os\": [\n        \"win32\"\n      ],\n      \"engines\": {\n        \"node\": \">= 10.0.0\"\n      },\n      \"funding\": {\n        \"type\": \"opencollective\",\n        \"url\": \"https://opencollective.com/parcel\"\n      }\n    },\n    \"node_modules/@parcel/watcher-win32-x64\": {\n      \"version\": \"2.6.0\",\n      \"resolved\": \"https://registry.npmjs.org/@parcel/watcher-win32-x64/-/watcher-win32-x64-2.6.0.tgz\",\n      \"integrity\": \"sha512-cA+/pXV2YkfxlIcXOQ5fSWqAzzPyD78/x5qbK/I0vUkrlYHA8TIz+MXjAbGouguKVSI4bOmkTSJ1/poVSsgt+A==\",\n      \"cpu\": [\n        \"x64\"\n      ],\n      \"dev\": true,\n      \"license\": \"MIT\",\n      \"optional\": true,\n      \"os\": [\n        \"win32\"\n      ],\n      \"engines\": {\n        \"node\": \">= 10.0.0\"\n      },\n      \"funding\": {\n        \"type\": \"opencollective\",\n        \"url\": \"https://opencollective.com/parcel\"\n      }\n    },\n    \"node_modules/@parcel/watcher/node_modules/detect-libc\": {\n      \"version\": \"2.1.2\",\n      \"resolved\": \"https://registry.npmjs.org/detect-libc/-/detect-libc-2.1.2.tgz\",\n      \"integrity\": \"sha512-Btj2BOOO83o3WyH59e8MgXsxEQVcarkUOpEYrubB0urwnN10yQ364rsiByU11nZlqWYZm05i/of7io4mzihBtQ==\",\n      \"dev\": true,\n      \"license\": \"Apache-2.0\",\n      \"engines\": {\n        \"node\": \">=8\"\n      }\n    },\n    \"node_modules/@parcel/watcher/node_modules/picomatch\": {\n      \"version\": \"4.0.7\",\n      \"resolved\": \"https://registry.npmjs.org/picomatch/-/picomatch-4.0.7.tgz\",\n      \"integrity\": \"sha512-qcJu88Q2IWqJsDD529JKMdwGm/dvInW4HvQnRwiH9JtihJvzGOscDtHE3x1pBKeUOTysQ8kVmLnJ2kJu7yhcGA==\",\n      \"dev\": true,\n      \"license\": \"MIT\",\n      \"engines\": {\n        \"node\": \">=12\"\n      },\n      \"funding\": {\n        \"url\": \"https://github.com/sponsors/jonschlinkert\"\n      }\n    },\n    \"node_modules/@parcel/workers\": {\n      \"version\": \"2.16.4\",\n      \"resolved\": \"https://registry.npmjs.org/@parcel/workers/-/workers-2.16.4.tgz\",\n      \"integrity\": \"sha512-dkBEWqnHXDZnRbTZouNt4uEGIslJT+V0c8OH1MPOfjISp1ucD6/u9ET8k9d/PxS9h1hL53og0SpBuuSEPLDl6A==\",\n      \"dev\": true,\n      \"license\": \"MIT\",\n      \"dependencies\": {\n        \"@parcel/diagnostic\": \"2.16.4\",\n        \"@parcel/logger\": \"2.16.4\",\n        \"@parcel/profiler\": \"2.16.4\",\n        \"@parcel/types-internal\": \"2.16.4\",\n        \"@parcel/utils\": \"2.16.4\",\n        \"nullthrows\": \"^1.1.1\"\n      },\n      \"engines\": {\n        \"node\": \">= 16.0.0\"\n      },\n      \"funding\": {\n        \"type\": \"opencollective\",\n        \"url\": \"https://opencollective.com/parcel\"\n      },\n      \"peerDependencies\": {\n        \"@parcel/core\": \"^2.16.4\"\n      }\n    },\n    \"node_modules/@swc/core\": {\n      \"version\": \"1.16.20\",\n      \"resolved\": \"https://registry.npmjs.org/@swc/core/-/core-1.16.20.tgz\",\n      \"integrity\": \"sha512-zcdfS7k28OJIMuLhqRRyGja9PxrC2GXhFXkbQ1X15y6uZEMsTrqyej55V1DiJtlXaDOmwSLn5222YPT9ZoFxPA==\",\n      \"dev\": true,\n      \"hasInstallScript\": true,\n      \"license\": \"Apache-2.0\",\n      \"dependencies\": {\n        \"@swc/counter\": \"^0.1.3\",\n        \"@swc/types\": \"^0.1.28\"\n      },\n      \"engines\": {\n        \"node\": \">=10\"\n      },\n      \"funding\": {\n        \"type\": \"opencollective\",\n        \"url\": \"https://opencollective.com/swc\"\n      },\n      \"optionalDependencies\": {\n        \"@swc/core-darwin-arm64\": \"1.16.20\",\n        \"@swc/core-darwin-x64\": \"1.16.20\",\n        \"@swc/core-linux-arm-gnueabihf\": \"1.16.20\",\n        \"@swc/core-linux-arm64-gnu\": \"1.16.20\",\n        \"@swc/core-linux-arm64-musl\": \"1.16.20\",\n        \"@swc/core-linux-ppc64-gnu\": \"1.16.20\",\n        \"@swc/core-linux-s390x-gnu\": \"1.16.20\",\n        \"@swc/core-linux-x64-gnu\": \"1.16.20\",\n        \"@swc/core-linux-x64-musl\": \"1.16.20\",\n        \"@swc/core-win32-arm64-msvc\": \"1.16.20\",\n        \"@swc/core-win32-ia32-msvc\": \"1.16.20\",\n        \"@swc/core-win32-x64-msvc\": \"1.16.20\"\n      },\n      \"peerDependencies\": {\n        \"@swc/helpers\": \">=0.5.17\"\n      },\n      \"peerDependenciesMeta\": {\n        \"@swc/helpers\": {\n          \"optional\": true\n        }\n      }\n    },\n    \"node_modules/@swc/core-darwin-arm64\": {\n      \"version\": \"1.16.20\",\n      \"resolved\": \"https://registry.npmjs.org/@swc/core-darwin-arm64/-/core-darwin-arm64-1.16.20.tgz\",\n      \"integrity\": \"sha512-i7NFSDnuE6tdBvBgmoVKKmburgcwZt/FZK2IusJaVGrjFrMUC1hrgE3RI+Kt9RhYM7vHvQj0W9j53zSxKEMbWQ==\",\n      \"cpu\": [\n        \"arm64\"\n      ],\n      \"dev\": true,\n      \"license\": \"Apache-2.0 AND MIT\",\n      \"optional\": true,\n      \"os\": [\n        \"darwin\"\n      ],\n      \"engines\": {\n        \"node\": \">=10\"\n      }\n    },\n    \"node_modules/@swc/core-darwin-x64\": {\n      \"version\": \"1.16.20\",\n      \"resolved\": \"https://registry.npmjs.org/@swc/core-darwin-x64/-/core-darwin-x64-1.16.20.tgz\",\n      \"integrity\": \"sha512-ho/LkT1Q3beSBeZGNZnm1mVbh5bKZHC0UGHtK3MswqOylbHtZoMXJBL40N8JpDj5SBxwECmdNEyXnU9HJ4F6RA==\",\n      \"cpu\": [\n        \"x64\"\n      ],\n      \"dev\": true,\n      \"license\": \"Apache-2.0 AND MIT\",\n      \"optional\": true,\n      \"os\": [\n        \"darwin\"\n      ],\n      \"engines\": {\n        \"node\": \">=10\"\n      }\n    },\n    \"node_modules/@swc/core-linux-arm-gnueabihf\": {\n      \"version\": \"1.16.20\",\n      \"resolved\": \"https://registry.npmjs.org/@swc/core-linux-arm-gnueabihf/-/core-linux-arm-gnueabihf-1.16.20.tgz\",\n      \"integrity\": \"sha512-xm3/s3zp9WyNgB1Sl78tpH76MHgobI3TSenTY15bkSHyrdQa9W2MUSESHRPd7CHGFLfpWl/0jwwNp5+hwG0e9A==\",\n      \"cpu\": [\n        \"arm\"\n      ],\n      \"dev\": true,\n      \"license\": \"Apache-2.0\",\n      \"optional\": true,\n      \"os\": [\n        \"linux\"\n      ],\n      \"engines\": {\n        \"node\": \">=10\"\n      }\n    },\n    \"node_modules/@swc/core-linux-arm64-gnu\": {\n      \"version\": \"1.16.20\",\n      \"resolved\": \"https://registry.npmjs.org/@swc/core-linux-arm64-gnu/-/core-linux-arm64-gnu-1.16.20.tgz\",\n      \"integrity\": \"sha512-e6Um0U+VcTQyurOXhbratRQlrPITSRwugG00fhICbi2MGTi1vRiE4TMqGCjWpR1zPmZKXDGMw+yNFvh7AAgT2Q==\",\n      \"cpu\": [\n        \"arm64\"\n      ],\n      \"dev\": true,\n      \"license\": \"Apache-2.0 AND MIT\",\n      \"optional\": true,\n      \"os\": [\n        \"linux\"\n      ],\n      \"engines\": {\n        \"node\": \">=10\"\n      }\n    },\n    \"node_modules/@swc/core-linux-arm64-musl\": {\n      \"version\": \"1.16.20\",\n      \"resolved\": \"https://registry.npmjs.org/@swc/core-linux-arm64-musl/-/core-linux-arm64-musl-1.16.20.tgz\",\n      \"integrity\": \"sha512-ekCO2obfK9NFwXGHfAQjjuU5mLDDC7qMaUJH/V/4iyzD0BqNhilr6McZrXLytOQ/xKtTNxLQ71wYrD3M2LW8Kg==\",\n      \"cpu\": [\n        \"arm64\"\n      ],\n      \"dev\": true,\n      \"license\": \"Apache-2.0 AND MIT\",\n      \"optional\": true,\n      \"os\": [\n        \"linux\"\n      ],\n      \"engines\": {\n        \"node\": \">=10\"\n      }\n    },\n    \"node_modules/@swc/core-linux-ppc64-gnu\": {\n      \"version\": \"1.16.20\",\n      \"resolved\": \"https://registry.npmjs.org/@swc/core-linux-ppc64-gnu/-/core-linux-ppc64-gnu-1.16.20.tgz\",\n      \"integrity\": \"sha512-6/x2K3l4GNUWyaSmkywnth6ipZISzhVzOLsI66bj12/hSQYaKAyg9MKTwnuFf2B/iYA6GrjDghk36RYghRameQ==\",\n      \"cpu\": [\n        \"ppc64\"\n      ],\n      \"dev\": true,\n      \"license\": \"Apache-2.0 AND MIT\",\n      \"optional\": true,\n      \"os\": [\n        \"linux\"\n      ],\n      \"engines\": {\n        \"node\": \">=10\"\n      }\n    },\n    \"node_modules/@swc/core-linux-s390x-gnu\": {\n      \"version\": \"1.16.20\",\n      \"resolved\": \"https://registry.npmjs.org/@swc/core-linux-s390x-gnu/-/core-linux-s390x-gnu-1.16.20.tgz\",\n      \"integrity\": \"sha512-1GTd8sqS/NpcF+Y3YDSE0bT31V61+hD7ZZWEsVyiyxk/HQt2zpk4zlJJHOASBLc+/CyUuBZ949n6QMszbIXkmQ==\",\n      \"cpu\": [\n        \"s390x\"\n      ],\n      \"dev\": true,\n      \"license\": \"Apache-2.0 AND MIT\",\n      \"optional\": true,\n      \"os\": [\n        \"linux\"\n      ],\n      \"engines\": {\n        \"node\": \">=10\"\n      }\n    },\n    \"node_modules/@swc/core-linux-x64-gnu\": {\n      \"version\": \"1.16.20\",\n      \"resolved\": \"https://registry.npmjs.org/@swc/core-linux-x64-gnu/-/core-linux-x64-gnu-1.16.20.tgz\",\n      \"integrity\": \"sha512-XtMeYAgQa5UZhAX84TXn0sXPmhf1xHwcv0cl5hHiBXxTVbplY7WiTwIQU9uOtVm3VUqL/quyCm78/umUNZ7FmA==\",\n      \"cpu\": [\n        \"x64\"\n      ],\n      \"dev\": true,\n      \"license\": \"Apache-2.0 AND MIT\",\n      \"optional\": true,\n      \"os\": [\n        \"linux\"\n      ],\n      \"engines\": {\n        \"node\": \">=10\"\n      }\n    },\n    \"node_modules/@swc/core-linux-x64-musl\": {\n      \"version\": \"1.16.20\",\n      \"resolved\": \"https://registry.npmjs.org/@swc/core-linux-x64-musl/-/core-linux-x64-musl-1.16.20.tgz\",\n      \"integrity\": \"sha512-qeF3UILa+MA4zJ29CdQ8KE7YbGFPMQBxWo3Lh0Ed0ETFEJ8pCKISWo7wQG4/SmfM9HX4KT1Odoj6ixyBn6Ji2Q==\",\n      \"cpu\": [\n        \"x64\"\n      ],\n      \"dev\": true,\n      \"license\": \"Apache-2.0 AND MIT\",\n      \"optional\": true,\n      \"os\": [\n        \"linux\"\n      ],\n      \"engines\": {\n        \"node\": \">=10\"\n      }\n    },\n    \"node_modules/@swc/core-win32-arm64-msvc\": {\n      \"version\": \"1.16.20\",\n      \"resolved\": \"https://registry.npmjs.org/@swc/core-win32-arm64-msvc/-/core-win32-arm64-msvc-1.16.20.tgz\",\n      \"integrity\": \"sha512-ciMtHXAmE+jnrWWO14rErr6tfK34QZm8jZRSdRLPodqJlzrYDw7TqN60HC8Yim5Ua9a1r/poyfkpNft6GRXvxA==\",\n      \"cpu\": [\n        \"arm64\"\n      ],\n      \"dev\": true,\n      \"license\": \"Apache-2.0 AND MIT\",\n      \"optional\": true,\n      \"os\": [\n        \"win32\"\n      ],\n      \"engines\": {\n        \"node\": \">=10\"\n      }\n    },\n    \"node_modules/@swc/core-win32-ia32-msvc\": {\n      \"version\": \"1.16.20\",\n      \"resolved\": \"https://registry.npmjs.org/@swc/core-win32-ia32-msvc/-/core-win32-ia32-msvc-1.16.20.tgz\",\n      \"integrity\": \"sha512-MTbkgGooWebmjmATx1+QRECVZ+q4ICKNXCutwOrFVD5b5hdxla/yV4e6cRFrfNMowejaNpmMQg31ENWt0Yfzpg==\",\n      \"cpu\": [\n        \"ia32\"\n      ],\n      \"dev\": true,\n      \"license\": \"Apache-2.0 AND MIT\",\n      \"optional\": true,\n      \"os\": [\n        \"win32\"\n      ],\n      \"engines\": {\n        \"node\": \">=10\"\n      }\n    },\n    \"node_modules/@swc/core-win32-x64-msvc\": {\n      \"version\": \"1.16.20\",\n      \"resolved\": \"https://registry.npmjs.org/@swc/core-win32-x64-msvc/-/core-win32-x64-msvc-1.16.20.tgz\",\n      \"integrity\": \"sha512-Lf5oMaSdJBImtGhDecasxcIa7Z5LeJ4aGmBOY7TScroO+A/MxxB9PslIpgV0rtG/FcxtipN7hveBg9ZTeboaaw==\",\n      \"cpu\": [\n        \"x64\"\n      ],\n      \"dev\": true,\n      \"license\": \"Apache-2.0 AND MIT\",\n      \"optional\": true,\n      \"os\": [\n        \"win32\"\n      ],\n      \"engines\": {\n        \"node\": \">=10\"\n      }\n    },\n    \"node_modules/@swc/counter\": {\n      \"version\": \"0.1.3\",\n      \"resolved\": \"https://registry.npmjs.org/@swc/counter/-/counter-0.1.3.tgz\",\n      \"integrity\": \"sha512-e2BR4lsJkkRlKZ/qCHPw9ZaSxc0MVUd7gtbtaB7aMvHeJVYe8sOB8DBZkP2DtISHGSku9sCK6T6cnY0CtXrOCQ==\",\n      \"dev\": true,\n      \"license\": \"Apache-2.0\"\n    },\n    \"node_modules/@swc/helpers\": {\n      \"version\": \"0.5.23\",\n      \"resolved\": \"https://registry.npmjs.org/@swc/helpers/-/helpers-0.5.23.tgz\",\n      \"integrity\": \"sha512-5lSsMOTXURePglDfvuAQUqkGek9Hg2kksOYay2m0+XR++b2NWYL/4sWyuvVBIs8oKnJaxkdi9whaL/sqN13afw==\",\n      \"dev\": true,\n      \"license\": \"Apache-2.0\",\n      \"dependencies\": {\n        \"tslib\": \"^2.8.0\"\n      }\n    },\n    \"node_modules/@swc/types\": {\n      \"version\": \"0.1.28\",\n      \"resolved\": \"https://registry.npmjs.org/@swc/types/-/types-0.1.28.tgz\",\n      \"integrity\": \"sha512-V6Mnml8v09QALx6K0elJ7o9K/MkVDtW3t6L+7Ou/JcWtb3xwId2AH4FeOceySd2JaO87IMw4+6vSZxLm34LPbw==\",\n      \"dev\": true,\n      \"license\": \"Apache-2.0\",\n      \"dependencies\": {\n        \"@swc/counter\": \"^0.1.3\"\n      }\n    },\n    \"node_modules/@tsconfig/node10\": {\n      \"version\": \"1.0.13\",\n      \"resolved\": \"https://registry.npmjs.org/@tsconfig/node10/-/node10-1.0.13.tgz\",\n      \"integrity\": \"sha512-gcLdvR9HO1ZJBypsOGqaP6TFEzb6vIta0KSTLt9NAQ6pXQO3cRgSVyCN6pzYqI9DlJgY71XKO0dpDhCf08b3pg==\",\n      \"dev\": true,\n      \"license\": \"MIT\"\n    },\n    \"node_modules/@tsconfig/node12\": {\n      \"version\": \"1.0.11\",\n      \"resolved\": \"https://registry.npmjs.org/@tsconfig/node12/-/node12-1.0.11.tgz\",\n      \"integrity\": \"sha512-cqefuRsh12pWyGsIoBKJA9luFu3mRxCA+ORZvA4ktLSzIuCUtWVxGIuXigEwO5/ywWFMZ2QEGKWvkZG1zDMTag==\",\n      \"dev\": true,\n      \"license\": \"MIT\"\n    },\n    \"node_modules/@tsconfig/node14\": {\n      \"version\": \"1.0.3\",\n      \"resolved\": \"https://registry.npmjs.org/@tsconfig/node14/-/node14-1.0.3.tgz\",\n      \"integrity\": \"sha512-ysT8mhdixWK6Hw3i1V2AeRqZ5WfXg1G43mqoYlM2nc6388Fq5jcXyr5mRsqViLx/GJYdoL0bfXD8nmF+Zn/Iow==\",\n      \"dev\": true,\n      \"license\": \"MIT\"\n    },\n    \"node_modules/@tsconfig/node16\": {\n      \"version\": \"1.0.4\",\n      \"resolved\": \"https://registry.npmjs.org/@tsconfig/node16/-/node16-1.0.4.tgz\",\n      \"integrity\": \"sha512-vxhUy4J8lyeyinH7Azl1pdd43GJhZH/tP2weN8TntQblOY+A0XbT8DJk1/oCPuOOyg/Ja757rG0CgHcWC8OfMA==\",\n      \"dev\": true,\n      \"license\": \"MIT\"\n    },\n    \"node_modules/@types/adm-zip\": {\n      \"version\": \"0.5.8\",\n      \"resolved\": \"https://registry.npmjs.org/@types/adm-zip/-/adm-zip-0.5.8.tgz\",\n      \"integrity\": \"sha512-RVVH7QvZYbN+ihqZ4kX/dMiowf6o+Jk1fNwiSdx0NahBJLU787zkULhGhJM8mf/obmLGmgdMM0bXsQTmyfbR7Q==\",\n      \"dev\": true,\n      \"license\": \"MIT\",\n      \"dependencies\": {\n        \"@types/node\": \"*\"\n      }\n    },\n    \"node_modules/@types/hoist-non-react-statics\": {\n      \"version\": \"3.3.7\",\n      \"resolved\": \"https://registry.npmjs.org/@types/hoist-non-react-statics/-/hoist-non-react-statics-3.3.7.tgz\",\n      \"integrity\": \"sha512-PQTyIulDkIDro8P+IHbKCsw7U2xxBYflVzW/FgWdCAePD9xGSidgA76/GeJ6lBKoblyhf9pBY763gbrN+1dI8g==\",\n      \"license\": \"MIT\",\n      \"dependencies\": {\n        \"hoist-non-react-statics\": \"^3.3.0\"\n      },\n      \"peerDependencies\": {\n        \"@types/react\": \"*\"\n      }\n    },\n    \"node_modules/@types/lz-string\": {\n      \"version\": \"1.3.34\",\n      \"resolved\": \"https://registry.npmjs.org/@types/lz-string/-/lz-string-1.3.34.tgz\",\n      \"integrity\": \"sha512-j6G1e8DULJx3ONf6NdR5JiR2ZY3K3PaaqiEuKYkLQO0Czfi1AzrtjfnfCROyWGeDd5IVMKCwsgSmMip9OWijow==\",\n      \"dev\": true,\n      \"license\": \"MIT\"\n    },\n    \"node_modules/@types/marked\": {\n      \"version\": \"4.3.2\",\n      \"resolved\": \"https://registry.npmjs.org/@types/marked/-/marked-4.3.2.tgz\",\n      \"integrity\": \"sha512-a79Yc3TOk6dGdituy8hmTTJXjOkZ7zsFYV10L337ttq/rec8lRMDBpV7fL3uLx6TgbFCa5DU/h8FmIBQPSbU0w==\",\n      \"dev\": true,\n      \"license\": \"MIT\"\n    },\n    \"node_modules/@types/mocha\": {\n      \"version\": \"7.0.2\",\n      \"resolved\": \"https://registry.npmjs.org/@types/mocha/-/mocha-7.0.2.tgz\",\n      \"integrity\": \"sha512-ZvO2tAcjmMi8V/5Z3JsyofMe3hasRcaw88cto5etSVMwVQfeivGAlEYmaQgceUSVYFofVjT+ioHsATjdWcFt1w==\",\n      \"dev\": true,\n      \"license\": \"MIT\"\n    },\n    \"node_modules/@types/node\": {\n      \"version\": \"13.13.52\",\n      \"resolved\": \"https://registry.npmjs.org/@types/node/-/node-13.13.52.tgz\",\n      \"integrity\": \"sha512-s3nugnZumCC//n4moGGe6tkNMyYEdaDBitVjwPxXmR5lnMG5dHePinH2EdxkG3Rh1ghFHHixAG4NJhpJW1rthQ==\",\n      \"dev\": true,\n      \"license\": \"MIT\"\n    },\n    \"node_modules/@types/prop-types\": {\n      \"version\": \"15.7.15\",\n      \"resolved\": \"https://registry.npmjs.org/@types/prop-types/-/prop-types-15.7.15.tgz\",\n      \"integrity\": \"sha512-F6bEyamV9jKGAFBEmlQnesRPGOQqS2+Uwi0Em15xenOxHaf2hv6L8YCVn3rPdPJOiJfPiCnLIRyvwVaqMY3MIw==\",\n      \"license\": \"MIT\"\n    },\n    \"node_modules/@types/react\": {\n      \"version\": \"18.3.31\",\n      \"resolved\": \"https://registry.npmjs.org/@types/react/-/react-18.3.31.tgz\",\n      \"integrity\": \"sha512-vfEqpXTvwT91yhmwdfouStN2hSKwTvyRs8qpLfADyrq/kxDw0hZM7Wk9Ug1FELj8hIby+S/+kQCSRFF32nv2Qw==\",\n      \"license\": \"MIT\",\n      \"dependencies\": {\n        \"@types/prop-types\": \"*\",\n        \"csstype\": \"^3.2.2\"\n      }\n    },\n    \"node_modules/acorn\": {\n      \"version\": \"8.19.0\",\n      \"resolved\": \"https://registry.npmjs.org/acorn/-/acorn-8.19.0.tgz\",\n      \"integrity\": \"sha512-oJlA3XiRm7Cyk6qFD2Jn8ak9B7jSy0qy00ADO3+8dpT0LSjFihQYv4C02LFCSYJV3Q37xYwwRy5m+IpIiUzqWw==\",\n      \"dev\": true,\n      \"license\": \"MIT\",\n      \"bin\": {\n        \"acorn\": \"bin/acorn\"\n      },\n      \"engines\": {\n        \"node\": \">=0.4.0\"\n      }\n    },\n    \"node_modules/acorn-walk\": {\n      \"version\": \"8.3.5\",\n      \"resolved\": \"https://registry.npmjs.org/acorn-walk/-/acorn-walk-8.3.5.tgz\",\n      \"integrity\": \"sha512-HEHNfbars9v4pgpW6SO1KSPkfoS0xVOM/9UzkJltjlsHZmJasxg8aXkuZa7SMf8vKGIBhpUsPluQSqhJFCqebw==\",\n      \"dev\": true,\n      \"license\": \"MIT\",\n      \"dependencies\": {\n        \"acorn\": \"^8.11.0\"\n      },\n      \"engines\": {\n        \"node\": \">=0.4.0\"\n      }\n    },\n    \"node_modules/adm-zip\": {\n      \"version\": \"0.5.18\",\n      \"resolved\": \"https://registry.npmjs.org/adm-zip/-/adm-zip-0.5.18.tgz\",\n      \"integrity\": \"sha512-ufJnssQGbxzLNS1Ho9bCtX4rQKCCvoVuDLHoJyc3F9dOGDB4BkWs2Ci0kv53lqocAEQ/Cbi+I2XCsNYGqVYqng==\",\n      \"dev\": true,\n      \"license\": \"MIT\",\n      \"engines\": {\n        \"node\": \">=12.0\"\n      }\n    },\n    \"node_modules/ansi-colors\": {\n      \"version\": \"4.1.3\",\n      \"resolved\": \"https://registry.npmjs.org/ansi-colors/-/ansi-colors-4.1.3.tgz\",\n      \"integrity\": \"sha512-/6w/C21Pm1A7aZitlI5Ni/2J6FFQN8i1Cvz3kHABAAbw93v/NlvKdVOqz7CCWz/3iv/JplRSEEZ83XION15ovw==\",\n      \"dev\": true,\n      \"license\": \"MIT\",\n      \"engines\": {\n        \"node\": \">=6\"\n      }\n    },\n    \"node_modules/ansi-regex\": {\n      \"version\": \"5.0.1\",\n      \"resolved\": \"https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz\",\n      \"integrity\": \"sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==\",\n      \"dev\": true,\n      \"license\": \"MIT\",\n      \"engines\": {\n        \"node\": \">=8\"\n      }\n    },\n    \"node_modules/ansi-styles\": {\n      \"version\": \"4.3.0\",\n      \"resolved\": \"https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz\",\n      \"integrity\": \"sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==\",\n      \"dev\": true,\n      \"license\": \"MIT\",\n      \"dependencies\": {\n        \"color-convert\": \"^2.0.1\"\n      },\n      \"engines\": {\n        \"node\": \">=8\"\n      },\n      \"funding\": {\n        \"url\": \"https://github.com/chalk/ansi-styles?sponsor=1\"\n      }\n    },\n    \"node_modules/anymatch\": {\n      \"version\": \"3.1.3\",\n      \"resolved\": \"https://registry.npmjs.org/anymatch/-/anymatch-3.1.3.tgz\",\n      \"integrity\": \"sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw==\",\n      \"dev\": true,\n      \"license\": \"ISC\",\n      \"dependencies\": {\n        \"normalize-path\": \"^3.0.0\",\n        \"picomatch\": \"^2.0.4\"\n      },\n      \"engines\": {\n        \"node\": \">= 8\"\n      }\n    },\n    \"node_modules/arg\": {\n      \"version\": \"4.1.3\",\n      \"resolved\": \"https://registry.npmjs.org/arg/-/arg-4.1.3.tgz\",\n      \"integrity\": \"sha512-58S9QDqG0Xx27YwPSt9fJxivjYl432YCwfDMfZ+71RAqUrZef7LrKQZ3LHLOwCS4FLNBplP533Zx895SeOCHvA==\",\n      \"dev\": true,\n      \"license\": \"MIT\"\n    },\n    \"node_modules/argparse\": {\n      \"version\": \"2.0.1\",\n      \"resolved\": \"https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz\",\n      \"integrity\": \"sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==\",\n      \"dev\": true,\n      \"license\": \"Python-2.0\"\n    },\n    \"node_modules/asap\": {\n      \"version\": \"2.0.6\",\n      \"resolved\": \"https://registry.npmjs.org/asap/-/asap-2.0.6.tgz\",\n      \"integrity\": \"sha512-BSHWgDSAiKs50o2Re8ppvp3seVHXSRM44cdSsT9FfNEUUZLOGWVCsiWaRPWM1Znn+mqZ1OfVZ3z3DWEzSp7hRA==\",\n      \"license\": \"MIT\"\n    },\n    \"node_modules/backtrace-js\": {\n      \"version\": \"1.1.3\",\n      \"resolved\": \"https://registry.npmjs.org/backtrace-js/-/backtrace-js-1.1.3.tgz\",\n      \"integrity\": \"sha512-BycxY6Ggi1+/09QNMprStIcYdR5G76Wgnr/7XsWlDOJs7nZ4Y4fSo4XX8bMRxKpl3BVE78rJQFw8D2vgievtQA==\",\n      \"license\": \"MIT\"\n    },\n    \"node_modules/balanced-match\": {\n      \"version\": \"1.0.2\",\n      \"resolved\": \"https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz\",\n      \"integrity\": \"sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==\",\n      \"dev\": true,\n      \"license\": \"MIT\"\n    },\n    \"node_modules/base-x\": {\n      \"version\": \"3.0.11\",\n      \"resolved\": \"https://registry.npmjs.org/base-x/-/base-x-3.0.11.tgz\",\n      \"integrity\": \"sha512-xz7wQ8xDhdyP7tQxwdteLYeFfS68tSMNCZ/Y37WJ4bhGfKPpqEIlmIyueQHqOyoPhE6xNUqjzRr8ra0eF9VRvA==\",\n      \"dev\": true,\n      \"license\": \"MIT\",\n      \"dependencies\": {\n        \"safe-buffer\": \"^5.0.1\"\n      }\n    },\n    \"node_modules/baseline-browser-mapping\": {\n      \"version\": \"2.11.33\",\n      \"resolved\": \"https://registry.npmjs.org/baseline-browser-mapping/-/baseline-browser-mapping-2.11.33.tgz\",\n      \"integrity\": \"sha512-yiVKDX+qCMRKBE084lXvq9EcwFUhKZ2nU8TK1EQQuOgPNR/lmbGxXOeDdlGUqC2Zz11Cs9rk1d/8NfgBmlkt0w==\",\n      \"dev\": true,\n      \"license\": \"Apache-2.0\",\n      \"bin\": {\n        \"baseline-browser-mapping\": \"dist/cli.cjs\"\n      },\n      \"engines\": {\n        \"node\": \">=6.0.0\"\n      }\n    },\n    \"node_modules/binary-extensions\": {\n      \"version\": \"2.3.0\",\n      \"resolved\": \"https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.3.0.tgz\",\n      \"integrity\": \"sha512-Ceh+7ox5qe7LJuLHoY0feh3pHuUDHAcRUeyL2VYghZwfpkNIy/+8Ocg0a3UuSoYzavmylwuLWQOf3hl0jjMMIw==\",\n      \"dev\": true,\n      \"license\": \"MIT\",\n      \"engines\": {\n        \"node\": \">=8\"\n      },\n      \"funding\": {\n        \"url\": \"https://github.com/sponsors/sindresorhus\"\n      }\n    },\n    \"node_modules/brace-expansion\": {\n      \"version\": \"2.1.7\",\n      \"resolved\": \"https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.1.7.tgz\",\n      \"integrity\": \"sha512-uZbew1NqdmPDTMJ8ah1y+b+9QEJrfkXFk3RcTQw3X0jW/xRUvFKsg1CfQdSYGdTbXZWExtU3J3ccxtnfw1Fi0g==\",\n      \"dev\": true,\n      \"license\": \"MIT\",\n      \"dependencies\": {\n        \"balanced-match\": \"^1.0.0\"\n      }\n    },\n    \"node_modules/braces\": {\n      \"version\": \"3.0.3\",\n      \"resolved\": \"https://registry.npmjs.org/braces/-/braces-3.0.3.tgz\",\n      \"integrity\": \"sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==\",\n      \"dev\": true,\n      \"license\": \"MIT\",\n      \"dependencies\": {\n        \"fill-range\": \"^7.1.1\"\n      },\n      \"engines\": {\n        \"node\": \">=8\"\n      }\n    },\n    \"node_modules/browser-stdout\": {\n      \"version\": \"1.3.1\",\n      \"resolved\": \"https://registry.npmjs.org/browser-stdout/-/browser-stdout-1.3.1.tgz\",\n      \"integrity\": \"sha512-qhAVI1+Av2X7qelOfAIYwXONood6XlZE/fXaBSmW/T5SzLAmCgzi+eiWE7fUvbHaeNBQH13UftjpXxsfLkMpgw==\",\n      \"dev\": true,\n      \"license\": \"ISC\"\n    },\n    \"node_modules/browserslist\": {\n      \"version\": \"4.29.4\",\n      \"resolved\": \"https://registry.npmjs.org/browserslist/-/browserslist-4.29.4.tgz\",\n      \"integrity\": \"sha512-2TcbbiwXEq+N0kD36tykpCfyyQigUXmuwNQbnPp4Xk4PX9JOqVIKjJlIDjpH7uY6tmRGoAd+apeT1p60T8wsdA==\",\n      \"dev\": true,\n      \"funding\": [\n        {\n          \"type\": \"opencollective\",\n          \"url\": \"https://opencollective.com/browserslist\"\n        },\n        {\n          \"type\": \"tidelift\",\n          \"url\": \"https://tidelift.com/funding/github/npm/browserslist\"\n        },\n        {\n          \"type\": \"github\",\n          \"url\": \"https://github.com/sponsors/ai\"\n        }\n      ],\n      \"license\": \"MIT\",\n      \"dependencies\": {\n        \"baseline-browser-mapping\": \"^2.11.29\",\n        \"caniuse-lite\": \"^1.0.30001816\",\n        \"electron-to-chromium\": \"^1.5.459\",\n        \"node-releases\": \"^2.0.59\",\n        \"update-browserslist-db\": \"^1.3.4\"\n      },\n      \"bin\": {\n        \"browserslist\": \"cli.js\"\n      },\n      \"engines\": {\n        \"node\": \"^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7\"\n      }\n    },\n    \"node_modules/camelcase\": {\n      \"version\": \"6.3.0\",\n      \"resolved\": \"https://registry.npmjs.org/camelcase/-/camelcase-6.3.0.tgz\",\n      \"integrity\": \"sha512-Gmy6FhYlCY7uOElZUSbxo2UCDH8owEk996gkbrpsgGtrJLM3J7jGxl9Ic7Qwwj4ivOE5AWZWRMecDdF7hqGjFA==\",\n      \"dev\": true,\n      \"license\": \"MIT\",\n      \"engines\": {\n        \"node\": \">=10\"\n      },\n      \"funding\": {\n        \"url\": \"https://github.com/sponsors/sindresorhus\"\n      }\n    },\n    \"node_modules/caniuse-lite\": {\n      \"version\": \"1.0.30001819\",\n      \"resolved\": \"https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001819.tgz\",\n      \"integrity\": \"sha512-LFUqIIAwpzsIuevnKnsR9qnStBcgzPShTX61lBwN9uFkkf8o8zLiebEjbW8AYtZiF+1YKDWfdt/pWDtMuG8Xwg==\",\n      \"dev\": true,\n      \"funding\": [\n        {\n          \"type\": \"opencollective\",\n          \"url\": \"https://opencollective.com/browserslist\"\n        },\n        {\n          \"type\": \"tidelift\",\n          \"url\": \"https://tidelift.com/funding/github/npm/caniuse-lite\"\n        },\n        {\n          \"type\": \"github\",\n          \"url\": \"https://github.com/sponsors/ai\"\n        }\n      ],\n      \"license\": \"CC-BY-4.0\"\n    },\n    \"node_modules/chalk\": {\n      \"version\": \"4.1.2\",\n      \"resolved\": \"https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz\",\n      \"integrity\": \"sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==\",\n      \"dev\": true,\n      \"license\": \"MIT\",\n      \"dependencies\": {\n        \"ansi-styles\": \"^4.1.0\",\n        \"supports-color\": \"^7.1.0\"\n      },\n      \"engines\": {\n        \"node\": \">=10\"\n      },\n      \"funding\": {\n        \"url\": \"https://github.com/chalk/chalk?sponsor=1\"\n      }\n    },\n    \"node_modules/chalk/node_modules/supports-color\": {\n      \"version\": \"7.2.0\",\n      \"resolved\": \"https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz\",\n      \"integrity\": \"sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==\",\n      \"dev\": true,\n      \"license\": \"MIT\",\n      \"dependencies\": {\n        \"has-flag\": \"^4.0.0\"\n      },\n      \"engines\": {\n        \"node\": \">=8\"\n      }\n    },\n    \"node_modules/chokidar\": {\n      \"version\": \"3.6.0\",\n      \"resolved\": \"https://registry.npmjs.org/chokidar/-/chokidar-3.6.0.tgz\",\n      \"integrity\": \"sha512-7VT13fmjotKpGipCW9JEQAusEPE+Ei8nl6/g4FBAmIm0GOOLMua9NDDo/DWp0ZAxCr3cPq5ZpBqmPAQgDda2Pw==\",\n      \"dev\": true,\n      \"license\": \"MIT\",\n      \"dependencies\": {\n        \"anymatch\": \"~3.1.2\",\n        \"braces\": \"~3.0.2\",\n        \"glob-parent\": \"~5.1.2\",\n        \"is-binary-path\": \"~2.1.0\",\n        \"is-glob\": \"~4.0.1\",\n        \"normalize-path\": \"~3.0.0\",\n        \"readdirp\": \"~3.6.0\"\n      },\n      \"engines\": {\n        \"node\": \">= 8.10.0\"\n      },\n      \"funding\": {\n        \"url\": \"https://paulmillr.com/funding/\"\n      },\n      \"optionalDependencies\": {\n        \"fsevents\": \"~2.3.2\"\n      }\n    },\n    \"node_modules/chrome-trace-event\": {\n      \"version\": \"1.0.4\",\n      \"resolved\": \"https://registry.npmjs.org/chrome-trace-event/-/chrome-trace-event-1.0.4.tgz\",\n      \"integrity\": \"sha512-rNjApaLzuwaOTjCiT8lSDdGN1APCiqkChLMJxJPWLunPAt5fy8xgU9/jNOchV84wfIxrA0lRQB7oCT8jrn/wrQ==\",\n      \"dev\": true,\n      \"license\": \"MIT\",\n      \"engines\": {\n        \"node\": \">=6.0\"\n      }\n    },\n    \"node_modules/cliui\": {\n      \"version\": \"7.0.4\",\n      \"resolved\": \"https://registry.npmjs.org/cliui/-/cliui-7.0.4.tgz\",\n      \"integrity\": \"sha512-OcRE68cOsVMXp1Yvonl/fzkQOyjLSu/8bhPDfQt0e0/Eb283TKP20Fs2MqoPsr9SwA595rRCA+QMzYc9nBP+JQ==\",\n      \"dev\": true,\n      \"license\": \"ISC\",\n      \"dependencies\": {\n        \"string-width\": \"^4.2.0\",\n        \"strip-ansi\": \"^6.0.0\",\n        \"wrap-ansi\": \"^7.0.0\"\n      }\n    },\n    \"node_modules/clone\": {\n      \"version\": \"2.1.2\",\n      \"resolved\": \"https://registry.npmjs.org/clone/-/clone-2.1.2.tgz\",\n      \"integrity\": \"sha512-3Pe/CF1Nn94hyhIYpjtiLhdCoEoz0DqQ+988E9gmeEdQZlojxnOb74wctFyuwWQHzqyf9X7C7MG8juUpqBJT8w==\",\n      \"dev\": true,\n      \"license\": \"MIT\",\n      \"engines\": {\n        \"node\": \">=0.8\"\n      }\n    },\n    \"node_modules/color-convert\": {\n      \"version\": \"2.0.1\",\n      \"resolved\": \"https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz\",\n      \"integrity\": \"sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==\",\n      \"dev\": true,\n      \"license\": \"MIT\",\n      \"dependencies\": {\n        \"color-name\": \"~1.1.4\"\n      },\n      \"engines\": {\n        \"node\": \">=7.0.0\"\n      }\n    },\n    \"node_modules/color-name\": {\n      \"version\": \"1.1.4\",\n      \"resolved\": \"https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz\",\n      \"integrity\": \"sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==\",\n      \"dev\": true,\n      \"license\": \"MIT\"\n    },\n    \"node_modules/commander\": {\n      \"version\": \"12.1.0\",\n      \"resolved\": \"https://registry.npmjs.org/commander/-/commander-12.1.0.tgz\",\n      \"integrity\": \"sha512-Vw8qHK3bZM9y/P10u3Vib8o/DdkvA2OtPtZvD871QKjy74Wj1WSKFILMPRPSdUSx5RFK1arlJzEtA4PkFgnbuA==\",\n      \"dev\": true,\n      \"license\": \"MIT\",\n      \"engines\": {\n        \"node\": \">=18\"\n      }\n    },\n    \"node_modules/core-js\": {\n      \"version\": \"1.2.7\",\n      \"resolved\": \"https://registry.npmjs.org/core-js/-/core-js-1.2.7.tgz\",\n      \"integrity\": \"sha512-ZiPp9pZlgxpWRu0M+YWbm6+aQ84XEfH1JRXvfOc/fILWI0VKhLC2LX13X1NYq4fULzLMq7Hfh43CSo2/aIaUPA==\",\n      \"deprecated\": \"core-js@<3.23.3 is no longer maintained and not recommended for usage due to the number of issues. Because of the V8 engine whims, feature detection in old core-js versions could cause a slowdown up to 100x even if nothing is polyfilled. Some versions have web compatibility issues. Please, upgrade your dependencies to the actual version of core-js.\",\n      \"license\": \"MIT\"\n    },\n    \"node_modules/create-require\": {\n      \"version\": \"1.1.1\",\n      \"resolved\": \"https://registry.npmjs.org/create-require/-/create-require-1.1.1.tgz\",\n      \"integrity\": \"sha512-dcKFX3jn0MpIaXjisoRvexIJVEKzaq7z2rZKxf+MSr9TkdmHmsU4m2lcLojrj/FHl8mk5VxMmYA+ftRkP/3oKQ==\",\n      \"dev\": true,\n      \"license\": \"MIT\"\n    },\n    \"node_modules/crs_queue\": {\n      \"version\": \"3.2.1\",\n      \"resolved\": \"https://registry.npmjs.org/crs_queue/-/crs_queue-3.2.1.tgz\",\n      \"integrity\": \"sha512-IGhdTEm1G05b904vAdBaBxgQAVPCcecjq9rcBxRcO2cV8E5npw8GvXvqVP5lqHBiyaDGt/70SO5cv5D+KGJATw==\",\n      \"license\": \"MIT-0\"\n    },\n    \"node_modules/csstype\": {\n      \"version\": \"3.2.3\",\n      \"resolved\": \"https://registry.npmjs.org/csstype/-/csstype-3.2.3.tgz\",\n      \"integrity\": \"sha512-z1HGKcYy2xA8AGQfwrn0PAy+PB7X/GSj3UVJW9qKyn43xWa+gl5nXmU4qqLMRzWVLFC8KusUX8T/0kCiOYpAIQ==\",\n      \"license\": \"MIT\"\n    },\n    \"node_modules/debug\": {\n      \"version\": \"4.4.3\",\n      \"resolved\": \"https://registry.npmjs.org/debug/-/debug-4.4.3.tgz\",\n      \"integrity\": \"sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA==\",\n      \"dev\": true,\n      \"license\": \"MIT\",\n      \"dependencies\": {\n        \"ms\": \"^2.1.3\"\n      },\n      \"engines\": {\n        \"node\": \">=6.0\"\n      },\n      \"peerDependenciesMeta\": {\n        \"supports-color\": {\n          \"optional\": true\n        }\n      }\n    },\n    \"node_modules/decamelize\": {\n      \"version\": \"4.0.0\",\n      \"resolved\": \"https://registry.npmjs.org/decamelize/-/decamelize-4.0.0.tgz\",\n      \"integrity\": \"sha512-9iE1PgSik9HeIIw2JO94IidnE3eBoQrFJ3w7sFuzSX4DpmZ3v5sZpUiV5Swcf6mQEF+Y0ru8Neo+p+nyh2J+hQ==\",\n      \"dev\": true,\n      \"license\": \"MIT\",\n      \"engines\": {\n        \"node\": \">=10\"\n      },\n      \"funding\": {\n        \"url\": \"https://github.com/sponsors/sindresorhus\"\n      }\n    },\n    \"node_modules/detect-libc\": {\n      \"version\": \"1.0.3\",\n      \"resolved\": \"https://registry.npmjs.org/detect-libc/-/detect-libc-1.0.3.tgz\",\n      \"integrity\": \"sha512-pGjwhsmsp4kL2RTz08wcOlGN83otlqHeD/Z5T8GXZB+/YcpQ/dgo+lbU8ZsGxV0HIvqqxo9l7mqYwyYMD9bKDg==\",\n      \"dev\": true,\n      \"license\": \"Apache-2.0\",\n      \"bin\": {\n        \"detect-libc\": \"bin/detect-libc.js\"\n      },\n      \"engines\": {\n        \"node\": \">=0.10\"\n      }\n    },\n    \"node_modules/diff\": {\n      \"version\": \"5.2.2\",\n      \"resolved\": \"https://registry.npmjs.org/diff/-/diff-5.2.2.tgz\",\n      \"integrity\": \"sha512-vtcDfH3TOjP8UekytvnHH1o1P4FcUdt4eQ1Y+Abap1tk/OB2MWQvcwS2ClCd1zuIhc3JKOx6p3kod8Vfys3E+A==\",\n      \"dev\": true,\n      \"license\": \"BSD-3-Clause\",\n      \"engines\": {\n        \"node\": \">=0.3.1\"\n      }\n    },\n    \"node_modules/dotenv\": {\n      \"version\": \"16.6.1\",\n      \"resolved\": \"https://registry.npmjs.org/dotenv/-/dotenv-16.6.1.tgz\",\n      \"integrity\": \"sha512-uBq4egWHTcTt33a72vpSG0z3HnPuIl6NqYcTrKEg2azoEyl2hpW0zqlxysq2pK9HlDIHyHyakeYaYnSAwd8bow==\",\n      \"dev\": true,\n      \"license\": \"BSD-2-Clause\",\n      \"engines\": {\n        \"node\": \">=12\"\n      },\n      \"funding\": {\n        \"url\": \"https://dotenvx.com\"\n      }\n    },\n    \"node_modules/dotenv-expand\": {\n      \"version\": \"11.0.7\",\n      \"resolved\": \"https://registry.npmjs.org/dotenv-expand/-/dotenv-expand-11.0.7.tgz\",\n      \"integrity\": \"sha512-zIHwmZPRshsCdpMDyVsqGmgyP0yT8GAgXUnkdAoJisxvf33k7yO6OuoKmcTGuXPWSsm8Oh88nZicRLA9Y0rUeA==\",\n      \"dev\": true,\n      \"license\": \"BSD-2-Clause\",\n      \"dependencies\": {\n        \"dotenv\": \"^16.4.5\"\n      },\n      \"engines\": {\n        \"node\": \">=12\"\n      },\n      \"funding\": {\n        \"url\": \"https://dotenvx.com\"\n      }\n    },\n    \"node_modules/electron-to-chromium\": {\n      \"version\": \"1.5.464\",\n      \"resolved\": \"https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.464.tgz\",\n      \"integrity\": \"sha512-nRa65aFge40viPAKxMKULIY8tcXKwKboJWNn4RoKwyWXJ6SP7BnrDGKUTzc64818jIciH0PK7LSF8QzZes19GA==\",\n      \"dev\": true,\n      \"license\": \"ISC\"\n    },\n    \"node_modules/emoji-regex\": {\n      \"version\": \"8.0.0\",\n      \"resolved\": \"https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz\",\n      \"integrity\": \"sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==\",\n      \"dev\": true,\n      \"license\": \"MIT\"\n    },\n    \"node_modules/encoding\": {\n      \"version\": \"0.1.13\",\n      \"resolved\": \"https://registry.npmjs.org/encoding/-/encoding-0.1.13.tgz\",\n      \"integrity\": \"sha512-ETBauow1T35Y/WZMkio9jiM0Z5xjHHmJ4XmjZOq1l/dXz3lr2sRn87nJy20RupqSh1F2m3HHPSp8ShIPQJrJ3A==\",\n      \"license\": \"MIT\",\n      \"dependencies\": {\n        \"iconv-lite\": \"^0.6.2\"\n      }\n    },\n    \"node_modules/escalade\": {\n      \"version\": \"3.2.0\",\n      \"resolved\": \"https://registry.npmjs.org/escalade/-/escalade-3.2.0.tgz\",\n      \"integrity\": \"sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA==\",\n      \"dev\": true,\n      \"license\": \"MIT\",\n      \"engines\": {\n        \"node\": \">=6\"\n      }\n    },\n    \"node_modules/escape-string-regexp\": {\n      \"version\": \"4.0.0\",\n      \"resolved\": \"https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz\",\n      \"integrity\": \"sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==\",\n      \"dev\": true,\n      \"license\": \"MIT\",\n      \"engines\": {\n        \"node\": \">=10\"\n      },\n      \"funding\": {\n        \"url\": \"https://github.com/sponsors/sindresorhus\"\n      }\n    },\n    \"node_modules/fbjs\": {\n      \"version\": \"0.8.18\",\n      \"resolved\": \"https://registry.npmjs.org/fbjs/-/fbjs-0.8.18.tgz\",\n      \"integrity\": \"sha512-EQaWFK+fEPSoibjNy8IxUtaFOMXcWsY0JaVrQoZR9zC8N2Ygf9iDITPWjUTVIax95b6I742JFLqASHfsag/vKA==\",\n      \"license\": \"MIT\",\n      \"dependencies\": {\n        \"core-js\": \"^1.0.0\",\n        \"isomorphic-fetch\": \"^2.1.1\",\n        \"loose-envify\": \"^1.0.0\",\n        \"object-assign\": \"^4.1.0\",\n        \"promise\": \"^7.1.1\",\n        \"setimmediate\": \"^1.0.5\",\n        \"ua-parser-js\": \"^0.7.30\"\n      }\n    },\n    \"node_modules/fill-range\": {\n      \"version\": \"7.1.1\",\n      \"resolved\": \"https://registry.npmjs.org/fill-range/-/fill-range-7.1.1.tgz\",\n      \"integrity\": \"sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==\",\n      \"dev\": true,\n      \"license\": \"MIT\",\n      \"dependencies\": {\n        \"to-regex-range\": \"^5.0.1\"\n      },\n      \"engines\": {\n        \"node\": \">=8\"\n      }\n    },\n    \"node_modules/find-up\": {\n      \"version\": \"5.0.0\",\n      \"resolved\": \"https://registry.npmjs.org/find-up/-/find-up-5.0.0.tgz\",\n      \"integrity\": \"sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==\",\n      \"dev\": true,\n      \"license\": \"MIT\",\n      \"dependencies\": {\n        \"locate-path\": \"^6.0.0\",\n        \"path-exists\": \"^4.0.0\"\n      },\n      \"engines\": {\n        \"node\": \">=10\"\n      },\n      \"funding\": {\n        \"url\": \"https://github.com/sponsors/sindresorhus\"\n      }\n    },\n    \"node_modules/flat\": {\n      \"version\": \"5.0.2\",\n      \"resolved\": \"https://registry.npmjs.org/flat/-/flat-5.0.2.tgz\",\n      \"integrity\": \"sha512-b6suED+5/3rTpUBdG1gupIl8MPFCAMA0QXwmljLhvCUKcUvdE4gWky9zpuGCcXHOsz4J9wPGNWq6OKpmIzz3hQ==\",\n      \"dev\": true,\n      \"license\": \"BSD-3-Clause\",\n      \"bin\": {\n        \"flat\": \"cli.js\"\n      }\n    },\n    \"node_modules/fs.realpath\": {\n      \"version\": \"1.0.0\",\n      \"resolved\": \"https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz\",\n      \"integrity\": \"sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==\",\n      \"dev\": true,\n      \"license\": \"ISC\"\n    },\n    \"node_modules/fsevents\": {\n      \"version\": \"2.3.3\",\n      \"resolved\": \"https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz\",\n      \"integrity\": \"sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==\",\n      \"dev\": true,\n      \"hasInstallScript\": true,\n      \"license\": \"MIT\",\n      \"optional\": true,\n      \"os\": [\n        \"darwin\"\n      ],\n      \"engines\": {\n        \"node\": \"^8.16.0 || ^10.6.0 || >=11.0.0\"\n      }\n    },\n    \"node_modules/get-caller-file\": {\n      \"version\": \"2.0.5\",\n      \"resolved\": \"https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz\",\n      \"integrity\": \"sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==\",\n      \"dev\": true,\n      \"license\": \"ISC\",\n      \"engines\": {\n        \"node\": \"6.* || 8.* || >= 10.*\"\n      }\n    },\n    \"node_modules/get-port\": {\n      \"version\": \"4.2.0\",\n      \"resolved\": \"https://registry.npmjs.org/get-port/-/get-port-4.2.0.tgz\",\n      \"integrity\": \"sha512-/b3jarXkH8KJoOMQc3uVGHASwGLPq3gSFJ7tgJm2diza+bydJPTGOibin2steecKeOylE8oY2JERlVWkAJO6yw==\",\n      \"dev\": true,\n      \"license\": \"MIT\",\n      \"engines\": {\n        \"node\": \">=6\"\n      }\n    },\n    \"node_modules/glob\": {\n      \"version\": \"8.1.0\",\n      \"resolved\": \"https://registry.npmjs.org/glob/-/glob-8.1.0.tgz\",\n      \"integrity\": \"sha512-r8hpEjiQEYlF2QU0df3dS+nxxSIreXQS1qRhMJM0Q5NDdR386C7jb7Hwwod8Fgiuex+k0GFjgft18yvxm5XoCQ==\",\n      \"deprecated\": \"Old versions of glob are not supported, and contain widely publicized security vulnerabilities, which have been fixed in the current version. Please update. Support for old versions may be purchased (at exorbitant rates) by contacting i@izs.me\",\n      \"dev\": true,\n      \"license\": \"ISC\",\n      \"dependencies\": {\n        \"fs.realpath\": \"^1.0.0\",\n        \"inflight\": \"^1.0.4\",\n        \"inherits\": \"2\",\n        \"minimatch\": \"^5.0.1\",\n        \"once\": \"^1.3.0\"\n      },\n      \"engines\": {\n        \"node\": \">=12\"\n      },\n      \"funding\": {\n        \"url\": \"https://github.com/sponsors/isaacs\"\n      }\n    },\n    \"node_modules/glob-parent\": {\n      \"version\": \"5.1.2\",\n      \"resolved\": \"https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz\",\n      \"integrity\": \"sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==\",\n      \"dev\": true,\n      \"license\": \"ISC\",\n      \"dependencies\": {\n        \"is-glob\": \"^4.0.1\"\n      },\n      \"engines\": {\n        \"node\": \">= 6\"\n      }\n    },\n    \"node_modules/globals\": {\n      \"version\": \"13.24.0\",\n      \"resolved\": \"https://registry.npmjs.org/globals/-/globals-13.24.0.tgz\",\n      \"integrity\": \"sha512-AhO5QUcj8llrbG09iWhPU2B204J1xnPeL8kQmVorSsy+Sjj1sk8gIyh6cUocGmH4L0UuhAJy+hJMRA4mgA4mFQ==\",\n      \"dev\": true,\n      \"license\": \"MIT\",\n      \"dependencies\": {\n        \"type-fest\": \"^0.20.2\"\n      },\n      \"engines\": {\n        \"node\": \">=8\"\n      },\n      \"funding\": {\n        \"url\": \"https://github.com/sponsors/sindresorhus\"\n      }\n    },\n    \"node_modules/has-flag\": {\n      \"version\": \"4.0.0\",\n      \"resolved\": \"https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz\",\n      \"integrity\": \"sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==\",\n      \"dev\": true,\n      \"license\": \"MIT\",\n      \"engines\": {\n        \"node\": \">=8\"\n      }\n    },\n    \"node_modules/he\": {\n      \"version\": \"1.2.0\",\n      \"resolved\": \"https://registry.npmjs.org/he/-/he-1.2.0.tgz\",\n      \"integrity\": \"sha512-F/1DnUGPopORZi0ni+CvrCgHQ5FyEAHRLSApuYWMmrbSwoN2Mn/7k+Gl38gJnR7yyDZk6WLXwiGod1JOWNDKGw==\",\n      \"dev\": true,\n      \"license\": \"MIT\",\n      \"bin\": {\n        \"he\": \"bin/he\"\n      }\n    },\n    \"node_modules/hoist-non-react-statics\": {\n      \"version\": \"3.3.2\",\n      \"resolved\": \"https://registry.npmjs.org/hoist-non-react-statics/-/hoist-non-react-statics-3.3.2.tgz\",\n      \"integrity\": \"sha512-/gGivxi8JPKWNm/W0jSmzcMPpfpPLc3dY/6GxhX2hQ9iGj3aDfklV4ET7NjKpSinLpJ5vafa9iiGIEZg10SfBw==\",\n      \"license\": \"BSD-3-Clause\",\n      \"dependencies\": {\n        \"react-is\": \"^16.7.0\"\n      }\n    },\n    \"node_modules/iconv-lite\": {\n      \"version\": \"0.6.3\",\n      \"resolved\": \"https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.6.3.tgz\",\n      \"integrity\": \"sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw==\",\n      \"license\": \"MIT\",\n      \"dependencies\": {\n        \"safer-buffer\": \">= 2.1.2 < 3.0.0\"\n      },\n      \"engines\": {\n        \"node\": \">=0.10.0\"\n      }\n    },\n    \"node_modules/inflight\": {\n      \"version\": \"1.0.6\",\n      \"resolved\": \"https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz\",\n      \"integrity\": \"sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==\",\n      \"deprecated\": \"This module is not supported, and leaks memory. Do not use it. Check out lru-cache if you want a good and tested way to coalesce async requests by a key value, which is much more comprehensive and powerful.\",\n      \"dev\": true,\n      \"license\": \"ISC\",\n      \"dependencies\": {\n        \"once\": \"^1.3.0\",\n        \"wrappy\": \"1\"\n      }\n    },\n    \"node_modules/inherits\": {\n      \"version\": \"2.0.4\",\n      \"resolved\": \"https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz\",\n      \"integrity\": \"sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==\",\n      \"dev\": true,\n      \"license\": \"ISC\"\n    },\n    \"node_modules/intl-messageformat\": {\n      \"version\": \"10.7.7\",\n      \"resolved\": \"https://registry.npmjs.org/intl-messageformat/-/intl-messageformat-10.7.7.tgz\",\n      \"integrity\": \"sha512-F134jIoeYMro/3I0h08D0Yt4N9o9pjddU/4IIxMMURqbAtI2wu70X8hvG1V48W49zXHXv3RKSF/po+0fDfsGjA==\",\n      \"license\": \"BSD-3-Clause\",\n      \"dependencies\": {\n        \"@formatjs/ecma402-abstract\": \"2.2.4\",\n        \"@formatjs/fast-memoize\": \"2.2.3\",\n        \"@formatjs/icu-messageformat-parser\": \"2.9.4\",\n        \"tslib\": \"2\"\n      }\n    },\n    \"node_modules/is-binary-path\": {\n      \"version\": \"2.1.0\",\n      \"resolved\": \"https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz\",\n      \"integrity\": \"sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==\",\n      \"dev\": true,\n      \"license\": \"MIT\",\n      \"dependencies\": {\n        \"binary-extensions\": \"^2.0.0\"\n      },\n      \"engines\": {\n        \"node\": \">=8\"\n      }\n    },\n    \"node_modules/is-extglob\": {\n      \"version\": \"2.1.1\",\n      \"resolved\": \"https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz\",\n      \"integrity\": \"sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==\",\n      \"dev\": true,\n      \"license\": \"MIT\",\n      \"engines\": {\n        \"node\": \">=0.10.0\"\n      }\n    },\n    \"node_modules/is-fullwidth-code-point\": {\n      \"version\": \"3.0.0\",\n      \"resolved\": \"https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz\",\n      \"integrity\": \"sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==\",\n      \"dev\": true,\n      \"license\": \"MIT\",\n      \"engines\": {\n        \"node\": \">=8\"\n      }\n    },\n    \"node_modules/is-glob\": {\n      \"version\": \"4.0.3\",\n      \"resolved\": \"https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz\",\n      \"integrity\": \"sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==\",\n      \"dev\": true,\n      \"license\": \"MIT\",\n      \"dependencies\": {\n        \"is-extglob\": \"^2.1.1\"\n      },\n      \"engines\": {\n        \"node\": \">=0.10.0\"\n      }\n    },\n    \"node_modules/is-number\": {\n      \"version\": \"7.0.0\",\n      \"resolved\": \"https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz\",\n      \"integrity\": \"sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==\",\n      \"dev\": true,\n      \"license\": \"MIT\",\n      \"engines\": {\n        \"node\": \">=0.12.0\"\n      }\n    },\n    \"node_modules/is-plain-obj\": {\n      \"version\": \"2.1.0\",\n      \"resolved\": \"https://registry.npmjs.org/is-plain-obj/-/is-plain-obj-2.1.0.tgz\",\n      \"integrity\": \"sha512-YWnfyRwxL/+SsrWYfOpUtz5b3YD+nyfkHvjbcanzk8zgyO4ASD67uVMRt8k5bM4lLMDnXfriRhOpemw+NfT1eA==\",\n      \"dev\": true,\n      \"license\": \"MIT\",\n      \"engines\": {\n        \"node\": \">=8\"\n      }\n    },\n    \"node_modules/is-stream\": {\n      \"version\": \"1.1.0\",\n      \"resolved\": \"https://registry.npmjs.org/is-stream/-/is-stream-1.1.0.tgz\",\n      \"integrity\": \"sha512-uQPm8kcs47jx38atAcWTVxyltQYoPT68y9aWYdV6yWXSyW8mzSat0TL6CiWdZeCdF3KrAvpVtnHbTv4RN+rqdQ==\",\n      \"license\": \"MIT\",\n      \"engines\": {\n        \"node\": \">=0.10.0\"\n      }\n    },\n    \"node_modules/is-unicode-supported\": {\n      \"version\": \"0.1.0\",\n      \"resolved\": \"https://registry.npmjs.org/is-unicode-supported/-/is-unicode-supported-0.1.0.tgz\",\n      \"integrity\": \"sha512-knxG2q4UC3u8stRGyAVJCOdxFmv5DZiRcdlIaAQXAbSfJya+OhopNotLQrstBhququ4ZpuKbDc/8S6mgXgPFPw==\",\n      \"dev\": true,\n      \"license\": \"MIT\",\n      \"engines\": {\n        \"node\": \">=10\"\n      },\n      \"funding\": {\n        \"url\": \"https://github.com/sponsors/sindresorhus\"\n      }\n    },\n    \"node_modules/isomorphic-fetch\": {\n      \"version\": \"2.2.1\",\n      \"resolved\": \"https://registry.npmjs.org/isomorphic-fetch/-/isomorphic-fetch-2.2.1.tgz\",\n      \"integrity\": \"sha512-9c4TNAKYXM5PRyVcwUZrF3W09nQ+sO7+jydgs4ZGW9dhsLG2VOlISJABombdQqQRXCwuYG3sYV/puGf5rp0qmA==\",\n      \"license\": \"MIT\",\n      \"dependencies\": {\n        \"node-fetch\": \"^1.0.1\",\n        \"whatwg-fetch\": \">=0.10.0\"\n      }\n    },\n    \"node_modules/js-tokens\": {\n      \"version\": \"4.0.0\",\n      \"resolved\": \"https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz\",\n      \"integrity\": \"sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==\",\n      \"license\": \"MIT\"\n    },\n    \"node_modules/js-yaml\": {\n      \"version\": \"4.3.2\",\n      \"resolved\": \"https://registry.npmjs.org/js-yaml/-/js-yaml-4.3.2.tgz\",\n      \"integrity\": \"sha512-SFNOvSJ+Dgf/9An904Yx+CgSlIPCkIpao4qo51lpee25TIRejdH3rhR4EZMGoNx3/TP3O+wzWuiTFl4sqbltzA==\",\n      \"dev\": true,\n      \"funding\": [\n        {\n          \"type\": \"github\",\n          \"url\": \"https://github.com/sponsors/puzrin\"\n        },\n        {\n          \"type\": \"github\",\n          \"url\": \"https://github.com/sponsors/nodeca\"\n        }\n      ],\n      \"license\": \"MIT\",\n      \"dependencies\": {\n        \"argparse\": \"^2.0.1\"\n      },\n      \"bin\": {\n        \"js-yaml\": \"bin/js-yaml.js\"\n      }\n    },\n    \"node_modules/json5\": {\n      \"version\": \"2.2.3\",\n      \"resolved\": \"https://registry.npmjs.org/json5/-/json5-2.2.3.tgz\",\n      \"integrity\": \"sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg==\",\n      \"dev\": true,\n      \"license\": \"MIT\",\n      \"bin\": {\n        \"json5\": \"lib/cli.js\"\n      },\n      \"engines\": {\n        \"node\": \">=6\"\n      }\n    },\n    \"node_modules/lightningcss\": {\n      \"version\": \"1.33.0\",\n      \"resolved\": \"https://registry.npmjs.org/lightningcss/-/lightningcss-1.33.0.tgz\",\n      \"integrity\": \"sha512-WkUDrojuJs0xkgGf2udWxa3yGBRxPtxUkB79i6aCZLRgc7PM8fZe9TosfPDcvEpQZbuFASnHYmRLBLUbmLOIIA==\",\n      \"dev\": true,\n      \"license\": \"MPL-2.0\",\n      \"dependencies\": {\n        \"detect-libc\": \"^2.0.3\"\n      },\n      \"engines\": {\n        \"node\": \">= 12.0.0\"\n      },\n      \"funding\": {\n        \"type\": \"opencollective\",\n        \"url\": \"https://opencollective.com/parcel\"\n      },\n      \"optionalDependencies\": {\n        \"lightningcss-android-arm64\": \"1.33.0\",\n        \"lightningcss-darwin-arm64\": \"1.33.0\",\n        \"lightningcss-darwin-x64\": \"1.33.0\",\n        \"lightningcss-freebsd-x64\": \"1.33.0\",\n        \"lightningcss-linux-arm-gnueabihf\": \"1.33.0\",\n        \"lightningcss-linux-arm64-gnu\": \"1.33.0\",\n        \"lightningcss-linux-arm64-musl\": \"1.33.0\",\n        \"lightningcss-linux-x64-gnu\": \"1.33.0\",\n        \"lightningcss-linux-x64-musl\": \"1.33.0\",\n        \"lightningcss-win32-arm64-msvc\": \"1.33.0\",\n        \"lightningcss-win32-x64-msvc\": \"1.33.0\"\n      }\n    },\n    \"node_modules/lightningcss-android-arm64\": {\n      \"version\": \"1.33.0\",\n      \"resolved\": \"https://registry.npmjs.org/lightningcss-android-arm64/-/lightningcss-android-arm64-1.33.0.tgz\",\n      \"integrity\": \"sha512-gEpRTalKdosp4Bb8qWtc2iOgE5SeIHlpS1up9bFq2wAyYhl1UdTObYiHe98zEM9SQvSoqQZ1IQD0JNpg3Ml5pg==\",\n      \"cpu\": [\n        \"arm64\"\n      ],\n      \"dev\": true,\n      \"license\": \"MPL-2.0\",\n      \"optional\": true,\n      \"os\": [\n        \"android\"\n      ],\n      \"engines\": {\n        \"node\": \">= 12.0.0\"\n      },\n      \"funding\": {\n        \"type\": \"opencollective\",\n        \"url\": \"https://opencollective.com/parcel\"\n      }\n    },\n    \"node_modules/lightningcss-darwin-arm64\": {\n      \"version\": \"1.33.0\",\n      \"resolved\": \"https://registry.npmjs.org/lightningcss-darwin-arm64/-/lightningcss-darwin-arm64-1.33.0.tgz\",\n      \"integrity\": \"sha512-Sciaz8eenNTKn9b3t7+xr0ipTp9YxKQY4npwQ3mrRuL0BAVHBLyZxofhaKBAVtzmtRZ/zTyo0/to4B1uWG/Djg==\",\n      \"cpu\": [\n        \"arm64\"\n      ],\n      \"dev\": true,\n      \"license\": \"MPL-2.0\",\n      \"optional\": true,\n      \"os\": [\n        \"darwin\"\n      ],\n      \"engines\": {\n        \"node\": \">= 12.0.0\"\n      },\n      \"funding\": {\n        \"type\": \"opencollective\",\n        \"url\": \"https://opencollective.com/parcel\"\n      }\n    },\n    \"node_modules/lightningcss-darwin-x64\": {\n      \"version\": \"1.33.0\",\n      \"resolved\": \"https://registry.npmjs.org/lightningcss-darwin-x64/-/lightningcss-darwin-x64-1.33.0.tgz\",\n      \"integrity\": \"sha512-Z5UPAxzrjlWNNyGy6i65cJzzvgJ5D3T6wMvs+gWpY9d7qRhANrxqAp6LhxIgZhWEw18RfJTGcRxjuLIBr+m8XQ==\",\n      \"cpu\": [\n        \"x64\"\n      ],\n      \"dev\": true,\n      \"license\": \"MPL-2.0\",\n      \"optional\": true,\n      \"os\": [\n        \"darwin\"\n      ],\n      \"engines\": {\n        \"node\": \">= 12.0.0\"\n      },\n      \"funding\": {\n        \"type\": \"opencollective\",\n        \"url\": \"https://opencollective.com/parcel\"\n      }\n    },\n    \"node_modules/lightningcss-freebsd-x64\": {\n      \"version\": \"1.33.0\",\n      \"resolved\": \"https://registry.npmjs.org/lightningcss-freebsd-x64/-/lightningcss-freebsd-x64-1.33.0.tgz\",\n      \"integrity\": \"sha512-QQM/Ti/hQajJwCY+RiWuCZ9sdtI/XQk7nDK5vC8kkdwixezOlDgvDx7+RT+QjK6FcFT4MpsuoBnHIo/O3StRRg==\",\n      \"cpu\": [\n        \"x64\"\n      ],\n      \"dev\": true,\n      \"license\": \"MPL-2.0\",\n      \"optional\": true,\n      \"os\": [\n        \"freebsd\"\n      ],\n      \"engines\": {\n        \"node\": \">= 12.0.0\"\n      },\n      \"funding\": {\n        \"type\": \"opencollective\",\n        \"url\": \"https://opencollective.com/parcel\"\n      }\n    },\n    \"node_modules/lightningcss-linux-arm-gnueabihf\": {\n      \"version\": \"1.33.0\",\n      \"resolved\": \"https://registry.npmjs.org/lightningcss-linux-arm-gnueabihf/-/lightningcss-linux-arm-gnueabihf-1.33.0.tgz\",\n      \"integrity\": \"sha512-N7FVBe6iS24MlM6R/4RBTxGhQheZGs7tiQ9U32UtF75NzP5Q7xWPRqLBCKxlRQRk3rY1jCIPLzx7WzOhuUIRLQ==\",\n      \"cpu\": [\n        \"arm\"\n      ],\n      \"dev\": true,\n      \"license\": \"MPL-2.0\",\n      \"optional\": true,\n      \"os\": [\n        \"linux\"\n      ],\n      \"engines\": {\n        \"node\": \">= 12.0.0\"\n      },\n      \"funding\": {\n        \"type\": \"opencollective\",\n        \"url\": \"https://opencollective.com/parcel\"\n      }\n    },\n    \"node_modules/lightningcss-linux-arm64-gnu\": {\n      \"version\": \"1.33.0\",\n      \"resolved\": \"https://registry.npmjs.org/lightningcss-linux-arm64-gnu/-/lightningcss-linux-arm64-gnu-1.33.0.tgz\",\n      \"integrity\": \"sha512-j2v/itmy4HlNxlc6voKXYgBqNi0Ng2LShg4z7GufpEgs05P+2suBVyi9I6YHq5uoVFx9ETin3eCEhLVyXGQnKg==\",\n      \"cpu\": [\n        \"arm64\"\n      ],\n      \"dev\": true,\n      \"license\": \"MPL-2.0\",\n      \"optional\": true,\n      \"os\": [\n        \"linux\"\n      ],\n      \"engines\": {\n        \"node\": \">= 12.0.0\"\n      },\n      \"funding\": {\n        \"type\": \"opencollective\",\n        \"url\": \"https://opencollective.com/parcel\"\n      }\n    },\n    \"node_modules/lightningcss-linux-arm64-musl\": {\n      \"version\": \"1.33.0\",\n      \"resolved\": \"https://registry.npmjs.org/lightningcss-linux-arm64-musl/-/lightningcss-linux-arm64-musl-1.33.0.tgz\",\n      \"integrity\": \"sha512-yiO5ROMuYQgXbC60yjZU5CYSFZGKXL0HFATXt9mHJn1+zW55oCtMI9NfcVhYLMFDL7gV7oBPon/EmMMGg2OvtQ==\",\n      \"cpu\": [\n        \"arm64\"\n      ],\n      \"dev\": true,\n      \"license\": \"MPL-2.0\",\n      \"optional\": true,\n      \"os\": [\n        \"linux\"\n      ],\n      \"engines\": {\n        \"node\": \">= 12.0.0\"\n      },\n      \"funding\": {\n        \"type\": \"opencollective\",\n        \"url\": \"https://opencollective.com/parcel\"\n      }\n    },\n    \"node_modules/lightningcss-linux-x64-gnu\": {\n      \"version\": \"1.33.0\",\n      \"resolved\": \"https://registry.npmjs.org/lightningcss-linux-x64-gnu/-/lightningcss-linux-x64-gnu-1.33.0.tgz\",\n      \"integrity\": \"sha512-ar+Ju7LmcN0Jo4FpL4hpFybwNG9/3A/Br5KW2n2jyODg3MEZXaDYADdemoNS+BDNfMgKvylJLj4S5tyRActuAg==\",\n      \"cpu\": [\n        \"x64\"\n      ],\n      \"dev\": true,\n      \"license\": \"MPL-2.0\",\n      \"optional\": true,\n      \"os\": [\n        \"linux\"\n      ],\n      \"engines\": {\n        \"node\": \">= 12.0.0\"\n      },\n      \"funding\": {\n        \"type\": \"opencollective\",\n        \"url\": \"https://opencollective.com/parcel\"\n      }\n    },\n    \"node_modules/lightningcss-linux-x64-musl\": {\n      \"version\": \"1.33.0\",\n      \"resolved\": \"https://registry.npmjs.org/lightningcss-linux-x64-musl/-/lightningcss-linux-x64-musl-1.33.0.tgz\",\n      \"integrity\": \"sha512-RYiYbkokw0trfKqqzfF55lginwEPrD3OJDfTuJzFs1MK6iFnDenaz1fqLLtX4ITG3OktJQXOeTaw1awrBAlZPw==\",\n      \"cpu\": [\n        \"x64\"\n      ],\n      \"dev\": true,\n      \"license\": \"MPL-2.0\",\n      \"optional\": true,\n      \"os\": [\n        \"linux\"\n      ],\n      \"engines\": {\n        \"node\": \">= 12.0.0\"\n      },\n      \"funding\": {\n        \"type\": \"opencollective\",\n        \"url\": \"https://opencollective.com/parcel\"\n      }\n    },\n    \"node_modules/lightningcss-win32-arm64-msvc\": {\n      \"version\": \"1.33.0\",\n      \"resolved\": \"https://registry.npmjs.org/lightningcss-win32-arm64-msvc/-/lightningcss-win32-arm64-msvc-1.33.0.tgz\",\n      \"integrity\": \"sha512-1K+MPfLSFVpphzpdbfkhlWk6wBrTObBzS2T6db10PNOZgR9GoVsAWzwNyuhUYYbTp23j+4RrncfujZ4uAzXvwA==\",\n      \"cpu\": [\n        \"arm64\"\n      ],\n      \"dev\": true,\n      \"license\": \"MPL-2.0\",\n      \"optional\": true,\n      \"os\": [\n        \"win32\"\n      ],\n      \"engines\": {\n        \"node\": \">= 12.0.0\"\n      },\n      \"funding\": {\n        \"type\": \"opencollective\",\n        \"url\": \"https://opencollective.com/parcel\"\n      }\n    },\n    \"node_modules/lightningcss-win32-x64-msvc\": {\n      \"version\": \"1.33.0\",\n      \"resolved\": \"https://registry.npmjs.org/lightningcss-win32-x64-msvc/-/lightningcss-win32-x64-msvc-1.33.0.tgz\",\n      \"integrity\": \"sha512-OlEICDx/Xl0FqSp4bry8zFnCvGpig3Gl4gCquvYwHuqJKEC1+n9NgDniFvqHGmMv1ZkqDJrDqKKSykTDX+ehuA==\",\n      \"cpu\": [\n        \"x64\"\n      ],\n      \"dev\": true,\n      \"license\": \"MPL-2.0\",\n      \"optional\": true,\n      \"os\": [\n        \"win32\"\n      ],\n      \"engines\": {\n        \"node\": \">= 12.0.0\"\n      },\n      \"funding\": {\n        \"type\": \"opencollective\",\n        \"url\": \"https://opencollective.com/parcel\"\n      }\n    },\n    \"node_modules/lightningcss/node_modules/detect-libc\": {\n      \"version\": \"2.1.2\",\n      \"resolved\": \"https://registry.npmjs.org/detect-libc/-/detect-libc-2.1.2.tgz\",\n      \"integrity\": \"sha512-Btj2BOOO83o3WyH59e8MgXsxEQVcarkUOpEYrubB0urwnN10yQ364rsiByU11nZlqWYZm05i/of7io4mzihBtQ==\",\n      \"dev\": true,\n      \"license\": \"Apache-2.0\",\n      \"engines\": {\n        \"node\": \">=8\"\n      }\n    },\n    \"node_modules/lmdb\": {\n      \"version\": \"2.8.5\",\n      \"resolved\": \"https://registry.npmjs.org/lmdb/-/lmdb-2.8.5.tgz\",\n      \"integrity\": \"sha512-9bMdFfc80S+vSldBmG3HOuLVHnxRdNTlpzR6QDnzqCQtCzGUEAGTzBKYMeIM+I/sU4oZfgbcbS7X7F65/z/oxQ==\",\n      \"dev\": true,\n      \"hasInstallScript\": true,\n      \"license\": \"MIT\",\n      \"dependencies\": {\n        \"msgpackr\": \"^1.9.5\",\n        \"node-addon-api\": \"^6.1.0\",\n        \"node-gyp-build-optional-packages\": \"5.1.1\",\n        \"ordered-binary\": \"^1.4.1\",\n        \"weak-lru-cache\": \"^1.2.2\"\n      },\n      \"bin\": {\n        \"download-lmdb-prebuilds\": \"bin/download-prebuilds.js\"\n      },\n      \"optionalDependencies\": {\n        \"@lmdb/lmdb-darwin-arm64\": \"2.8.5\",\n        \"@lmdb/lmdb-darwin-x64\": \"2.8.5\",\n        \"@lmdb/lmdb-linux-arm\": \"2.8.5\",\n        \"@lmdb/lmdb-linux-arm64\": \"2.8.5\",\n        \"@lmdb/lmdb-linux-x64\": \"2.8.5\",\n        \"@lmdb/lmdb-win32-x64\": \"2.8.5\"\n      }\n    },\n    \"node_modules/lmdb/node_modules/node-addon-api\": {\n      \"version\": \"6.1.0\",\n      \"resolved\": \"https://registry.npmjs.org/node-addon-api/-/node-addon-api-6.1.0.tgz\",\n      \"integrity\": \"sha512-+eawOlIgy680F0kBzPUNFhMZGtJ1YmqM6l4+Crf4IkImjYrO/mqPwRMh352g23uIaQKFItcQ64I7KMaJxHgAVA==\",\n      \"dev\": true,\n      \"license\": \"MIT\"\n    },\n    \"node_modules/locate-path\": {\n      \"version\": \"6.0.0\",\n      \"resolved\": \"https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz\",\n      \"integrity\": \"sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==\",\n      \"dev\": true,\n      \"license\": \"MIT\",\n      \"dependencies\": {\n        \"p-locate\": \"^5.0.0\"\n      },\n      \"engines\": {\n        \"node\": \">=10\"\n      },\n      \"funding\": {\n        \"url\": \"https://github.com/sponsors/sindresorhus\"\n      }\n    },\n    \"node_modules/log-symbols\": {\n      \"version\": \"4.1.0\",\n      \"resolved\": \"https://registry.npmjs.org/log-symbols/-/log-symbols-4.1.0.tgz\",\n      \"integrity\": \"sha512-8XPvpAA8uyhfteu8pIvQxpJZ7SYYdpUivZpGy6sFsBuKRY/7rQGavedeB8aK+Zkyq6upMFVL/9AW6vOYzfRyLg==\",\n      \"dev\": true,\n      \"license\": \"MIT\",\n      \"dependencies\": {\n        \"chalk\": \"^4.1.0\",\n        \"is-unicode-supported\": \"^0.1.0\"\n      },\n      \"engines\": {\n        \"node\": \">=10\"\n      },\n      \"funding\": {\n        \"url\": \"https://github.com/sponsors/sindresorhus\"\n      }\n    },\n    \"node_modules/loose-envify\": {\n      \"version\": \"1.4.0\",\n      \"resolved\": \"https://registry.npmjs.org/loose-envify/-/loose-envify-1.4.0.tgz\",\n      \"integrity\": \"sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q==\",\n      \"license\": \"MIT\",\n      \"dependencies\": {\n        \"js-tokens\": \"^3.0.0 || ^4.0.0\"\n      },\n      \"bin\": {\n        \"loose-envify\": \"cli.js\"\n      }\n    },\n    \"node_modules/lz-string\": {\n      \"version\": \"1.5.0\",\n      \"resolved\": \"https://registry.npmjs.org/lz-string/-/lz-string-1.5.0.tgz\",\n      \"integrity\": \"sha512-h5bgJWpxJNswbU7qCrV0tIKQCaS3blPDrqKWx+QxzuzL1zGUzij9XCWLrSLsJPu5t+eWA/ycetzYAO5IOMcWAQ==\",\n      \"license\": \"MIT\",\n      \"bin\": {\n        \"lz-string\": \"bin/bin.js\"\n      }\n    },\n    \"node_modules/make-error\": {\n      \"version\": \"1.3.6\",\n      \"resolved\": \"https://registry.npmjs.org/make-error/-/make-error-1.3.6.tgz\",\n      \"integrity\": \"sha512-s8UhlNe7vPKomQhC1qFelMokr/Sc3AgNbso3n74mVPA5LTZwkB9NlXf4XPamLxJE8h0gh73rM94xvwRT2CVInw==\",\n      \"dev\": true,\n      \"license\": \"ISC\"\n    },\n    \"node_modules/marked\": {\n      \"version\": \"4.3.0\",\n      \"resolved\": \"https://registry.npmjs.org/marked/-/marked-4.3.0.tgz\",\n      \"integrity\": \"sha512-PRsaiG84bK+AMvxziE/lCFss8juXjNaWzVbN5tXAm4XjeaS9NAHhop+PjQxz2A9h8Q4M/xGmzP8vqNwy6JeK0A==\",\n      \"dev\": true,\n      \"license\": \"MIT\",\n      \"bin\": {\n        \"marked\": \"bin/marked.js\"\n      },\n      \"engines\": {\n        \"node\": \">= 12\"\n      }\n    },\n    \"node_modules/md2jsx\": {\n      \"version\": \"1.1.0\",\n      \"resolved\": \"https://registry.npmjs.org/md2jsx/-/md2jsx-1.1.0.tgz\",\n      \"integrity\": \"sha512-eKQp7nIoX/8Wq0ND+wOT/zY5Ay97kwJAqbwVBqLufbogq53ViKVya75NqtOiYXfSaWH+wFiml0CCO6l5txpV9A==\",\n      \"dev\": true,\n      \"license\": \"MIT\",\n      \"dependencies\": {\n        \"@types/marked\": \"^4.0.7\",\n        \"marked\": \"^4.1.1\"\n      },\n      \"bin\": {\n        \"md2jsx\": \"dist/cmd.js\"\n      }\n    },\n    \"node_modules/minimatch\": {\n      \"version\": \"5.1.9\",\n      \"resolved\": \"https://registry.npmjs.org/minimatch/-/minimatch-5.1.9.tgz\",\n      \"integrity\": \"sha512-7o1wEA2RyMP7Iu7GNba9vc0RWWGACJOCZBJX2GJWip0ikV+wcOsgVuY9uE8CPiyQhkGFSlhuSkZPavN7u1c2Fw==\",\n      \"dev\": true,\n      \"license\": \"ISC\",\n      \"dependencies\": {\n        \"brace-expansion\": \"^2.0.1\"\n      },\n      \"engines\": {\n        \"node\": \">=10\"\n      }\n    },\n    \"node_modules/mocha\": {\n      \"version\": \"10.8.2\",\n      \"resolved\": \"https://registry.npmjs.org/mocha/-/mocha-10.8.2.tgz\",\n      \"integrity\": \"sha512-VZlYo/WE8t1tstuRmqgeyBgCbJc/lEdopaa+axcKzTBJ+UIdlAB9XnmvTCAH4pwR4ElNInaedhEBmZD8iCSVEg==\",\n      \"dev\": true,\n      \"license\": \"MIT\",\n      \"dependencies\": {\n        \"ansi-colors\": \"^4.1.3\",\n        \"browser-stdout\": \"^1.3.1\",\n        \"chokidar\": \"^3.5.3\",\n        \"debug\": \"^4.3.5\",\n        \"diff\": \"^5.2.0\",\n        \"escape-string-regexp\": \"^4.0.0\",\n        \"find-up\": \"^5.0.0\",\n        \"glob\": \"^8.1.0\",\n        \"he\": \"^1.2.0\",\n        \"js-yaml\": \"^4.1.0\",\n        \"log-symbols\": \"^4.1.0\",\n        \"minimatch\": \"^5.1.6\",\n        \"ms\": \"^2.1.3\",\n        \"serialize-javascript\": \"^6.0.2\",\n        \"strip-json-comments\": \"^3.1.1\",\n        \"supports-color\": \"^8.1.1\",\n        \"workerpool\": \"^6.5.1\",\n        \"yargs\": \"^16.2.0\",\n        \"yargs-parser\": \"^20.2.9\",\n        \"yargs-unparser\": \"^2.0.0\"\n      },\n      \"bin\": {\n        \"_mocha\": \"bin/_mocha\",\n        \"mocha\": \"bin/mocha.js\"\n      },\n      \"engines\": {\n        \"node\": \">= 14.0.0\"\n      }\n    },\n    \"node_modules/ms\": {\n      \"version\": \"2.1.3\",\n      \"resolved\": \"https://registry.npmjs.org/ms/-/ms-2.1.3.tgz\",\n      \"integrity\": \"sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==\",\n      \"dev\": true,\n      \"license\": \"MIT\"\n    },\n    \"node_modules/msgpackr\": {\n      \"version\": \"1.12.1\",\n      \"resolved\": \"https://registry.npmjs.org/msgpackr/-/msgpackr-1.12.1.tgz\",\n      \"integrity\": \"sha512-4EUH9tQHnMmEgzW/MdAP0KIfa1T9AF+htl0ffe2n5vb2EKn9y2co8ccpgWko6S52Jy1PQZKwRnx5/KkYjtd9MQ==\",\n      \"dev\": true,\n      \"license\": \"MIT\",\n      \"optionalDependencies\": {\n        \"msgpackr-extract\": \"^3.0.2\"\n      }\n    },\n    \"node_modules/msgpackr-extract\": {\n      \"version\": \"3.0.4\",\n      \"resolved\": \"https://registry.npmjs.org/msgpackr-extract/-/msgpackr-extract-3.0.4.tgz\",\n      \"integrity\": \"sha512-4kmO/MdyUIkLIvTPr8VHLil4AtoKIoniWPIEk5+CDy0xnWC84azhSFmuJ7PxZdsYtiP5kEeQsORAVIeMgxT+Hw==\",\n      \"dev\": true,\n      \"hasInstallScript\": true,\n      \"license\": \"MIT\",\n      \"optional\": true,\n      \"dependencies\": {\n        \"node-gyp-build-optional-packages\": \"5.2.2\"\n      },\n      \"bin\": {\n        \"download-msgpackr-prebuilds\": \"bin/download-prebuilds.js\"\n      },\n      \"optionalDependencies\": {\n        \"@msgpackr-extract/msgpackr-extract-darwin-arm64\": \"3.0.4\",\n        \"@msgpackr-extract/msgpackr-extract-darwin-x64\": \"3.0.4\",\n        \"@msgpackr-extract/msgpackr-extract-linux-arm\": \"3.0.4\",\n        \"@msgpackr-extract/msgpackr-extract-linux-arm64\": \"3.0.4\",\n        \"@msgpackr-extract/msgpackr-extract-linux-x64\": \"3.0.4\",\n        \"@msgpackr-extract/msgpackr-extract-win32-x64\": \"3.0.4\"\n      }\n    },\n    \"node_modules/msgpackr-extract/node_modules/detect-libc\": {\n      \"version\": \"2.1.2\",\n      \"resolved\": \"https://registry.npmjs.org/detect-libc/-/detect-libc-2.1.2.tgz\",\n      \"integrity\": \"sha512-Btj2BOOO83o3WyH59e8MgXsxEQVcarkUOpEYrubB0urwnN10yQ364rsiByU11nZlqWYZm05i/of7io4mzihBtQ==\",\n      \"dev\": true,\n      \"license\": \"Apache-2.0\",\n      \"optional\": true,\n      \"engines\": {\n        \"node\": \">=8\"\n      }\n    },\n    \"node_modules/msgpackr-extract/node_modules/node-gyp-build-optional-packages\": {\n      \"version\": \"5.2.2\",\n      \"resolved\": \"https://registry.npmjs.org/node-gyp-build-optional-packages/-/node-gyp-build-optional-packages-5.2.2.tgz\",\n      \"integrity\": \"sha512-s+w+rBWnpTMwSFbaE0UXsRlg7hU4FjekKU4eyAih5T8nJuNZT1nNsskXpxmeqSK9UzkBl6UgRlnKc8hz8IEqOw==\",\n      \"dev\": true,\n      \"license\": \"MIT\",\n      \"optional\": true,\n      \"dependencies\": {\n        \"detect-libc\": \"^2.0.1\"\n      },\n      \"bin\": {\n        \"node-gyp-build-optional-packages\": \"bin.js\",\n        \"node-gyp-build-optional-packages-optional\": \"optional.js\",\n        \"node-gyp-build-optional-packages-test\": \"build-test.js\"\n      }\n    },\n    \"node_modules/node-addon-api\": {\n      \"version\": \"7.1.1\",\n      \"resolved\": \"https://registry.npmjs.org/node-addon-api/-/node-addon-api-7.1.1.tgz\",\n      \"integrity\": \"sha512-5m3bsyrjFWE1xf7nz7YXdN4udnVtXK6/Yfgn5qnahL6bCkf2yKt4k3nuTKAtT4r3IG8JNR2ncsIMdZuAzJjHQQ==\",\n      \"dev\": true,\n      \"license\": \"MIT\"\n    },\n    \"node_modules/node-fetch\": {\n      \"version\": \"1.7.3\",\n      \"resolved\": \"https://registry.npmjs.org/node-fetch/-/node-fetch-1.7.3.tgz\",\n      \"integrity\": \"sha512-NhZ4CsKx7cYm2vSrBAr2PvFOe6sWDf0UYLRqA6svUYg7+/TSfVAu49jYC4BvQ4Sms9SZgdqGBgroqfDhJdTyKQ==\",\n      \"license\": \"MIT\",\n      \"dependencies\": {\n        \"encoding\": \"^0.1.11\",\n        \"is-stream\": \"^1.0.1\"\n      }\n    },\n    \"node_modules/node-gyp-build-optional-packages\": {\n      \"version\": \"5.1.1\",\n      \"resolved\": \"https://registry.npmjs.org/node-gyp-build-optional-packages/-/node-gyp-build-optional-packages-5.1.1.tgz\",\n      \"integrity\": \"sha512-+P72GAjVAbTxjjwUmwjVrqrdZROD4nf8KgpBoDxqXXTiYZZt/ud60dE5yvCSr9lRO8e8yv6kgJIC0K0PfZFVQw==\",\n      \"dev\": true,\n      \"license\": \"MIT\",\n      \"dependencies\": {\n        \"detect-libc\": \"^2.0.1\"\n      },\n      \"bin\": {\n        \"node-gyp-build-optional-packages\": \"bin.js\",\n        \"node-gyp-build-optional-packages-optional\": \"optional.js\",\n        \"node-gyp-build-optional-packages-test\": \"build-test.js\"\n      }\n    },\n    \"node_modules/node-gyp-build-optional-packages/node_modules/detect-libc\": {\n      \"version\": \"2.1.2\",\n      \"resolved\": \"https://registry.npmjs.org/detect-libc/-/detect-libc-2.1.2.tgz\",\n      \"integrity\": \"sha512-Btj2BOOO83o3WyH59e8MgXsxEQVcarkUOpEYrubB0urwnN10yQ364rsiByU11nZlqWYZm05i/of7io4mzihBtQ==\",\n      \"dev\": true,\n      \"license\": \"Apache-2.0\",\n      \"engines\": {\n        \"node\": \">=8\"\n      }\n    },\n    \"node_modules/node-releases\": {\n      \"version\": \"2.0.60\",\n      \"resolved\": \"https://registry.npmjs.org/node-releases/-/node-releases-2.0.60.tgz\",\n      \"integrity\": \"sha512-OmO8+GM1JUZqXET720VrJCwkjUCXmCMQm0Z3UDDRbfNLHS4NEAvY60j5jiFv0tkKw2PNNlqOLhahVmwJIOLDIQ==\",\n      \"dev\": true,\n      \"license\": \"MIT\",\n      \"engines\": {\n        \"node\": \">=18\"\n      }\n    },\n    \"node_modules/normalize-path\": {\n      \"version\": \"3.0.0\",\n      \"resolved\": \"https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz\",\n      \"integrity\": \"sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==\",\n      \"dev\": true,\n      \"license\": \"MIT\",\n      \"engines\": {\n        \"node\": \">=0.10.0\"\n      }\n    },\n    \"node_modules/nullthrows\": {\n      \"version\": \"1.1.1\",\n      \"resolved\": \"https://registry.npmjs.org/nullthrows/-/nullthrows-1.1.1.tgz\",\n      \"integrity\": \"sha512-2vPPEi+Z7WqML2jZYddDIfy5Dqb0r2fze2zTxNNknZaFpVHU3mFB3R+DWeJWGVx0ecvttSGlJTI+WG+8Z4cDWw==\",\n      \"dev\": true,\n      \"license\": \"MIT\"\n    },\n    \"node_modules/object-assign\": {\n      \"version\": \"4.1.1\",\n      \"resolved\": \"https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz\",\n      \"integrity\": \"sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==\",\n      \"license\": \"MIT\",\n      \"engines\": {\n        \"node\": \">=0.10.0\"\n      }\n    },\n    \"node_modules/once\": {\n      \"version\": \"1.4.0\",\n      \"resolved\": \"https://registry.npmjs.org/once/-/once-1.4.0.tgz\",\n      \"integrity\": \"sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==\",\n      \"dev\": true,\n      \"license\": \"ISC\",\n      \"dependencies\": {\n        \"wrappy\": \"1\"\n      }\n    },\n    \"node_modules/ordered-binary\": {\n      \"version\": \"1.6.3\",\n      \"resolved\": \"https://registry.npmjs.org/ordered-binary/-/ordered-binary-1.6.3.tgz\",\n      \"integrity\": \"sha512-Bc8LnA2x4ZHRQ9LjCm/NOdD3+CTQPhGNu8m7/6+ERtiB6Bb/fn7nCySwcmAC+5WCqwelpSAQgo1VX9BGpsC0tQ==\",\n      \"dev\": true,\n      \"license\": \"MIT\"\n    },\n    \"node_modules/p-limit\": {\n      \"version\": \"3.1.0\",\n      \"resolved\": \"https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz\",\n      \"integrity\": \"sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==\",\n      \"dev\": true,\n      \"license\": \"MIT\",\n      \"dependencies\": {\n        \"yocto-queue\": \"^0.1.0\"\n      },\n      \"engines\": {\n        \"node\": \">=10\"\n      },\n      \"funding\": {\n        \"url\": \"https://github.com/sponsors/sindresorhus\"\n      }\n    },\n    \"node_modules/p-locate\": {\n      \"version\": \"5.0.0\",\n      \"resolved\": \"https://registry.npmjs.org/p-locate/-/p-locate-5.0.0.tgz\",\n      \"integrity\": \"sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==\",\n      \"dev\": true,\n      \"license\": \"MIT\",\n      \"dependencies\": {\n        \"p-limit\": \"^3.0.2\"\n      },\n      \"engines\": {\n        \"node\": \">=10\"\n      },\n      \"funding\": {\n        \"url\": \"https://github.com/sponsors/sindresorhus\"\n      }\n    },\n    \"node_modules/parcel\": {\n      \"version\": \"2.16.4\",\n      \"resolved\": \"https://registry.npmjs.org/parcel/-/parcel-2.16.4.tgz\",\n      \"integrity\": \"sha512-RQlrqs4ujYNJpTQi+dITqPKNhRWEqpjPd1YBcGp50Wy3FcJHpwu0/iRm7XWz2dKU/Bwp2qCcVYPIeEDYi2uOUw==\",\n      \"dev\": true,\n      \"license\": \"MIT\",\n      \"dependencies\": {\n        \"@parcel/config-default\": \"2.16.4\",\n        \"@parcel/core\": \"2.16.4\",\n        \"@parcel/diagnostic\": \"2.16.4\",\n        \"@parcel/events\": \"2.16.4\",\n        \"@parcel/feature-flags\": \"2.16.4\",\n        \"@parcel/fs\": \"2.16.4\",\n        \"@parcel/logger\": \"2.16.4\",\n        \"@parcel/package-manager\": \"2.16.4\",\n        \"@parcel/reporter-cli\": \"2.16.4\",\n        \"@parcel/reporter-dev-server\": \"2.16.4\",\n        \"@parcel/reporter-tracer\": \"2.16.4\",\n        \"@parcel/utils\": \"2.16.4\",\n        \"chalk\": \"^4.1.2\",\n        \"commander\": \"^12.1.0\",\n        \"get-port\": \"^4.2.0\"\n      },\n      \"bin\": {\n        \"parcel\": \"lib/bin.js\"\n      },\n      \"engines\": {\n        \"node\": \">= 16.0.0\"\n      },\n      \"funding\": {\n        \"type\": \"opencollective\",\n        \"url\": \"https://opencollective.com/parcel\"\n      }\n    },\n    \"node_modules/parcel-namer-hashless\": {\n      \"version\": \"1.0.7\",\n      \"resolved\": \"https://registry.npmjs.org/parcel-namer-hashless/-/parcel-namer-hashless-1.0.7.tgz\",\n      \"integrity\": \"sha512-UzDAc47AH6gnzs8xiSkY3k8pVEGWurPiH+0RznWBCCiM35ybuehoVmAbu00AjaDSQ4DJKcVBjDvc+UYmN08vVw==\",\n      \"dev\": true,\n      \"license\": \"MIT\",\n      \"dependencies\": {\n        \"@parcel/namer-default\": \"^2.8.3\",\n        \"@parcel/plugin\": \"^2.8.3\",\n        \"@swc/helpers\": \"^0.5.1\"\n      },\n      \"engines\": {\n        \"node\": \">= 16.0.0\",\n        \"parcel\": \"2.x\"\n      }\n    },\n    \"node_modules/path-exists\": {\n      \"version\": \"4.0.0\",\n      \"resolved\": \"https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz\",\n      \"integrity\": \"sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==\",\n      \"dev\": true,\n      \"license\": \"MIT\",\n      \"engines\": {\n        \"node\": \">=8\"\n      }\n    },\n    \"node_modules/picocolors\": {\n      \"version\": \"1.1.1\",\n      \"resolved\": \"https://registry.npmjs.org/picocolors/-/picocolors-1.1.1.tgz\",\n      \"integrity\": \"sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==\",\n      \"dev\": true,\n      \"license\": \"ISC\"\n    },\n    \"node_modules/picomatch\": {\n      \"version\": \"2.3.2\",\n      \"resolved\": \"https://registry.npmjs.org/picomatch/-/picomatch-2.3.2.tgz\",\n      \"integrity\": \"sha512-V7+vQEJ06Z+c5tSye8S+nHUfI51xoXIXjHQ99cQtKUkQqqO1kO/KCJUfZXuB47h/YBlDhah2H3hdUGXn8ie0oA==\",\n      \"dev\": true,\n      \"license\": \"MIT\",\n      \"engines\": {\n        \"node\": \">=8.6\"\n      },\n      \"funding\": {\n        \"url\": \"https://github.com/sponsors/jonschlinkert\"\n      }\n    },\n    \"node_modules/postcss-value-parser\": {\n      \"version\": \"4.2.0\",\n      \"resolved\": \"https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-4.2.0.tgz\",\n      \"integrity\": \"sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ==\",\n      \"dev\": true,\n      \"license\": \"MIT\"\n    },\n    \"node_modules/process\": {\n      \"version\": \"0.11.10\",\n      \"resolved\": \"https://registry.npmjs.org/process/-/process-0.11.10.tgz\",\n      \"integrity\": \"sha512-cdGef/drWFoydD1JsMzuFf8100nZl+GT+yacc2bEced5f9Rjk4z+WtFUTBu9PhOi9j/jfmBPu0mMEY4wIdAF8A==\",\n      \"dev\": true,\n      \"license\": \"MIT\",\n      \"engines\": {\n        \"node\": \">= 0.6.0\"\n      }\n    },\n    \"node_modules/promise\": {\n      \"version\": \"7.3.1\",\n      \"resolved\": \"https://registry.npmjs.org/promise/-/promise-7.3.1.tgz\",\n      \"integrity\": \"sha512-nolQXZ/4L+bP/UGlkfaIujX9BKxGwmQ9OT4mOt5yvy8iK1h3wqTEJCijzGANTCCl9nWjY41juyAn2K3Q1hLLTg==\",\n      \"license\": \"MIT\",\n      \"dependencies\": {\n        \"asap\": \"~2.0.3\"\n      }\n    },\n    \"node_modules/prop-types\": {\n      \"version\": \"15.8.1\",\n      \"resolved\": \"https://registry.npmjs.org/prop-types/-/prop-types-15.8.1.tgz\",\n      \"integrity\": \"sha512-oj87CgZICdulUohogVAR7AjlC0327U4el4L6eAvOqCeudMDVU0NThNaV+b9Df4dXgSP1gXMTnPdhfe/2qDH5cg==\",\n      \"license\": \"MIT\",\n      \"dependencies\": {\n        \"loose-envify\": \"^1.4.0\",\n        \"object-assign\": \"^4.1.1\",\n        \"react-is\": \"^16.13.1\"\n      }\n    },\n    \"node_modules/randombytes\": {\n      \"version\": \"2.1.0\",\n      \"resolved\": \"https://registry.npmjs.org/randombytes/-/randombytes-2.1.0.tgz\",\n      \"integrity\": \"sha512-vYl3iOX+4CKUWuxGi9Ukhie6fsqXqS9FE2Zaic4tNFD2N2QQaXOMFbuKK4QmDHC0JO6B1Zp41J0LpT0oR68amQ==\",\n      \"dev\": true,\n      \"license\": \"MIT\",\n      \"dependencies\": {\n        \"safe-buffer\": \"^5.1.0\"\n      }\n    },\n    \"node_modules/react\": {\n      \"version\": \"18.3.1\",\n      \"resolved\": \"https://registry.npmjs.org/react/-/react-18.3.1.tgz\",\n      \"integrity\": \"sha512-wS+hAgJShR0KhEvPJArfuPVN1+Hz1t0Y6n5jLrGQbkb4urgPE/0Rve+1kMB1v/oWgHgm4WIcV+i7F2pTVj+2iQ==\",\n      \"license\": \"MIT\",\n      \"dependencies\": {\n        \"loose-envify\": \"^1.1.0\"\n      },\n      \"engines\": {\n        \"node\": \">=0.10.0\"\n      }\n    },\n    \"node_modules/react-dom\": {\n      \"version\": \"18.3.1\",\n      \"resolved\": \"https://registry.npmjs.org/react-dom/-/react-dom-18.3.1.tgz\",\n      \"integrity\": \"sha512-5m4nQKp+rZRb09LNH59GM4BxTh9251/ylbKIbpe7TpGxfJ+9kv6BLkLBXIjjspbgbnIBNqlI23tRnTWT0snUIw==\",\n      \"license\": \"MIT\",\n      \"dependencies\": {\n        \"loose-envify\": \"^1.1.0\",\n        \"scheduler\": \"^0.23.2\"\n      },\n      \"peerDependencies\": {\n        \"react\": \"^18.3.1\"\n      }\n    },\n    \"node_modules/react-intl\": {\n      \"version\": \"6.8.9\",\n      \"resolved\": \"https://registry.npmjs.org/react-intl/-/react-intl-6.8.9.tgz\",\n      \"integrity\": \"sha512-TUfj5E7lyUDvz/GtovC9OMh441kBr08rtIbgh3p0R8iF3hVY+V2W9Am7rb8BpJ/29BH1utJOqOOhmvEVh3GfZg==\",\n      \"license\": \"BSD-3-Clause\",\n      \"dependencies\": {\n        \"@formatjs/ecma402-abstract\": \"2.2.4\",\n        \"@formatjs/icu-messageformat-parser\": \"2.9.4\",\n        \"@formatjs/intl\": \"2.10.15\",\n        \"@formatjs/intl-displaynames\": \"6.8.5\",\n        \"@formatjs/intl-listformat\": \"7.7.5\",\n        \"@types/hoist-non-react-statics\": \"3\",\n        \"@types/react\": \"16 || 17 || 18\",\n        \"hoist-non-react-statics\": \"3\",\n        \"intl-messageformat\": \"10.7.7\",\n        \"tslib\": \"2\"\n      },\n      \"peerDependencies\": {\n        \"react\": \"^16.6.0 || 17 || 18\",\n        \"typescript\": \"^4.7 || 5\"\n      },\n      \"peerDependenciesMeta\": {\n        \"typescript\": {\n          \"optional\": true\n        }\n      }\n    },\n    \"node_modules/react-is\": {\n      \"version\": \"16.13.1\",\n      \"resolved\": \"https://registry.npmjs.org/react-is/-/react-is-16.13.1.tgz\",\n      \"integrity\": \"sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==\",\n      \"license\": \"MIT\"\n    },\n    \"node_modules/react-refresh\": {\n      \"version\": \"0.16.0\",\n      \"resolved\": \"https://registry.npmjs.org/react-refresh/-/react-refresh-0.16.0.tgz\",\n      \"integrity\": \"sha512-FPvF2XxTSikpJxcr+bHut2H4gJ17+18Uy20D5/F+SKzFap62R3cM5wH6b8WN3LyGSYeQilLEcJcR1fjBSI2S1A==\",\n      \"dev\": true,\n      \"license\": \"MIT\",\n      \"engines\": {\n        \"node\": \">=0.10.0\"\n      }\n    },\n    \"node_modules/react16\": {\n      \"version\": \"1.0.0\",\n      \"resolved\": \"https://registry.npmjs.org/react16/-/react16-1.0.0.tgz\",\n      \"integrity\": \"sha512-TF3fQcz4LRhzlZ6Bo+qczbvNNHowkq0jHpFj45f+8wkFy3IAgGISLyDVF4nw+JHrxhvy6pGpMgPkE014bXX70Q==\",\n      \"license\": \"MIT\",\n      \"dependencies\": {\n        \"fbjs\": \"^0.8.16\",\n        \"loose-envify\": \"^1.1.0\",\n        \"object-assign\": \"^4.1.1\",\n        \"prop-types\": \"^15.6.0\"\n      },\n      \"engines\": {\n        \"node\": \">=0.10.0\"\n      }\n    },\n    \"node_modules/readdirp\": {\n      \"version\": \"3.6.0\",\n      \"resolved\": \"https://registry.npmjs.org/readdirp/-/readdirp-3.6.0.tgz\",\n      \"integrity\": \"sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==\",\n      \"dev\": true,\n      \"license\": \"MIT\",\n      \"dependencies\": {\n        \"picomatch\": \"^2.2.1\"\n      },\n      \"engines\": {\n        \"node\": \">=8.10.0\"\n      }\n    },\n    \"node_modules/regenerator-runtime\": {\n      \"version\": \"0.14.1\",\n      \"resolved\": \"https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.14.1.tgz\",\n      \"integrity\": \"sha512-dYnhHh0nJoMfnkZs6GmmhFknAGRrLznOu5nc9ML+EJxGvrx6H7teuevqVqCuPcPK//3eDrrjQhehXVx9cnkGdw==\",\n      \"dev\": true,\n      \"license\": \"MIT\"\n    },\n    \"node_modules/require-directory\": {\n      \"version\": \"2.1.1\",\n      \"resolved\": \"https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz\",\n      \"integrity\": \"sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q==\",\n      \"dev\": true,\n      \"license\": \"MIT\",\n      \"engines\": {\n        \"node\": \">=0.10.0\"\n      }\n    },\n    \"node_modules/safe-buffer\": {\n      \"version\": \"5.2.1\",\n      \"resolved\": \"https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz\",\n      \"integrity\": \"sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==\",\n      \"dev\": true,\n      \"funding\": [\n        {\n          \"type\": \"github\",\n          \"url\": \"https://github.com/sponsors/feross\"\n        },\n        {\n          \"type\": \"patreon\",\n          \"url\": \"https://www.patreon.com/feross\"\n        },\n        {\n          \"type\": \"consulting\",\n          \"url\": \"https://feross.org/support\"\n        }\n      ],\n      \"license\": \"MIT\"\n    },\n    \"node_modules/safer-buffer\": {\n      \"version\": \"2.1.2\",\n      \"resolved\": \"https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz\",\n      \"integrity\": \"sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==\",\n      \"license\": \"MIT\"\n    },\n    \"node_modules/scheduler\": {\n      \"version\": \"0.23.2\",\n      \"resolved\": \"https://registry.npmjs.org/scheduler/-/scheduler-0.23.2.tgz\",\n      \"integrity\": \"sha512-UOShsPwz7NrMUqhR6t0hWjFduvOzbtv7toDH1/hIrfRNIDBnnBWd0CwJTGvTpngVlmwGCdP9/Zl/tVrDqcuYzQ==\",\n      \"license\": \"MIT\",\n      \"dependencies\": {\n        \"loose-envify\": \"^1.1.0\"\n      }\n    },\n    \"node_modules/semver\": {\n      \"version\": \"7.8.5\",\n      \"resolved\": \"https://registry.npmjs.org/semver/-/semver-7.8.5.tgz\",\n      \"integrity\": \"sha512-Y7/KDsb8LjooZpwaqGyulO6DQlksgCncchHGk+sZIY4SBvUocMBEFH5Ur1fI4dV+Jvl0w6cjvucaIi40puRioA==\",\n      \"dev\": true,\n      \"license\": \"ISC\",\n      \"bin\": {\n        \"semver\": \"bin/semver.js\"\n      },\n      \"engines\": {\n        \"node\": \">=10\"\n      }\n    },\n    \"node_modules/serialize-javascript\": {\n      \"version\": \"6.0.2\",\n      \"resolved\": \"https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-6.0.2.tgz\",\n      \"integrity\": \"sha512-Saa1xPByTTq2gdeFZYLLo+RFE35NHZkAbqZeWNd3BpzppeVisAqpDjcp8dyf6uIvEqJRd46jemmyA4iFIeVk8g==\",\n      \"dev\": true,\n      \"license\": \"BSD-3-Clause\",\n      \"dependencies\": {\n        \"randombytes\": \"^2.1.0\"\n      }\n    },\n    \"node_modules/setimmediate\": {\n      \"version\": \"1.0.5\",\n      \"resolved\": \"https://registry.npmjs.org/setimmediate/-/setimmediate-1.0.5.tgz\",\n      \"integrity\": \"sha512-MATJdZp8sLqDl/68LfQmbP8zKPLQNV6BIZoIgrscFDQ+RsvK/BxeDQOgyxKKoh0y/8h3BqVFnCqQ/gd+reiIXA==\",\n      \"license\": \"MIT\"\n    },\n    \"node_modules/string-width\": {\n      \"version\": \"4.2.3\",\n      \"resolved\": \"https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz\",\n      \"integrity\": \"sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==\",\n      \"dev\": true,\n      \"license\": \"MIT\",\n      \"dependencies\": {\n        \"emoji-regex\": \"^8.0.0\",\n        \"is-fullwidth-code-point\": \"^3.0.0\",\n        \"strip-ansi\": \"^6.0.1\"\n      },\n      \"engines\": {\n        \"node\": \">=8\"\n      }\n    },\n    \"node_modules/strip-ansi\": {\n      \"version\": \"6.0.1\",\n      \"resolved\": \"https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz\",\n      \"integrity\": \"sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==\",\n      \"dev\": true,\n      \"license\": \"MIT\",\n      \"dependencies\": {\n        \"ansi-regex\": \"^5.0.1\"\n      },\n      \"engines\": {\n        \"node\": \">=8\"\n      }\n    },\n    \"node_modules/strip-json-comments\": {\n      \"version\": \"3.1.1\",\n      \"resolved\": \"https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz\",\n      \"integrity\": \"sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==\",\n      \"dev\": true,\n      \"license\": \"MIT\",\n      \"engines\": {\n        \"node\": \">=8\"\n      },\n      \"funding\": {\n        \"url\": \"https://github.com/sponsors/sindresorhus\"\n      }\n    },\n    \"node_modules/supports-color\": {\n      \"version\": \"8.1.1\",\n      \"resolved\": \"https://registry.npmjs.org/supports-color/-/supports-color-8.1.1.tgz\",\n      \"integrity\": \"sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==\",\n      \"dev\": true,\n      \"license\": \"MIT\",\n      \"dependencies\": {\n        \"has-flag\": \"^4.0.0\"\n      },\n      \"engines\": {\n        \"node\": \">=10\"\n      },\n      \"funding\": {\n        \"url\": \"https://github.com/chalk/supports-color?sponsor=1\"\n      }\n    },\n    \"node_modules/term-size\": {\n      \"version\": \"2.2.1\",\n      \"resolved\": \"https://registry.npmjs.org/term-size/-/term-size-2.2.1.tgz\",\n      \"integrity\": \"sha512-wK0Ri4fOGjv/XPy8SBHZChl8CM7uMc5VML7SqiQ0zG7+J5Vr+RMQDoHa2CNT6KHUnTGIXH34UDMkPzAUyapBZg==\",\n      \"dev\": true,\n      \"license\": \"MIT\",\n      \"engines\": {\n        \"node\": \">=8\"\n      },\n      \"funding\": {\n        \"url\": \"https://github.com/sponsors/sindresorhus\"\n      }\n    },\n    \"node_modules/to-regex-range\": {\n      \"version\": \"5.0.1\",\n      \"resolved\": \"https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz\",\n      \"integrity\": \"sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==\",\n      \"dev\": true,\n      \"license\": \"MIT\",\n      \"dependencies\": {\n        \"is-number\": \"^7.0.0\"\n      },\n      \"engines\": {\n        \"node\": \">=8.0\"\n      }\n    },\n    \"node_modules/ts-node\": {\n      \"version\": \"10.9.2\",\n      \"resolved\": \"https://registry.npmjs.org/ts-node/-/ts-node-10.9.2.tgz\",\n      \"integrity\": \"sha512-f0FFpIdcHgn8zcPSbf1dRevwt047YMnaiJM3u2w2RewrB+fob/zePZcrOyQoLMMO7aBIddLcQIEK5dYjkLnGrQ==\",\n      \"dev\": true,\n      \"license\": \"MIT\",\n      \"dependencies\": {\n        \"@cspotcode/source-map-support\": \"^0.8.0\",\n        \"@tsconfig/node10\": \"^1.0.7\",\n        \"@tsconfig/node12\": \"^1.0.7\",\n        \"@tsconfig/node14\": \"^1.0.0\",\n        \"@tsconfig/node16\": \"^1.0.2\",\n        \"acorn\": \"^8.4.1\",\n        \"acorn-walk\": \"^8.1.1\",\n        \"arg\": \"^4.1.0\",\n        \"create-require\": \"^1.1.0\",\n        \"diff\": \"^4.0.1\",\n        \"make-error\": \"^1.1.1\",\n        \"v8-compile-cache-lib\": \"^3.0.1\",\n        \"yn\": \"3.1.1\"\n      },\n      \"bin\": {\n        \"ts-node\": \"dist/bin.js\",\n        \"ts-node-cwd\": \"dist/bin-cwd.js\",\n        \"ts-node-esm\": \"dist/bin-esm.js\",\n        \"ts-node-script\": \"dist/bin-script.js\",\n        \"ts-node-transpile-only\": \"dist/bin-transpile.js\",\n        \"ts-script\": \"dist/bin-script-deprecated.js\"\n      },\n      \"peerDependencies\": {\n        \"@swc/core\": \">=1.2.50\",\n        \"@swc/wasm\": \">=1.2.50\",\n        \"@types/node\": \"*\",\n        \"typescript\": \">=2.7\"\n      },\n      \"peerDependenciesMeta\": {\n        \"@swc/core\": {\n          \"optional\": true\n        },\n        \"@swc/wasm\": {\n          \"optional\": true\n        }\n      }\n    },\n    \"node_modules/ts-node/node_modules/diff\": {\n      \"version\": \"4.0.4\",\n      \"resolved\": \"https://registry.npmjs.org/diff/-/diff-4.0.4.tgz\",\n      \"integrity\": \"sha512-X07nttJQkwkfKfvTPG/KSnE2OMdcUCao6+eXF3wmnIQRn2aPAHH3VxDbDOdegkd6JbPsXqShpvEOHfAT+nCNwQ==\",\n      \"dev\": true,\n      \"license\": \"BSD-3-Clause\",\n      \"engines\": {\n        \"node\": \">=0.3.1\"\n      }\n    },\n    \"node_modules/tslib\": {\n      \"version\": \"2.8.1\",\n      \"resolved\": \"https://registry.npmjs.org/tslib/-/tslib-2.8.1.tgz\",\n      \"integrity\": \"sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==\",\n      \"license\": \"0BSD\"\n    },\n    \"node_modules/type-fest\": {\n      \"version\": \"0.20.2\",\n      \"resolved\": \"https://registry.npmjs.org/type-fest/-/type-fest-0.20.2.tgz\",\n      \"integrity\": \"sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ==\",\n      \"dev\": true,\n      \"license\": \"(MIT OR CC0-1.0)\",\n      \"engines\": {\n        \"node\": \">=10\"\n      },\n      \"funding\": {\n        \"url\": \"https://github.com/sponsors/sindresorhus\"\n      }\n    },\n    \"node_modules/typescript\": {\n      \"version\": \"5.9.3\",\n      \"resolved\": \"https://registry.npmjs.org/typescript/-/typescript-5.9.3.tgz\",\n      \"integrity\": \"sha512-jl1vZzPDinLr9eUt3J/t7V6FgNEw9QjvBPdysz9KfQDD41fQrC2Y4vKQdiaUpFT4bXlb1RHhLpp8wtm6M5TgSw==\",\n      \"devOptional\": true,\n      \"license\": \"Apache-2.0\",\n      \"bin\": {\n        \"tsc\": \"bin/tsc\",\n        \"tsserver\": \"bin/tsserver\"\n      },\n      \"engines\": {\n        \"node\": \">=14.17\"\n      }\n    },\n    \"node_modules/ua-parser-js\": {\n      \"version\": \"0.7.41\",\n      \"resolved\": \"https://registry.npmjs.org/ua-parser-js/-/ua-parser-js-0.7.41.tgz\",\n      \"integrity\": \"sha512-O3oYyCMPYgNNHuO7Jjk3uacJWZF8loBgwrfd/5LE/HyZ3lUIOdniQ7DNXJcIgZbwioZxk0fLfI4EVnetdiX5jg==\",\n      \"funding\": [\n        {\n          \"type\": \"opencollective\",\n          \"url\": \"https://opencollective.com/ua-parser-js\"\n        },\n        {\n          \"type\": \"paypal\",\n          \"url\": \"https://paypal.me/faisalman\"\n        },\n        {\n          \"type\": \"github\",\n          \"url\": \"https://github.com/sponsors/faisalman\"\n        }\n      ],\n      \"license\": \"MIT\",\n      \"bin\": {\n        \"ua-parser-js\": \"script/cli.js\"\n      },\n      \"engines\": {\n        \"node\": \"*\"\n      }\n    },\n    \"node_modules/update-browserslist-db\": {\n      \"version\": \"1.3.4\",\n      \"resolved\": \"https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.3.4.tgz\",\n      \"integrity\": \"sha512-t8wonIOdQyOjtPd2VktlBu6QjTVTks6v8bSi7kd0r2Vll8TK1JYDZtRRdbmCHOAMphkZgrzK+L+vXK4pyZ8t4A==\",\n      \"dev\": true,\n      \"funding\": [\n        {\n          \"type\": \"opencollective\",\n          \"url\": \"https://opencollective.com/browserslist\"\n        },\n        {\n          \"type\": \"tidelift\",\n          \"url\": \"https://tidelift.com/funding/github/npm/browserslist\"\n        },\n        {\n          \"type\": \"github\",\n          \"url\": \"https://github.com/sponsors/ai\"\n        }\n      ],\n      \"license\": \"MIT\",\n      \"dependencies\": {\n        \"escalade\": \"^3.2.0\",\n        \"picocolors\": \"^1.1.1\"\n      },\n      \"bin\": {\n        \"update-browserslist-db\": \"cli.js\"\n      },\n      \"peerDependencies\": {\n        \"browserslist\": \">= 4.21.0\"\n      }\n    },\n    \"node_modules/utility-types\": {\n      \"version\": \"3.11.0\",\n      \"resolved\": \"https://registry.npmjs.org/utility-types/-/utility-types-3.11.0.tgz\",\n      \"integrity\": \"sha512-6Z7Ma2aVEWisaL6TvBCy7P8rm2LQoPv6dJ7ecIaIixHcwfbJ0x7mWdbcwlIM5IGQxPZSFYeqRCqlOOeKoJYMkw==\",\n      \"dev\": true,\n      \"license\": \"MIT\",\n      \"engines\": {\n        \"node\": \">= 4\"\n      }\n    },\n    \"node_modules/v8-compile-cache-lib\": {\n      \"version\": \"3.0.1\",\n      \"resolved\": \"https://registry.npmjs.org/v8-compile-cache-lib/-/v8-compile-cache-lib-3.0.1.tgz\",\n      \"integrity\": \"sha512-wa7YjyUGfNZngI/vtK0UHAN+lgDCxBPCylVXGp0zu59Fz5aiGtNXaq3DhIov063MorB+VfufLh3JlF2KdTK3xg==\",\n      \"dev\": true,\n      \"license\": \"MIT\"\n    },\n    \"node_modules/weak-lru-cache\": {\n      \"version\": \"1.2.2\",\n      \"resolved\": \"https://registry.npmjs.org/weak-lru-cache/-/weak-lru-cache-1.2.2.tgz\",\n      \"integrity\": \"sha512-DEAoo25RfSYMuTGc9vPJzZcZullwIqRDSI9LOy+fkCJPi6hykCnfKaXTuPBDuXAUcqHXyOgFtHNp/kB2FjYHbw==\",\n      \"dev\": true,\n      \"license\": \"MIT\"\n    },\n    \"node_modules/whatwg-fetch\": {\n      \"version\": \"3.6.20\",\n      \"resolved\": \"https://registry.npmjs.org/whatwg-fetch/-/whatwg-fetch-3.6.20.tgz\",\n      \"integrity\": \"sha512-EqhiFU6daOA8kpjOWTL0olhVOF3i7OrFzSYiGsEMB8GcXS+RrzauAERX65xMeNWVqxA6HXH2m69Z9LaKKdisfg==\",\n      \"license\": \"MIT\"\n    },\n    \"node_modules/workerpool\": {\n      \"version\": \"6.5.1\",\n      \"resolved\": \"https://registry.npmjs.org/workerpool/-/workerpool-6.5.1.tgz\",\n      \"integrity\": \"sha512-Fs4dNYcsdpYSAfVxhnl1L5zTksjvOJxtC5hzMNl+1t9B8hTJTdKDyZ5ju7ztgPy+ft9tBFXoOlDNiOT9WUXZlA==\",\n      \"dev\": true,\n      \"license\": \"Apache-2.0\"\n    },\n    \"node_modules/wrap-ansi\": {\n      \"version\": \"7.0.0\",\n      \"resolved\": \"https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz\",\n      \"integrity\": \"sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==\",\n      \"dev\": true,\n      \"license\": \"MIT\",\n      \"dependencies\": {\n        \"ansi-styles\": \"^4.0.0\",\n        \"string-width\": \"^4.1.0\",\n        \"strip-ansi\": \"^6.0.0\"\n      },\n      \"engines\": {\n        \"node\": \">=10\"\n      },\n      \"funding\": {\n        \"url\": \"https://github.com/chalk/wrap-ansi?sponsor=1\"\n      }\n    },\n    \"node_modules/wrappy\": {\n      \"version\": \"1.0.2\",\n      \"resolved\": \"https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz\",\n      \"integrity\": \"sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==\",\n      \"dev\": true,\n      \"license\": \"ISC\"\n    },\n    \"node_modules/y18n\": {\n      \"version\": \"5.0.8\",\n      \"resolved\": \"https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz\",\n      \"integrity\": \"sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==\",\n      \"dev\": true,\n      \"license\": \"ISC\",\n      \"engines\": {\n        \"node\": \">=10\"\n      }\n    },\n    \"node_modules/yargs\": {\n      \"version\": \"16.2.2\",\n      \"resolved\": \"https://registry.npmjs.org/yargs/-/yargs-16.2.2.tgz\",\n      \"integrity\": \"sha512-Nt9ZJjXTv5R8MHbqby/wXQ6Gi0Bb3TcYZkR1bzuL4yB2OxWPkXknz513gEF0GoA6tn00UpbPvERW8rzCuWCA6w==\",\n      \"dev\": true,\n      \"license\": \"MIT\",\n      \"dependencies\": {\n        \"cliui\": \"^7.0.2\",\n        \"escalade\": \"^3.1.1\",\n        \"get-caller-file\": \"^2.0.5\",\n        \"require-directory\": \"^2.1.1\",\n        \"string-width\": \"^4.2.0\",\n        \"y18n\": \"^5.0.5\",\n        \"yargs-parser\": \"^20.2.2\"\n      },\n      \"engines\": {\n        \"node\": \">=10\"\n      }\n    },\n    \"node_modules/yargs-parser\": {\n      \"version\": \"20.2.9\",\n      \"resolved\": \"https://registry.npmjs.org/yargs-parser/-/yargs-parser-20.2.9.tgz\",\n      \"integrity\": \"sha512-y11nGElTIV+CT3Zv9t7VKl+Q3hTQoT9a1Qzezhhl6Rp21gJ/IVTW7Z3y9EWXhuUBC2Shnf+DX0antecpAwSP8w==\",\n      \"dev\": true,\n      \"license\": \"ISC\",\n      \"engines\": {\n        \"node\": \">=10\"\n      }\n    },\n    \"node_modules/yargs-unparser\": {\n      \"version\": \"2.0.0\",\n      \"resolved\": \"https://registry.npmjs.org/yargs-unparser/-/yargs-unparser-2.0.0.tgz\",\n      \"integrity\": \"sha512-7pRTIA9Qc1caZ0bZ6RYRGbHJthJWuakf+WmHK0rVeLkNrrGhfoabBNdue6kdINI6r4if7ocq9aD/n7xwKOdzOA==\",\n      \"dev\": true,\n      \"license\": \"MIT\",\n      \"dependencies\": {\n        \"camelcase\": \"^6.0.0\",\n        \"decamelize\": \"^4.0.0\",\n        \"flat\": \"^5.0.2\",\n        \"is-plain-obj\": \"^2.1.0\"\n      },\n      \"engines\": {\n        \"node\": \">=10\"\n      }\n    },\n    \"node_modules/yn\": {\n      \"version\": \"3.1.1\",\n      \"resolved\": \"https://registry.npmjs.org/yn/-/yn-3.1.1.tgz\",\n      \"integrity\": \"sha512-Ux4ygGWsu2c7isFWe8Yu1YluJmqVhxqK2cLXNQA5AcC3QfbGNpM7fu0Y8b/z16pXLnFxZYvWhd3fhBY9DLmC6Q==\",\n      \"dev\": true,\n      \"license\": \"MIT\",\n      \"engines\": {\n        \"node\": \">=6\"\n      }\n    },\n    \"node_modules/yocto-queue\": {\n      \"version\": \"0.1.0\",\n      \"resolved\": \"https://registry.npmjs.org/yocto-queue/-/yocto-queue-0.1.0.tgz\",\n      \"integrity\": \"sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==\",\n      \"dev\": true,\n      \"license\": \"MIT\",\n      \"engines\": {\n        \"node\": \">=10\"\n      },\n      \"funding\": {\n        \"url\": \"https://github.com/sponsors/sindresorhus\"\n      }\n    }\n  }\n}\n", "sic1/client/package.json": "{\n  \"name\": \"sic1-client\",\n  \"version\": \"1.11.6\",\n  \"description\": \"Single-instruction computer programming game (web client)\",\n  \"scripts\": {\n    \"intl:extract\": \"formatjs extract \\\"ts/*.ts*\\\" --ignore=\\\"*/*.d.ts\\\" --out-file content/messages/en.json --preserve-whitespace\",\n    \"intl:pseudoloc\": \"copy content\\\\messages\\\\en.json content\\\\messages\\\\en-XA.json && formatjs compile content/messages/en-XA.json --ast --pseudo-locale en-XA --out-file content/messages-compiled/en-XA.json\",\n    \"intl:download\": \"ts-node build/translations-download.ts && ts-node build/translations-extract.ts\",\n    \"test\": \"pushd test && mocha --require ts-node/register *.spec.ts && popd\",\n    \"watch:test\": \"npx mocha --watch --require ts-node/register test/*.spec.ts --watch --watch-extensions ts\",\n    \"build\": \"parcel build --no-cache --public-url ./ index.html\",\n    \"build:dev\": \"parcel build --no-cache --no-optimize --public-url ./ index.html\",\n    \"build:intl\": \"formatjs compile-folder --ast content/messages content/messages-compiled && ts-node build/build-language-data.tsx && ts-node build/build-manual.tsx\",\n    \"convert:mail\": \"ts-node build/convert-mail.ts\",\n    \"serve\": \"parcel serve --no-cache index.html\"\n  },\n  \"source\": \"index.html\",\n  \"@parcel/runtime-js\": {\n    \"splitManifestThreshold\": 100000000\n  },\n  \"devDependencies\": {\n    \"@formatjs/cli\": \"^6.2.4\",\n    \"@types/adm-zip\": \"^0.5.5\",\n    \"@types/lz-string\": \"^1.3.34\",\n    \"@types/mocha\": \"^7.0.1\",\n    \"@types/node\": \"^13.7.0\",\n    \"adm-zip\": \"^0.5.10\",\n    \"md2jsx\": \"^1.1.0\",\n    \"mocha\": \"^10.2.0\",\n    \"parcel\": \"^2.11.0\",\n    \"parcel-namer-hashless\": \"^1.0.3\",\n    \"process\": \"^0.11.10\",\n    \"ts-node\": \"^10.9.2\",\n    \"typescript\": \"^5.3.3\"\n  },\n  \"dependencies\": {\n    \"backtrace-js\": \"^1.1.3\",\n    \"crs_queue\": \"^3.2.1\",\n    \"lz-string\": \"^1.4.4\",\n    \"react\": \"^18.2.0\",\n    \"react-dom\": \"^18.2.0\",\n    \"react-intl\": \"^6.5.5\",\n    \"react16\": \"^1.0.0\"\n  },\n  \"engines\": {\n    \"browsers\": \"Chrome 90\"\n  }\n}", "sic1/client/tsconfig.json": "{\n    \"compilerOptions\": {\n      \"module\": \"ES2020\",\n      \"moduleResolution\": \"Node\",\n      \"resolveJsonModule\": true,\n      \"esModuleInterop\": true,\n      \"noEmit\": true,\n      \"types\": [],\n      \"lib\": [\"ESNext\", \"DOM\"],\n      \"jsx\": \"react\",\n      \"skipLibCheck\": true,\n      \"baseUrl\": \"./\"\n    }\n}", "sic1/client/favicon.svg": "<svg xmlns=\"http://www.w3.org/2000/svg\" viewBox=\"0 0 64 64\"><rect width=\"64\" height=\"64\" rx=\"12\" fill=\"#071609\"/><text x=\"8\" y=\"43\" fill=\"#8eef9a\" font-family=\"monospace\" font-size=\"32\">S1</text></svg>", "sic1/client/test/puzzles.spec.ts": "import \"mocha\";\nimport { puzzleFlatArray, shuffleInPlace } from \"../../shared/puzzles\";\nimport * as assert from \"assert\";\n\ndescribe(\"Random test validators\", () => {\n    puzzleFlatArray.forEach(puzzle => { it(puzzle.title, () => {\n        if (puzzle.test) {\n            const inputs = [];\n            const outputs = [];\n            puzzle.io.forEach(row => {\n                const input = row[0];\n                const output = row[1];\n                inputs.push(input);\n                outputs.push(output);\n            });\n\n            assert.deepStrictEqual(outputs, puzzle.test.getExpectedOutput(inputs));\n\n            let randomInputSequence = puzzle.test.createRandomTest();\n            if (puzzle.test.fixed) {\n                for (const fixed of puzzle.test.fixed) {\n                    randomInputSequence = randomInputSequence.concat(fixed);\n                }\n            }\n\n            shuffleInPlace(randomInputSequence);\n\n            const expectedOutputSequence = puzzle.test.getExpectedOutput(randomInputSequence);\n            for (let i = 0; i < randomInputSequence.length; i++) {\n                // console.log(`[${randomInputSequence[i].join(\", \")}] => [${expectedOutputSequence[i].join(\", \")}]`);\n            }\n        }\n    }); });\n});\n", "sic1/client/test/language-default.spec.ts": "import \"mocha\";\nimport * as assert from \"assert\";\nimport { getBestLocale } from \"../ts/language-default\";\n\ndescribe(\"Locale matcher should produce sane results\", () => {\n    const testLocales = [\n        \"en\",\n        \"zh-Hant\",\n        \"zh-Hans\",\n        \"ru\",\n        \"pt-BR\",\n    ];\n    \n    const tests = [\n        // English tests\n        [[], \"en\"],\n        [[\"en-US\"], \"en\"],\n        [[\"en-GB\"], \"en\"],\n\n        // Test language fallback\n        [[\"ru-RU\"], \"ru\"],\n        [[\"pt\"], \"pt-BR\"],\n        [[\"pt-PT\"], \"pt-BR\"],\n        [[\"pt-BR\"], \"pt-BR\"],\n\n        // Test Chinese handling\n        [[\"zh-CN\"], \"zh-Hans\"],\n        [[\"zh-TW\"], \"zh-Hant\"],\n        [[\"zh-HK\"], \"zh-Hant\"],\n        [[\"zh-Hans-CN\"], \"zh-Hans\"],\n        [[\"zh-Hant-TW\"], \"zh-Hant\"],\n    ];\n\n    for (const [desiredLocaleStrings, expectedResult] of tests) {\n        it(`${desiredLocaleStrings} should match ${expectedResult}`, () => assert.strictEqual(getBestLocale(desiredLocaleStrings as string[], testLocales), expectedResult))\n    }\n\n    // And a tricky one\n    it(\"Second choice is better than mismatched language\", () => assert.strictEqual(getBestLocale([\"zh-HK\", \"ru-HK\"], [\"zh-Hans\", \"ru\"]), \"ru\"));\n});\n", "sic1/client/test/tsconfig.json": "{\n    \"compilerOptions\": {\n        \"target\": \"ES2019\",\n        \"esModuleInterop\": true,\n        \"types\": [\"node\"]\n    },\n    \"files\": [\n        \"language-default.spec.ts\",\n        \"puzzles.spec.ts\"\n    ]\n}", "sic1/client/css/main.css": "\n\n\n\n:root {\n    /* Lime (default) */\n    --fg: #00ff00;\n    --sfg: #008000;\n    --sbg: #008000;\n    --bg: #000000;\n    --filter: none;\n}\n\n:focus {\n    outline: 4px solid var(--fg);\n    outline-offset: -4px;\n}\n\nhtml, body {\n    margin: 0;\n}\n\n.controls {\n    flex-basis: 20%;\n    display: flex;\n    flex-direction: column;\n}\n\n.controlGroup {\n    margin: 1em 0;\n}\n\n.controlFooter {\n    margin: 0.5em 0.25em 0.5em 0.25em;\n    border-top: 1px solid var(--sfg);\n    color: var(--sfg);\n}\n\n.program {\n    overflow: auto;\n    height: 30em;\n\n    display: flex;\n    flex-direction: row;\n    column-gap: 0.25em;\n}\n\n.gutter {\n    padding: 0 0.25em;\n}\n\n.breakpoint {\n    cursor: pointer;\n    outline: none;\n}\n\n.breakpoint:focus {\n    outline-offset: 0;\n    outline: 2px solid var(--fg);\n}\n\n.source {\n    font-size: 100%;\n    white-space: pre;\n}\n\n.input {\n    font-size: 100%;\n\n    display: block;\n    width: 100%;\n    height: 100%;\n    border: 0px;\n    margin: 0px;\n    padding: 0px;\n\n    resize: none;\n    outline: 0px;\n}\n\n.width100 {\n    width: 100%;\n    display: block;\n}\n\n.width100inline {\n    width: 100%;\n}\n\n.centerContainer {\n    position: absolute;\n    top: 0;\n    left: 0;\n    width: 100%;\n    height: 100%;\n    display: flex;\n    align-items: center;\n    justify-content: center;\n}\n\n.messageBox {\n    background-color: var(--fg);\n    filter: drop-shadow(0em 0em 0.5em var(--fg));\n\n    padding: 1px;\n    max-height: 100vh;\n    overflow: auto;\n}\n\n.fader {\n    position: fixed;\n    top: 0;\n    left: 0;\n    width: 100%;\n    height: 100%;\n    opacity: 1.0;\n    background-color: var(--bg);\n    animation-name: fadeOut;\n    z-index: 60;\n}\n\n.messageHeader {\n    padding: 0.25em;\n    text-align: center;\n}\n\n.messageHeader, .messageHeader a {\n    color: var(--bg);\n}\n\n.messageClose {\n    float: right;\n    font-size: 80%;\n    margin: 0px;\n}\n\n.messageBody {\n    background-color: var(--sbg);\n    padding: 0.5em 1em;\n}\n\n.messageBody button:not(.messageClose) {\n    padding: 0.5em;\n    margin: 0.25em 0;\n    border-width: 2px;\n    border-style: solid;\n    display: block;\n    width: 100%;\n}\n\n.messageBody pre {\n    padding: 0.25em;\n    border: 1px solid var(--fg);\n    overflow-x: auto;\n}\n\n.messageBody code {\n    font-weight: bold;\n    text-transform: none;\n}\n\n.messageBody pre > code {\n    font-weight: normal;\n}\n\n.wide {\n    max-width: 80em;\n}\n\n.narrow {\n    max-width: 60em;\n}\n\n.narrowByDefault {\n    width: 60em;\n}\n\n.browser {\n    display: flex;\n    flex-direction: row;\n    width: 90vw;\n    height: 90vh;\n    max-width: 80em;\n}\n\n.browserList {\n    padding: 0 0.25em;\n    overflow-y: auto;\n    display: flex;\n    flex-direction: column;\n    flex-shrink: 0;\n}\n\n.browserList > div, .itemList {\n    background-color: var(--bg);\n    border: 2px solid var(--fg);\n}\n\n.browserList p, .itemList p {\n    padding: 0.05em 0.25em;\n    margin: 0;\n}\n\n.browserList > p {\n    font-weight: bold;\n    padding: 0.25em 0;\n}\n\n.browserList > div > p, .itemList > p {\n    border-bottom: 1px solid var(--fg);\n    cursor: pointer;\n    outline: none;\n}\n\n.browserList .sub, .itemList .sub {\n    color: var(--sfg);\n}\n\n.browserList .selected, .itemList .selected {\n    background-color: var(--fg);\n    color: var(--bg);\n}\n\n.browserList .selected .sub, .itemList .selected .sub {\n    color: var(--bg);\n}\n\n.itemMoveContainer {\n    float: right;\n}\n\n.itemList button.itemMove {\n    display: inline;\n    width: auto;\n    margin: 0px;\n    padding: 0px 0.5em;\n    border: none;\n}\n\n.itemList span.editable {\n    background-color: var(--sbg);\n    color: var(--fg);\n    outline: none;\n}\n\n.browserView {\n    margin-left: 1.25em;\n    flex-grow: 1;\n    display: flex;\n    flex-direction: column;\n    overflow-x: hidden;\n}\n\n.browserView .browserContent {\n    overflow-y: auto;\n    flex-grow: 1;\n    border-bottom: 3px solid var(--fg);\n    margin-bottom: 0.5em;\n}\n\n.browserContent:focus {\n    outline: none;\n}\n\n.browserView header {\n    padding-bottom: 0.5em;\n    border-bottom: 3px solid var(--fg);\n}\n\n.mailBrowser .browserList > div:last-of-type {\n    flex-grow: 1;\n}\n\n.horizontalButtons {\n    margin: 1em 0;\n    display: flex;\n    flex-direction: row;\n    flex-wrap: wrap;\n    column-gap: 1em;\n}\n\n.horizontalButtons button:not(.messageClose) {\n    flex-grow: 1;\n    width: auto;\n    padding: 0.25em;\n    margin: 0px;\n}\n\n.dimmer {\n    position: fixed;\n    top: 0;\n    left: 0;\n    width: 100%;\n    height: 100%;\n    opacity: 0.5;\n    background-color: var(--bg);\n}\n\n.hidden {\n    display: none;\n}\n\nbody, textarea, button, input, code, pre, select {\n    font-family: 'Cascadia Mono', 'Consolas', monospace;\n    font-size: 100%;\n}\n\nbody, textarea, button, input, pre {\n    background-color: var(--bg);\n    color: var(--fg);\n}\n\na, a:hover, a:visited, a:active {\n    color: var(--fg);\n}\n\nlabel {\n    display: flex;\n    flex-direction: row;\n    align-items: center;\n}\n\nlabel + label {\n    margin-top: 0.5em;\n}\n\ninput {\n    accent-color: var(--fg);\n}\n\nlabel > input {\n    margin: 0 0 0 0.5em;\n}\n\nlabel > input[type='checkbox'] {\n    margin: 0 0.5em 0 0em;\n}\n\nlabel > input[type='checkbox'].right {\n    margin: 0 0em 0 0.5em;\n}\n\n/* It's 2022 and we still can't directly style checkboxes!? */\ninput[type='checkbox']:not(:checked) {\n    filter: saturate(0%) invert();\n}\n\ninput[type='range']::-webkit-slider-runnable-track {\n    background: var(--bg);\n    border-radius: 0.5em;\n    vertical-align: middle;\n}\n\nselect {\n    background-color: var(--bg);\n    color: var(--fg);\n}\n\n.controls button {\n    font-size: 85%;\n    margin: 0.25em;\n}\n\n.controls button.normal {\n    font-size: 100%;\n    margin: 0.5em;\n    padding: 0.25em;\n}\n\nbutton, input {\n    border: 1px solid var(--fg);\n}\n\nbutton:hover:enabled {\n    background-color: var(--sbg);\n}\n\nbutton:hover:enabled {\n    filter: drop-shadow(0em 0em 0.33em var(--fg));\n}\n\nbutton:active:enabled {\n    color:var(--bg);\n    background-color: var(--fg);\n}\n\nbutton:disabled {\n    color: var(--sfg);\n    border: 1px solid var(--sfg);\n}\n\n.deemphasize {\n    color: var(--sfg);\n}\n\n.off {\n    color: var(--sbg);\n}\n\n.emphasize {\n    background-color: var(--sbg);\n}\n\n.attention {\n    background-color: var(--fg);\n    color: var(--bg);\n}\n\n.watched {\n    font-weight: bold;\n}\n\n.mark {\n    text-decoration: underline;\n}\n\ntable {\n    background-color: var(--fg);\n    border-spacing: 1px;\n    margin: 0.25em;\n    width: calc(100% - 0.5em);\n}\n\nth, td {\n    background-color: var(--bg);\n    padding: 0.25em;\n}\n\n.achievement {\n    display: flex;\n    flex-direction: row;\n    align-items: center;\n}\n\n.achievement > img {\n    flex-grow: 0;\n    display: block;\n    border: 2px solid var(--fg);\n    margin-right: 0.25em;\n}\n\n.achievement p {\n    text-align: left;\n    margin: 0.5em;\n}\n\n.achievement p.title {\n    font-weight: bold;\n    text-transform: uppercase;\n}\n\n.achievement > img, .toast > img {\n    filter: var(--filter);\n}\n\n.messageBox table {\n    width: auto;\n    margin: auto;\n}\n\nspan.caps {\n    text-transform: uppercase;\n}\n\nth.horizontal {\n    text-align: left;\n}\n\ntd.text {\n    text-align: left;\n}\n\ntd.center {\n    text-align: center;\n}\n\n#asciitable {\n    margin-left: 0px;\n    margin-bottom: 1em;\n}\n\n#asciitable th {\n    background-color: var(--sbg);\n}\n\n#asciitable th:first-child {\n    text-align: right;\n}\n\n.state {\n    overflow-y: auto;\n}\n\n.memory td {\n    padding: 1pt;\n    font-size: 80%;\n}\n\n.memory.running td {\n    cursor: pointer;\n}\n\ntd {\n    text-align: right;\n}\n\nli {\n    margin: 0.5em 0em;\n}\n\nh3 {\n    text-transform: uppercase;\n}\n\n.version {\n    position: absolute;\n    right: 1em;\n    font-size: 80%;\n}\n\n.logo {\n    font-size: 300%;\n    margin-top: 0px;\n    margin-bottom: 0px;\n    text-align: center;\n}\n\n.creditSubtitle {\n    margin-top: 0px;\n    text-align: center;\n}\n\n.creditFooter {\n    margin-top: 1em;\n    padding-top: 1em;\n    border-top: 1px solid var(--fg);\n}\n\npre.licenses {\n    margin: 0px;\n    font-size: 80%;\n    white-space: pre-wrap;\n    overflow-y: auto;\n    max-height: 40em;\n}\n\ntextarea.saveData {\n    overflow-wrap: anywhere;\n    width: 100%;\n    height: 10em;\n}\n\n.chart {\n    background-color: var(--bg);\n    margin: 0.25em;\n    width: 15em;\n    height: 19em;\n}\n\ntable.stats {\n    margin: 0.25em;\n    width: 15em;\n    display: inline-table;\n}\n\nrect {\n    fill: var(--fg);\n}\n\nrect.chartInvisible {\n    opacity: 0;\n}\n\ntext {\n    fill: var(--sfg);\n    font-size: 1.4px;\n    font-family: 'Cascadia Mono', 'Consolas', monospace;\n    font-weight: bold;\n}\n\n.charts {\n    text-align: center;\n}\n\n.chartLeft {\n    text-anchor: start;\n}\n\n.chartRight {\n    text-anchor: end;\n}\n\n.chartTitle {\n    text-anchor: middle;\n    fill: var(--bg);\n}\n\n.chartOverlay {\n    text-anchor: middle;\n    fill: var(--sbg);\n}\n\nline {\n    stroke: var(--sfg);\n    stroke-width: 0.2;\n}\n\n.chartLine {\n    fill: none;\n    stroke: var(--sfg);\n    stroke-width: 0.25;\n}\n\n.chartArrow {\n    fill: var(--fg);\n    stroke: none;\n}\n\n/* Notifications */\n.toast {\n    position: fixed;\n    right: 25px;\n    bottom: 25px;\n    z-index: 55;\n    border: 2px solid var(--fg);\n    padding: 0.5em;\n    background-color: var(--sbg);\n    display: grid;\n    grid-template-columns: auto auto;\n    column-gap: 1em;\n    filter: drop-shadow(0em 0em 0.25em var(--fg));\n\n    animation-name: toastUp;\n    animation-duration: 6s;\n    animation-fill-mode: forwards;\n}\n\n.toast img {\n    border: 1px solid var(--fg);\n}\n\n.toast section {\n    display: flex;\n    flex-direction: column;\n    justify-content: center;\n}\n\n.toast section p {\n    margin-top: 0.5em;\n    margin-bottom: 0px;\n}\n\n.toast header {\n    font-weight: bold;\n}\n\n@media (min-width: 50em) {\n    html, body {\n        height: 100%;\n    }\n\n    #root {\n        height: 100%;\n    }\n\n    .ide {\n        display: flex;\n        flex-direction: row;\n        height: 100%;\n        column-gap: 0.25em;\n    }\n\n    .ioBox {\n        flex-grow: 1;\n        overflow-y: auto;\n    }\n\n    .program {\n        flex-grow: 1;\n        flex-basis: 80%;\n        overflow: auto;\n        height: auto;\n    }\n\n    .state {\n        flex-shrink: 0;\n        overflow-y: scroll;\n    }\n\n    .bootScreen {\n        max-height: 100vh;\n        overflow: auto;\n        text-shadow: 0em 0em 0.5em var(--fg);\n    }\n\n    .memory td {\n        font-size: 100%;\n    }\n\n    .chart {\n        width: 20em;\n        height: 25em;\n    }\n\n    table.stats {\n        width: 20em;\n    }\n}\n\n/* Scrollbar styling */\n* {\n    scrollbar-color: var(--fg) var(--bg);\n}\n\n::-webkit-scrollbar{\n    width: 0.75em;\n    height: 0.75em;\n}\n\n::-webkit-scrollbar-track {\n    background: var(--bg);\n}\n\n::-webkit-scrollbar-thumb {\n    /* Foreground */\n    background: var(--fg);\n}\n\n::-webkit-scrollbar-corner {\n    /* Background */\n    background: var(--bg);\n}\n\n::-webkit-scrollbar-button {\n    display: none;\n}\n\n/* Avoision mini-game */\n.avoisionBox {\n    border: 1px solid var(--fg);\n    max-width: 80vmin;\n    max-height: 80vmin;\n    margin: auto;\n    display: grid;\n}\n\n.avoision {\n    display: block;\n    width: 30em;\n    height: 30em;\n    max-width: 80vmin;\n    max-height: 80vmin;\n    grid-row: 1;\n    grid-column: 1;\n}\n\n.avoisionOverlay {\n    grid-row: 1;\n    grid-column: 1;\n    margin: auto;\n    z-index: 1;\n    font-size: 1.5em;\n    background-color: var(--sbg);\n    border: 1px solid var(--fg);\n    padding: 0.25em;\n    text-transform: uppercase;\n    font-weight: bold;\n    filter: drop-shadow(0em 0em 0.25em var(--fg));\n}\n\n.avoision:focus {\n    outline: none;\n}\n\n.avoisionHeader {\n    display: flex;\n    flex-direction: row;\n    text-transform: uppercase;\n    font-weight: bold;\n    font-size: 1.5em;\n    margin-bottom: 0.25em;\n}\n\n.avoisionPoints {\n    text-align: left;\n    flex-grow: 1;\n}\n\n.avoisionScore {\n    text-align: right;\n    flex-grow: 1;\n}\n\n/* Animations */\n.fadeIn {\n    animation-name: fadeIn;\n    animation-duration: 500ms;\n}\n\n@keyframes fadeOut {\n    0% { opacity: 1.0; }\n    100% { opacity: 0.0; }\n}\n\n@keyframes fadeIn {\n    0% { opacity: 0.0; }\n    100% { opacity: 1.0; }\n}\n\n@keyframes toastUp {\n    0% { transform: translateY(100px); opacity: 0.0; }\n    17% { transform: translateY(0px); opacity: 1.0; }\n    83% { transform: translateY(0px); opacity: 1.0; }\n    100% { opacity: 0.0; }\n}\n", "sic1/client/content/README.md": "Notes on the \"/content\" directory:\n\n# /content/md\nThis directory contains the original Markdown source for in-game story mails, but note that these files are now converted to HTML and stored in react-intl `<FormattedMessage>` elements, with content in \"/content/messages/en.json\".\n\nThese files are converted using `npm run convert:mail`, and then pasted into \"/ts/mail-story.tsx\".\n", "sic1/client/build/build-language-data.tsx": "import { createRenderToString, enumerateLocales, outputFile } from \"./shared\";\nimport { Shared } from \"../ts/shared\";\n\n// Note that English is special-cased as the default language\nconst locales = enumerateLocales().filter(locale => (locale !== \"en\"));\n\nfunction getLanguageNativeName(locale: string): string {\n    const render = createRenderToString(locale);\n    return render(Shared.resources.languageName);\n}\n\nconst languageData =\n`// Automatically generated by build-language-data.ts\nimport en from \"content/messages-compiled/en.json\";\n\nexport const localeToHrefOrMessages = {\n    en,\n${locales.map(locale => `    \"${locale}\": new URL(\"url:../content/messages-compiled/${locale}.json\", import.meta.url).href,`).join(\"\\n\")}\n} as const;\n\nexport const localeToLanguageName = {\n${[\"en\", ...locales].map(locale => `    \"${locale}\": \"${getLanguageNativeName(locale)}\",`).join(\"\\n\")}\n} as const;\n\nexport const localeToManualHref = {\n    en: new URL(\"../content/html/sic1-manual.html\", import.meta.url).href,\n${locales.map(locale => `    \"${locale}\": new URL(\"../content/html/sic1-manual-${locale}.html\", import.meta.url).href,`).join(\"\\n\")}\n}\n`;\n\noutputFile(\"ts/language-data.ts\", languageData);\n", "sic1/client/build/convert-mail.ts": "// Script for converting legacy Markdown-based mail format to localizable HTML (output should be pasted into the array in mail-story.tsx)\nimport { readdirSync, readFileSync } from \"fs\";\nimport { basename, join } from \"path\";\nimport { basicYamlParser } from \"md2jsx\";\nimport { marked } from \"marked\";\n\nconst contentDirectoryName = \"content\";\nconst markdownDirectoryName = \"md\";\nconst filePaths = readdirSync(join(contentDirectoryName, markdownDirectoryName)).map(fileName => join(contentDirectoryName, markdownDirectoryName, fileName))\n    .concat(\"../../sic1-assembly.md\");\n\n// Initialize Marked.js\nmarked.setOptions(marked.getDefaults());\n\nfunction indent(text: string, indent: string): string {\n    return text\n        .split(\"\\n\")\n        .join(`\\n${indent}`);\n}\n\n// Copied from md2jsx\nfunction parseFrontMatter(text: string, parseYaml: (str: string) => Record<string, any>): { metadata: Record<string, any>, markdown: string } {\n    let metadata: Record<string, any> = {};\n    let markdown = text;\n\n    const frontMatterPattern = /^---\\r?\\n(.*?)\\r?\\n---(\\r?\\n|$)/ms;\n    const matches = frontMatterPattern.exec(text);\n    if (matches) {\n        // Front matter found; parse it\n        const frontMatter = matches[1];\n        markdown = text.replace(matches[0], \"\");\n        metadata = parseYaml(frontMatter);\n    }\n\n    return { metadata, markdown };\n}\n\n// Copied from old contacts.ts\nconst Contacts = {\n    onboarding: { name: \"SIC Systems Onboarding\" },\n    taskManagement: { name: \"Automated Task Management\" },\n\n    all: {\n        name: \"All Engineering\",\n    },\n    badManager: {\n        name: \"Don\",\n        lastName: \"Cooper\",\n        title: \"Senior Engineering Lead\",\n    },\n    badManager2: {\n        name: \"Don\",\n        lastName: \"Cooper\",\n        title: \"Principal Engineering Lead\",\n    },\n    badManagerTeam: {\n        name: \"Don's Team\",\n    },\n    goodManager: {\n        name: \"Pat\",\n        lastName: \"Miller\",\n        title: \"Senior Engineering Lead\",\n    },\n    goodManager2: {\n        name: \"Pat\",\n        lastName: \"Miller\",\n    },\n    goodManagerTeam: {\n        name: \"Pat's Team\",\n    },\n    skip: {\n        name: \"Rick\",\n        lastName: \"Wagner\",\n        title: \"Partner Engineering Manager\",\n    },\n    otherSkip: {\n        name: \"Jerin\",\n        lastName: \"Kransky\",\n        title: \"Partner Engineering Manager\",\n    },\n    hr: {\n        name: \"Mary\",\n        lastName: \"Townsend\",\n        title: \"Human Resources\",\n    },\n    flunky: {\n        name: \"Ted\",\n        lastName: \"Philips\",\n        //title: Shared.jobTitles[0].title,\n    },\n    flunky1: {\n        name: \"Ted\",\n        lastName: \"Philips\",\n        //title: Shared.jobTitles[1].title,\n    },\n    mentor: {\n        name: \"Feng\",\n        lastName: \"Lee\",\n        title: \"Senior Engineer\",\n    },\n    assistant: {\n        name: \"Jeffrey\",\n        lastName: \"Young\",\n        title: \"Executive Assistant\",\n    },\n    owner: {\n        name: \"Ilano\",\n        lastName: \"Moscato\",\n        title: \"Benevolent Dictator for Life\",\n    },\n}\n\n// Job title substitution\nconst jobTitlePattern = /\\{\\{jobTitles\\[([0-9]+?)\\].title\\}\\}/;\n\nfunction replaceJobTitles(html: string): (undefined | { html: string, index: number }) {\n    const match = jobTitlePattern.exec(html);\n    if (match) {\n        const [sub, number] = match;\n        return {\n            html: html.replace(sub, \"{jobTitle}\"),\n            index: parseInt(number),\n        }\n    }\n}\n\n// ASCII table handling (kind of an ugly hack, but it works)\nconst asciiTableHtml = `<table id=\"asciitable\">\n<tr><th></th><th>0</th><th>1</th><th>2</th><th>3</th><th>4</th><th>5</th><th>6</th><th>7</th><th>8</th><th>9</th></tr>\n<tr><th>30</th><td>□</td><td>□</td><td title=\"Code: 32, character:  \"> </td><td title=\"Code: 33, character: !\">!</td><td title=\"Code: 34, character: &quot;\">&quot;</td><td title=\"Code: 35, character: #\">#</td><td title=\"Code: 36, character: $\">$</td><td title=\"Code: 37, character: %\">%</td><td title=\"Code: 38, character: &amp;\">&amp;</td><td title=\"Code: 39, character: &#39;\">&#39;</td></tr>\n<tr><th>40</th><td title=\"Code: 40, character: (\">(</td><td title=\"Code: 41, character: )\">)</td><td title=\"Code: 42, character: *\">*</td><td title=\"Code: 43, character: +\">+</td><td title=\"Code: 44, character: ,\">,</td><td title=\"Code: 45, character: -\">-</td><td title=\"Code: 46, character: .\">.</td><td title=\"Code: 47, character: /\">/</td><td title=\"Code: 48, character: 0\">0</td><td title=\"Code: 49, character: 1\">1</td></tr>      \n<tr><th>50</th><td title=\"Code: 50, character: 2\">2</td><td title=\"Code: 51, character: 3\">3</td><td title=\"Code: 52, character: 4\">4</td><td title=\"Code: 53, character: 5\">5</td><td title=\"Code: 54, character: 6\">6</td><td title=\"Code: 55, character: 7\">7</td><td title=\"Code: 56, character: 8\">8</td><td title=\"Code: 57, character: 9\">9</td><td title=\"Code: 58, character: :\">:</td><td title=\"Code: 59, character: ;\">;</td></tr>      \n<tr><th>60</th><td title=\"Code: 60, character: &lt;\">&lt;</td><td title=\"Code: 61, character: =\">=</td><td title=\"Code: 62, character: &gt;\">&gt;</td><td title=\"Code: 63, character: ?\">?</td><td title=\"Code: 64, character: @\">@</td><td title=\"Code: 65, character: A\">A</td><td title=\"Code: 66, character: B\">B</td><td title=\"Code: 67, character: C\">C</td><td title=\"Code: 68, character: D\">D</td><td title=\"Code: 69, character: E\">E</td></tr>\n<tr><th>70</th><td title=\"Code: 70, character: F\">F</td><td title=\"Code: 71, character: G\">G</td><td title=\"Code: 72, character: H\">H</td><td title=\"Code: 73, character: I\">I</td><td title=\"Code: 74, character: J\">J</td><td title=\"Code: 75, character: K\">K</td><td title=\"Code: 76, character: L\">L</td><td title=\"Code: 77, character: M\">M</td><td title=\"Code: 78, character: N\">N</td><td title=\"Code: 79, character: O\">O</td></tr>\n<tr><th>80</th><td title=\"Code: 80, character: P\">P</td><td title=\"Code: 81, character: Q\">Q</td><td title=\"Code: 82, character: R\">R</td><td title=\"Code: 83, character: S\">S</td><td title=\"Code: 84, character: T\">T</td><td title=\"Code: 85, character: U\">U</td><td title=\"Code: 86, character: V\">V</td><td title=\"Code: 87, character: W\">W</td><td title=\"Code: 88, character: X\">X</td><td title=\"Code: 89, character: Y\">Y</td></tr>\n<tr><th>90</th><td title=\"Code: 90, character: Z\">Z</td><td title=\"Code: 91, character: [\">[</td><td title=\"Code: 92, character: \\\\\">\\\\</td><td title=\"Code: 93, character: ]\">]</td><td title=\"Code: 94, character: ^\">^</td><td title=\"Code: 95, character: _\">_</td><td title=\"Code: 96, character: \\`\">\\`</td><td title=\"Code: 97, character: a\">a</td><td title=\"Code: 98, character: b\">b</td><td title=\"Code: 99, character: c\">c</td></tr>\n<tr><th>100</th><td title=\"Code: 100, character: d\">d</td><td title=\"Code: 101, character: e\">e</td><td title=\"Code: 102, character: f\">f</td><td title=\"Code: 103, character: g\">g</td><td title=\"Code: 104, character: h\">h</td><td title=\"Code: 105, character: i\">i</td><td title=\"Code: 106, character: j\">j</td><td title=\"Code: 107, character: k\">k</td><td title=\"Code: 108, character: l\">l</td><td title=\"Code: 109, character: m\">m</td></tr>\n<tr><th>110</th><td title=\"Code: 110, character: n\">n</td><td title=\"Code: 111, character: o\">o</td><td title=\"Code: 112, character: p\">p</td><td title=\"Code: 113, character: q\">q</td><td title=\"Code: 114, character: r\">r</td><td title=\"Code: 115, character: s\">s</td><td title=\"Code: 116, character: t\">t</td><td title=\"Code: 117, character: u\">u</td><td title=\"Code: 118, character: v\">v</td><td title=\"Code: 119, character: w\">w</td></tr>\n<tr><th>120</th><td title=\"Code: 120, character: x\">x</td><td title=\"Code: 121, character: y\">y</td><td title=\"Code: 122, character: z\">z</td><td title=\"Code: 123, character: &#123;\">&#123;</td><td title=\"Code: 124, character: |\">|</td><td title=\"Code: 125, character: &#125;\">&#125;</td><td title=\"Code: 126, character: ~\">~</td><td>□</td><td>□</td><td>□</td></tr>\n</table>`;\n\nfunction replaceAsciiTable(html: string): undefined | string {\n    const replaced = html.replace(asciiTableHtml, \"{asciiTable}\");\n    return (html === replaced) ? undefined : replaced;\n}\n\n// Convert a single Markdown file\nfunction convert(solvedCount: number, index: number, markdownWithFrontMatter: string, isMail: boolean): string {\n    const { metadata, markdown } = parseFrontMatter(markdownWithFrontMatter, basicYamlParser);\n    const name = `s${solvedCount}_${index}`;\n\n    // SIC-1 Assembly Manual doesn't specify metadata, so insert it here\n    if (solvedCount === 0 && index === 0) {\n        metadata.from = \"onboarding\";\n        metadata.subject = \"SIC-1 Reference Manual\";\n        metadata.actions = [\"manualInNewWindow\"];\n    }\n\n    const from = `Contacts.${metadata.from}`;\n    let html = marked(markdown);\n\n    // Extract the ASCII table first, since it has a lot of escape codes\n    const asciiTableReplaced = replaceAsciiTable(html);\n    if (asciiTableReplaced) {\n        html = asciiTableReplaced;\n    }\n\n    html = html\n        .replace(/&#39;/g, \"'\")\n        .replace(/'/g, \"''\")\n        .replace(/\\\\/g, \"\\\\\\\\\")\n        .replace(/&quot;/g, \"\\\"\")\n        .replace(/&amp;/g, \"&\")\n        .replace(/\\{\\{from.name\\}\\}/g, metadata.from ? Contacts[metadata.from].name : \"\")\n        .replace(/\\{\\{self.name\\}\\}/g, \"{selfName}\")\n        .replace(/(<h[1-5]) id=[^>]*?>/g, \"$1>\")\n        .replace(/`/g, \"\\\\`\")\n        ;\n\n    const jobTitleInfo = replaceJobTitles(html);\n    if (jobTitleInfo) {\n        html = jobTitleInfo.html;\n    }\n\n    const extra = Object.entries(metadata)\n        .filter(([key]) => (key !== \"from\" && key !== \"subject\"))\n        .map(([key, value]) => `\\n        ${key}: ${indent(JSON.stringify(value, null, 4), \"        \")},`)\n        .join(\"\");\n\n    return `\n    {\n        id: \"${name}\",\n        solvedCount: ${solvedCount},\n        from: ${from},\n        subject: <FormattedMessage\n            id=\"mail${name}Subject\"\n            description=\"Subject line for story mail ${name}\"\n            defaultMessage=\"${metadata.subject}\"\n            />,\n        create: (context) => <FormattedMessage\n            id=\"mail${name}Content\"\n            description=\"HTML content for story mail ${name}\"\n            defaultMessage={\\`${html}\\`}${isMail ? `\n            values={{ selfName: context.self.name${jobTitleInfo ? `, jobTitle: Shared.jobTitles[${jobTitleInfo.index}].title` : \"\"} }}`\n                : (asciiTableReplaced\n                    ? \"\\n            values={{ asciiTable }}\"\n                    : \"\")}\n            />,${extra}\n    },\n`;\n}\n\n// Convert each Markdown file\nconst nameSubstitutions = {\n    \"sic1-assembly\": \"s0_0\",\n    \"dev-environment\": \"s0_1\",\n    s0: \"s0_2\",\n};\n\nconst solvedToIndex: string[][] = [];\n\nfor (const filePath of filePaths) {\n    if (filePath.endsWith(\".md\")) {\n        const markdown = readFileSync(filePath, { encoding: \"utf8\" });\n        const fileNameWithoutExtension = basename(filePath).replace(/\\.md$/, \"\");\n        const isMail = /^s[0-9]+/.test(fileNameWithoutExtension);\n\n        const name = nameSubstitutions[fileNameWithoutExtension]\n            ?? (/_[0-9]+$/.test(fileNameWithoutExtension)\n                ? fileNameWithoutExtension\n                : `${fileNameWithoutExtension}_0`);\n        \n        // Add to index\n        const [_, solvedCountString, indexString] = /^s([0-9]+)_([0-9]+)$/.exec(name);\n        const solvedCount = parseInt(solvedCountString);\n        const index = parseInt(indexString);\n\n        if (!solvedToIndex[solvedCount]) {\n            solvedToIndex[solvedCount] = [];\n        }\n\n        solvedToIndex[solvedCount][index] = convert(solvedCount, index, markdown, isMail);\n    }\n}\n\nconsole.log(\"// Generated by convert-mail.ts\");\nconsole.log(\"export const storyMails = [\");\nfor (let i = 0; i < solvedToIndex.length; i++) {\n    console.log(\"    [\");\n    const index = solvedToIndex[i];\n    for (let j = 0; j < index.length; j++) {\n        const mail = index[j];\n        console.log(mail);\n    }\n    console.log(\"    ],\");\n}\nconsole.log(\"];\");\n", "sic1/client/build/shared.tsx": "import React from \"react\";\nimport ReactDOM from \"react-dom/server\";\nimport { readFileSync, readdirSync, writeFileSync } from \"fs\";\nimport { join } from \"path\";\nimport { IntlConfig, IntlProvider } from \"react-intl\";\nimport { Shared } from \"../ts/shared\";\n\nexport const contentDirectoryName = \"content\";\nexport const messagesDirectoryName = \"messages\";\nexport const messagesCompiledDirectoryName = \"messages-compiled\";\nexport const translationsZipFileName = \"translations.zip\";\n\nexport function outputFile(outputPath: string, content: string, inputPath?: string): void {\n    writeFileSync(outputPath, content);\n    console.log(`${inputPath ?? \"\"} => ${outputPath}`);\n}\n\n// Detect locales by presence of *.json files in \"content/messages/\" directory\nconst messagesFilePattern = /^(.*?)\\.json$/;\nexport function enumerateLocales(): string[] {\n    const result: string[] = [];\n    for (const item of readdirSync(join(contentDirectoryName, messagesDirectoryName))) {\n        const matches = messagesFilePattern.exec(item);\n        if (matches) {\n            result.push(matches[1]);\n        }\n    }\n\n    return result;\n}\n\nfunction loadMessages(locale: string): IntlConfig[\"messages\"] {\n    const messages = JSON.parse(readFileSync(join(contentDirectoryName, messagesCompiledDirectoryName, `${locale}.json`), { encoding: \"utf8\" }));\n    return messages as IntlConfig[\"messages\"];\n}\n\nexport function createRenderToString(locale: string): (node: React.ReactNode) => string {\n    const messages = loadMessages(locale);\n    const render = (node: React.ReactNode): string => {\n        return ReactDOM.renderToString(<IntlProvider\n            locale={locale}\n            messages={messages}\n            {...Shared.intlProviderOptions}\n            >\n                {node}\n            </IntlProvider>);\n    }\n\n    return render;\n}\n", "sic1/client/build/translations-download.ts": "import { readFileSync, writeFileSync } from \"fs\";\nimport { translationsZipFileName } from \"./shared\";\n\nconst protocol = \"https\";\nconst host = \"api.crowdin.com\";\nconst projectId = 639736;\nconst pollingPeriodMS = 1000;\n\ninterface BuildProjectData {\n    id: number;\n    status?: string;\n    progress?: number;\n}\n\ninterface DownloadBuildData {\n    url: string;\n}\n\nasync function sleepAsync(ms: number): Promise<void> {\n    return new Promise(resolve => setTimeout(resolve, ms));\n}\n\n(async () => {\n    const token = readFileSync(\"build/token.txt\", { encoding: \"utf8\" });\n\n    async function callAsync<T>(url: string, requestInit?: RequestInit): Promise<T> {\n        const result = await fetch(url, {\n            ...requestInit,\n            headers: {\n                ...(requestInit?.headers ?? {}),\n                Authorization: `Bearer ${token}`,\n            },\n        });\n\n        if (!result.ok) {\n            throw `Fetch failed (${result.status}): ${url}`;\n        }\n\n        const data: T = (await result.json()).data;\n        return data;\n    }\n\n    // Start a build\n    console.log(\"Starting build...\");\n    let data = await callAsync<BuildProjectData>(`${protocol}://${host}/api/v2/projects/${projectId}/translations/builds`, {\n        method: \"POST\",\n        headers: {\n            \"Content-Type\": \"application/json\",\n        },\n        body: JSON.stringify({\n            skipUntranslatedStrings: true,\n        }),\n    });\n\n    const buildId = data.id;\n    console.log(`Build id: ${buildId}`);\n\n    // Wait for completion\n    while (console.log(`Build progress: ${data.progress ?? \"unknown\"}`), data.status !== \"finished\") {\n        await sleepAsync(pollingPeriodMS);\n        data = await callAsync<BuildProjectData>(`${protocol}://${host}/api/v2/projects/${projectId}/translations/builds/${buildId}`);\n    }\n\n    // Download\n    const url = (await callAsync<DownloadBuildData>(`${protocol}://${host}/api/v2/projects/${projectId}/translations/builds/${buildId}/download`)).url;\n\n    console.log(\"Downloading...\");\n    const blob = await (await fetch(url)).blob();\n\n    console.log(\"Saving to disk...\");\n    writeFileSync(translationsZipFileName, Buffer.from(await blob.arrayBuffer()));\n})();\n", "sic1/client/build/translations-extract.ts": "import AdmZip from \"adm-zip\";\nimport { readFileSync } from \"fs\";\nimport { basename } from \"path\";\nimport { outputFile, translationsZipFileName } from \"./shared\";\n\nconst localeSubstitutions = {\n    \"zh-CN\": \"zh-Hans\",\n    \"zh-TW\": \"zh-Hant\",\n};\n\nconst zip = new AdmZip(readFileSync(translationsZipFileName));\nfor (const entry of zip.getEntries()) {\n    const name = basename(entry.entryName);\n    const matches = /^(.*)\\.json$/.exec(name);\n    if (matches) {\n        const rawLocale = matches[1];\n        const locale = localeSubstitutions[rawLocale] ?? rawLocale;\n\n        const originalJson = JSON.parse(entry.getData().toString()) as Record<string, { defaultMessage: string, description?: string }>;\n        const json = {};\n        for (const [stringId, info] of Object.entries(originalJson)) {\n            const { defaultMessage } = info;\n            json[stringId] = { defaultMessage };\n        }\n\n        const text = JSON.stringify(json, undefined, 4);\n\n        outputFile(`content/messages/${locale}.json`, text, translationsZipFileName);\n    }\n}\n", "sic1/client/build/tsconfig.json": "{\n    \"compilerOptions\": {\n        \"jsx\": \"react\",\n        \"esModuleInterop\": true,\n        \"noEmit\": true\n    }\n}", "sic1/client/build/build-manual.tsx": "import { join } from \"path\";\nimport { storyMails } from \"../ts/mail-story\";\nimport { MailContext } from \"../ts/mail-shared\";\nimport { Shared } from \"../ts/shared\";\nimport { contentDirectoryName, createRenderToString, enumerateLocales, outputFile } from \"./shared\";\n\nconst htmlDirectoryName = \"html\";\nconst htmlDirectoryPath = join(contentDirectoryName, htmlDirectoryName);\n\nconst storyMailContents = [].concat(...storyMails);\n\nfor (const locale of enumerateLocales()) {\n    const suffix = (locale === \"en\") ? \"\" : `-${locale}`;\n    const sic1ManualPath = join(htmlDirectoryPath, `sic1-manual${suffix}.html`);\n    const render = createRenderToString(locale);\n    const content = [\"s0_0\", \"s0_1\"]\n        .map(name => render(storyMailContents.find((mail) => (mail.id === name)).create({} as MailContext)))\n        .join(\"\\n\");\n\n    const sic1ManualContent = `<!DOCTYPE html>\n<html lang=\"${locale}\">\n<head>\n<meta charset=\"utf-8\">\n<title>${render(Shared.resources.manualTitle)}</title>\n<meta name=\"viewport\" content=\"width=device-width, initial-scale=1, shrink-to-fit=no\" />\n<style>\n:root { color-scheme: light dark; }\n\n#root {\n    max-width: 50em;\n    margin: auto;\n    font-family: sans-serif;\n}\n\nh1, h2, h3, h4, h5 { text-transform: uppercase; }\nheader h1 { margin-bottom: 0; }\nheader p { margin-top: 0; }\nheader { margin-bottom: 2em; }\n\ncode { font-family: sans-serif; font-weight: bold; text-transform: none; }\npre {\n    font-size: 100%;\n    padding: 0.25em;\n    border: 1px solid;\n}\n\npre code {\n    font-family: monospace;\n}\n\ntable, th, td {\n    border: 1px solid;\n    border-collapse: collapse;\n    padding: 0.25em;\n}\n\ntd { text-align: center; }\nth:first-child { text-align: right; }\n\n</style>\n</head>\n<body>\n<div id=\"root\">\n<header>\n${render(Shared.resources.manualHeading)}\n</header>\n${content}\n</div>\n</body>\n</html>\n`;\n\n    outputFile(sic1ManualPath, sic1ManualContent);\n}\n", "sic1/client/ts/mail.tsx": "import React from \"react\";\nimport { puzzleFlatArray } from \"../../shared/puzzles\";\nimport { Inbox, Sic1DataManager } from \"./data-manager\";\nimport { createPuzzleCharts } from \"./puzzle-list\";\nimport { PuzzleFriendLeaderboardPromises } from \"./service\";\nimport { Contacts } from \"./contacts\";\nimport { storyMails } from \"./mail-story\";\nimport { Mail } from \"./mail-shared\";\nimport { FormattedMessage } from \"react-intl\";\nimport { Shared } from \"./shared\";\n\n// Session stats: these are stats that are shown in \"task completed\" mails. They override the \"best\" results from\n// localStorage with the latest results from this session.\nconst puzzleTitleToSessionStats: {\n    [title: string]: {\n        cycles: number,\n        bytes: number,\n\n        // Also support overriding the friend leaderboard loading promises to support the \"update+retrieve\" scenario\n        leaderboardPromises?: PuzzleFriendLeaderboardPromises,\n    }\n} = {};\n\nexport function updateSessionStats(puzzleTitle: string, cycles: number, bytes: number, leaderboardPromises?: PuzzleFriendLeaderboardPromises): void {\n    puzzleTitleToSessionStats[puzzleTitle] = { cycles, bytes, leaderboardPromises };\n}\n\nconst puzzleMails: Mail[] = [];\nfor (let i = 0; i < puzzleFlatArray.length; i++) {\n    const puzzle = puzzleFlatArray[i];\n\n    puzzleMails.push({\n        id: puzzle.title,\n\n        // Note: This solved count isn't 100% accurate because puzzles can be solved out of order, but it is only\n        // used for displaying job titles in mail, so it's not a big deal\n        solvedCount: i + 1,\n\n        loadType: \"puzzle\",\n\n        from: Contacts.taskManagement,\n        unimportant: true,\n        create: () => {\n            const title = puzzle.title;\n            let stats = puzzleTitleToSessionStats[title];\n            if (!stats) {\n                // No new stats during this session; default to saved stats\n                const puzzleData = Sic1DataManager.getPuzzleData(title);\n                stats = { cycles: puzzleData.solutionCycles, bytes: puzzleData.solutionBytes };\n            }\n\n            const { cycles, bytes, leaderboardPromises } = stats;\n            return <>\n                <p>\n                    <FormattedMessage\n                        id=\"mailViewerTaskCompleted\"\n                        description=\"Markup shown for a 'task completed successfully' mail, indicating the program was correct\"\n                        defaultMessage=\"Well done! Your program produced the correct output. Thanks for your contribution to SIC Systems!\"\n                        />\n                </p>\n                {(cycles && bytes)\n                    ? <>\n                        <p>{Shared.resources.taskStatistics}</p>\n                        {createPuzzleCharts(title, cycles, bytes, leaderboardPromises)}\n                    </>\n                    : null\n                }\n            </>;\n        },\n    });\n}\n\nconst triggeredMails: Mail[] = [\n];\n\nconst idToMail: Record<string, Mail> = {};\n\nfunction getIdForStoryMail(solvedCount: number, index: number): string {\n    return `s${solvedCount}_${index}`;\n}\n\n// Triggered mails\nfor (const mail of triggeredMails) {\n    idToMail[mail.id] = mail;\n}\n\n// Add story mail\nfor (const storyMailIndex of storyMails) {\n    for (const storyMail of storyMailIndex) {\n        idToMail[storyMail.id] = storyMail;\n    }\n}\n\n// Puzzle mails are added once the relevant puzzle is solved\nfor (let i = 0; i < puzzleMails.length; i++) {\n    const puzzleMail = puzzleMails[i];\n    idToMail[puzzleMail.id] = puzzleMail;\n}\n\n// Helpers for looking up mail ids in an existing Inbox\nexport const mails = idToMail;\n\ntype InboxIds = { [id: string]: boolean };\n\nfunction getInboxIds(inbox: Inbox): InboxIds {\n    const inboxIds: { [id: string]: boolean } = {};\n    for (const { id } of inbox) {\n        inboxIds[id] = true;\n    }\n    return inboxIds;\n}\n\n// Helper for inserting missing mails\ntype MailOrdering = { [id: string]: number };\nfunction insertMailInOrder(inbox: Inbox, id: string, order: MailOrdering): void {\n    // Add *missing* mails in order, marked as read\n    const position = order[id];\n    const indexOfNextMail = inbox.findIndex(mail => (order[mail.id] > position));\n    const entry = { id, read: true };\n    if (indexOfNextMail < 0) {\n        inbox.push(entry);\n    } else {\n        const nextEntry = inbox[indexOfNextMail];\n        inbox.splice(indexOfNextMail, 1, entry, nextEntry);\n    }\n}\n\nexport function migrateInbox(): void {\n    let updated = false;\n    const data = Sic1DataManager.getData();\n    const inbox = data.inbox ?? [];\n    \n    // Check for, and remove, erroneous entries\n    for (let i = 0; i < inbox.length; i++) {\n        const id = inbox[i].id;\n        if (!mails[id]) {\n            updated = true;\n            inbox.splice(i, 1);\n            --i;\n        }\n    }\n\n    // Check for missing mails\n    const inboxIds = getInboxIds(inbox);\n    let missing = false;\n    for (let i = 0; i < puzzleFlatArray.length; i++) {\n        if (Sic1DataManager.getPuzzleData(puzzleFlatArray[i].title).solved) {\n            if (!inboxIds[puzzleMails[i].id]) {\n                missing = true;\n            }\n        }\n    }\n\n    for (let i = 0; i < storyMails.length && i <= data.solvedCount; i++) {\n        const mailList = storyMails[i];\n        if (mailList) {\n            for (const mail of mailList) {\n                if (!inboxIds[mail.id]) {\n                    missing = true;\n                }\n            }\n        }\n    }\n\n    if (missing) {\n        // There are missing mails. Algorithm to insert mails in a reasonable order:\n        //\n        // 1. Remove story mails\n        // 2. Insert any missing puzzle mails\n        // 3. Add back all reached story mails, in their proper location\n        updated = true;\n\n        // Create lookup table for story mails\n        const isStoryMail: { [id: string]: boolean } = {};\n        for (const mailList of storyMails) {\n            if (mailList) {\n                for (const mail of mailList) {\n                    isStoryMail[mail.id] = true;\n                }\n            }\n        }\n\n        // Create order for puzzle mails\n        const puzzleMailNaturalOrdering: MailOrdering = {};\n        for (let i = 0; i < puzzleMails.length; i++) {\n            puzzleMailNaturalOrdering[puzzleMails[i].id] = i;\n        }\n\n        // Remove story mails\n        for (let i = 0; i < inbox.length; i++) {\n            if (isStoryMail[inbox[i].id]) {\n                inbox.splice(i, 1);\n                --i;\n            }\n        }\n\n        // Insert missing puzzle mails, in order\n        for (let i = 0; i < puzzleFlatArray.length; i++) {\n            const { id } = puzzleMails[i];\n            if (Sic1DataManager.getPuzzleData(puzzleFlatArray[i].title).solved) {\n                if (!inboxIds[id]) {\n                    insertMailInOrder(inbox, id, puzzleMailNaturalOrdering);\n                }\n            }\n        }\n\n        // Note the *actual* order of puzzle mails\n        const puzzleMailActualOrdering: MailOrdering = {};\n        for (let i = 0; i < inbox.length; i++) {\n            puzzleMailActualOrdering[inbox[i].id] = i;\n        }\n\n        // Add back all reached story mails, in their proper location\n        for (let i = 0; i < storyMails.length && i <= data.solvedCount; i++) {\n            const mailList = storyMails[i];\n            if (mailList) {\n                // Find the correct position\n                let position = inbox.findIndex(mail => (puzzleMailActualOrdering[mail.id] === i));\n                if (position < 0) {\n                    position = inbox.length;\n                }\n\n                inbox.splice(position, 0, ...mailList.map(mail => ({ id: mail.id, read: true })));\n            }\n        }\n    }\n\n    if (updated) {\n        data.inbox = inbox;\n        Sic1DataManager.saveData();\n    }\n}\n\nexport function addMailForPuzzle(puzzleTitle: string): void {\n    const puzzleFlatArrayIndex = puzzleFlatArray.findIndex(puzzle => (puzzle.title === puzzleTitle));\n    const data = Sic1DataManager.getData();\n    const inbox = data.inbox!;\n    const inboxIds = getInboxIds(inbox);\n    let updated = false;\n\n    // Add puzzle mail, if needed\n    const puzzleMail = puzzleMails[puzzleFlatArrayIndex];\n    if (!inboxIds[puzzleMail.id]) {\n        updated = true;\n        inbox.push({\n            id: puzzleMail.id,\n            read: false,\n        });\n    }\n\n    // Add story mails, if needed\n    const mailList = storyMails[data.solvedCount];\n    if (mailList) {\n        for (const mail of mailList) {\n            const { id } = mail;\n            if (!inboxIds[id]) {\n                updated = true;\n                inbox.push({ id, read: false });\n            }\n        }\n    }\n\n    if (updated) {\n        Sic1DataManager.saveData();\n    }\n}\n\nexport function addTriggeredMail(id: string): void {\n    const inbox = Sic1DataManager.getData().inbox!;\n    if (inbox.findIndex(m => m.id === id) === -1) {\n        inbox.push({ id, read: false });\n        Sic1DataManager.saveData();\n    }\n}\n\nexport function ensureMailRead(mail: Mail, read = true): void {\n    const { id } = mail;\n    const data = Sic1DataManager.getData();\n    const inbox = data.inbox ?? [];\n    const index = inbox.findIndex(m => m.id === id);\n\n    if (index >= 0) {\n        if (inbox[index].read !== read) {\n            inbox[index].read = read;\n            Sic1DataManager.saveData();\n        }\n    }\n}\n\nexport function ensureSolutionStatsMailUnread(puzzleTitle: string): void {\n    const puzzleIndex = puzzleFlatArray.findIndex(p => p.title === puzzleTitle);\n    ensureMailRead(puzzleMails[puzzleIndex], false);\n}\n\nexport function hasUnreadMail(): boolean {\n    const { inbox } = Sic1DataManager.getData();\n    return inbox.findIndex(m => !m.read) !== -1;\n}\n", "sic1/client/ts/colors.ts": "export interface Color {\n    // All on range 0 - 1\n    red: number;\n    green: number;\n    blue: number;\n    opacity?: number;\n}\n\nconst colorVariables = [\n    // Required\n    \"fg\",   // Foreground\n    \"sbg\",  // Message box background\n    \"bg\",   // Background\n\n    // Optional\n    \"sfg\",  // Deemphasized text\n] as const;\n\nexport type ColorVariable = typeof colorVariables[number];\n\nconst colorVariableFallbacks = {\n    sfg: \"sbg\",\n} as const;\n\nconst lime = { red: 0, green: 1, blue: 0 };\nconst green = { red: 0, green: 0.5, blue: 0 };\nconst black = { red: 0, green: 0, blue: 0 };\n\nconst white = { red: 1, green: 1, blue: 1 };\nconst light = { red: 0.93, green: 0.93, blue: 0.93 };\nconst darkGray = { red: 0.41, green: 0.41, blue: 0.41 };\nconst lightGray = { red: 0.75, green: 0.75, blue: 0.75 };\n\nconst brightP1 = { red: 0.25, green: 1, blue: 0 };\nconst darkP1 = { red: 0.13, green: 0.5, blue: 0 };\nconst phosphorBackground = { red: 0.05, green: 0.05, blue: 0.05 };\n\nconst brightP3 = { red: 1, green: 0.69, blue: 0 };\nconst darkP3 = { red: 0.4, green: 0.27, blue: 0 };\n\nconst colorSchemes = {\n    \"Default\": {\n        fg: lime,\n        sbg: green,\n        bg: black,\n    },\n    \"White on Black\": {\n        fg: light,\n        sbg: darkGray,\n        bg: black,\n        filter: \"grayscale(1)\",\n    },\n    \"Black on White\": {\n        fg: black,\n        sfg: darkGray,\n        sbg: lightGray,\n        bg: white,\n        filter: \"grayscale(1) invert()\",\n    },\n    \"Green Phosphor\": {\n        fg: brightP1,\n        sbg: darkP1,\n        bg: phosphorBackground,\n        filter: \"contrast(0.9)\",\n    },\n    \"Amber Phosphor\": {\n        fg: brightP3,\n        sbg: darkP3,\n        bg: phosphorBackground,\n        filter: \"sepia(1) saturate(5) contrast(0.9)\", // sepia() is apparently amber!\n    },\n} as const;\n\nfunction setCssVariable(variable: string, value: string): void {\n    document.documentElement.style.setProperty(`--${variable}`, value);\n}\n\nexport type ColorScheme = keyof typeof colorSchemes;\nexport const colorSchemeNames = Object.keys(colorSchemes);\n\nexport function isColorScheme(colorSchemeString: string): colorSchemeString is ColorScheme {\n    return !!colorSchemes[colorSchemeString];\n}\n\nexport function colorToCssColor(color: Color): string {\n    const { red, green, blue, opacity } = color;\n    return `rgba(${Math.round(red * 255)}, ${Math.round(green * 255)}, ${Math.round(blue * 255)}, ${opacity ?? 1})`;\n}\n\nexport function getColor(colorSchemeName: ColorScheme, variable: string): Color {\n    const colorScheme = colorSchemes[colorSchemeName];\n    return colorScheme[variable] ?? colorScheme[colorVariableFallbacks[variable]];\n}\n\nexport function applyColorScheme(colorSchemeName: ColorScheme): void {\n    const scheme = colorSchemes[colorSchemeName];\n    if (scheme) {\n        for (const variable of colorVariables) {\n            const color = getColor(colorSchemeName, variable);\n            if (color) {\n                setCssVariable(variable, colorToCssColor(color));\n            }\n        }\n\n        setCssVariable(\"filter\", scheme[\"filter\"] ?? \"none\");\n    }\n}\n", "sic1/client/ts/ide-memory.tsx": "import React from \"react\";\nimport { Constants } from \"../../../lib/src/sic1asm\";\nimport { NumberSpan } from \"./ide-number-span\";\nimport { FormattedMessage } from \"react-intl\";\n\nexport interface Sic1MemoryProps {\n    hasStarted: boolean;\n    currentAddress: number | null;\n    memoryMap: number[][];\n    memory: { [address: number]: number };\n    watchedAddresses: Set<number>;\n    highlightAddress?: number;\n\n    onSetHighlightAddress: (address?: number) => void;\n    onToggleWatch: (address: number) => void;\n}\n\nexport class Sic1Memory extends React.Component<Sic1MemoryProps> {\n    public render(): React.ReactNode {\n        return <table className={`memory${this.props.hasStarted ? \" running\" : \"\"}`}><thead><tr><th colSpan={16}>\n            <FormattedMessage\n                id=\"headerStateMemory\"\n                description=\"Header for the 'memory' table, which shows the hexadecimal values of all 256 bytes of the emulator's memory\"\n                defaultMessage=\"Memory\"\n                />\n        </th></tr></thead>\n        <tbody>\n        {\n            this.props.memoryMap.map((row, rowIndex) => <tr key={rowIndex}>{row.map(index =>\n                <td key={index} className={`${\n                    (this.props.hasStarted && (this.props.highlightAddress === index))\n                        ? \"attention\"\n                        : ((this.props.currentAddress !== null && index >= this.props.currentAddress && index < this.props.currentAddress + Constants.subleqInstructionBytes)\n                            ? \"emphasize\"\n                            : \"\")\n                }${\n                    this.props.watchedAddresses.has(index) ? \" watched\" : \"\"\n                }`}\n\n                    onMouseEnter={() => this.props.onSetHighlightAddress(index)}\n                    onMouseLeave={() => this.props.onSetHighlightAddress(undefined)}\n                    onClick={this.props.hasStarted ? () => this.props.onToggleWatch(index) : undefined}\n                >\n                    <NumberSpan format=\"hex\" value={this.props.memory[index]} />\n                </td>)}</tr>)\n        }\n        </tbody>\n        </table>;\n    }\n}", "sic1/client/ts/button-result.tsx": "import React from \"react\";\nimport { Button, ButtonProps } from \"./button\";\n\ninterface ButtonWithResultProps extends ButtonProps {\n    onClickAsync: () => Promise<void>;\n    successMessage: string;\n    errorMessage: string;\n}\n\nexport class ButtonWithResult extends React.Component<ButtonWithResultProps, { result?: boolean }> {\n    constructor(props) {\n        super(props);\n        \n        this.state = {};\n    }\n\n    private start(): void {\n        const promise = this.props.onClickAsync();\n        if (promise) {\n            promise\n                .then(() => this.setState({ result: true }))\n                .catch(() => this.setState({ result: false }))\n            ;\n        } else {\n            this.setState({ result: false });\n        }\n    }\n\n    public render(): React.ReactNode {\n        const { children, successMessage, errorMessage, onClickAsync, ...rest } = this.props;\n        return <>\n            <p>{(this.state.result === undefined)\n                ? <>&nbsp;</>\n                : (this.state.result\n                    ? successMessage\n                    : errorMessage)\n            }</p>\n            <Button {...rest} onClick={() => this.start()}>{children}</Button>\n        </>;\n    }\n}\n", "sic1/client/ts/ide-watch.tsx": "import React from \"react\";\nimport { Assembler, Variable } from \"../../../lib/src/sic1asm\";\nimport { NumberSpan } from \"./ide-number-span\";\nimport { FormattedMessage } from \"react-intl\";\n\nexport interface Sic1WatchProps {\n    hasStarted: boolean;\n    memory: { [address: number]: number };\n    variables: Variable[];\n    variableToAddress: { [label: string]: number };\n    watchedAddresses: Set<number>;\n    highlightAddress?: number;\n\n    onSetHighlightAddress: (address?: number) => void;\n}\n\nexport class Sic1Watch extends React.Component<Sic1WatchProps> {\n    private truncateIfNeeded(text: string, length: number): React.ReactNode {\n        if (text.length > length) {\n            return <span title={text}>{text.slice(0, length - 3)}...</span>;\n        } else {\n            return text;\n        }\n    }\n\n    public render(): React.ReactNode {\n        const customWatches = Array.from(this.props.watchedAddresses.values()).map(address => ({\n            key: `custom${address}`,\n            label: <>\n                <FormattedMessage\n                    id=\"labelWatchedAddress\"\n                    description=\"Text shown in the 'variables' table for a manually watched address, i.e. an address the user manually highlighted\"\n                    defaultMessage=\"Address {address}\"\n                    values={{ address: <NumberSpan format=\"decimal\" value={address} /> }}\n                    />\n                </>,\n            address,\n            value: Assembler.unsignedToSigned(this.props.memory[address] ?? 0),\n        }));\n\n        const variableWatches = this.props.variables.map(v => ({\n            key: v.label,\n            label: <>{this.truncateIfNeeded(v.label, 25)} (<NumberSpan format=\"decimal\" value={this.props.variableToAddress[v.label] ?? 0} />)</>,\n            address: this.props.variableToAddress[v.label] ?? 0,\n            value: v.value,\n        }));\n\n        const watches = [...customWatches, ...variableWatches];\n\n        return <table>\n            <thead><tr>\n                <th className=\"width100inline\">\n                    <FormattedMessage\n                        id=\"headerVariableLabel\"\n                        description=\"Header for the 'label' column of the variable/watch table, showing name/label and memory address of variables while debugging\"\n                        defaultMessage=\"Label (Address)\"\n                        />\n                </th>\n                <th>\n                    <FormattedMessage\n                        id=\"headerVariableValue\"\n                        description=\"Header for the 'value' column of the variable/watch table, showing the value of variables while debugging\"\n                        defaultMessage=\"Value\"\n                        />\n                </th>\n            </tr></thead>\n            <tbody>\n                {watches.length > 0\n                    ? watches.map(watch => <tr\n                                key={watch.key}\n                                onMouseEnter={() => this.props.onSetHighlightAddress(watch.address)}\n                                onMouseLeave={() => this.props.onSetHighlightAddress(undefined)}\n                            >\n                            <td\n                                className={\"text\" + (((this.props.highlightAddress !== undefined) && (this.props.highlightAddress === watch.address)) ? \" attention\" : \"\")}\n                            >{watch.label}</td>\n                            <td\n                                className={((this.props.highlightAddress !== undefined) && (this.props.highlightAddress === watch.address)) ? \"attention\" : \"\"}\n                            ><NumberSpan format=\"decimal\" value={watch.value}/></td>\n                        </tr>)\n                    : <tr><td className=\"center\" colSpan={2}>\n                        <FormattedMessage\n                            id=\"textVariablesEmpty\"\n                            description=\"Text shown in the 'variables' table when there are no variables\"\n                            defaultMessage=\"(empty)\"\n                            />\n                        </td></tr>\n                }\n            </tbody>\n        </table>;\n    }\n}\n", "sic1/client/ts/main.tsx": "import { debug } from \"./setup\";\nimport { InitialPage, Sic1Root } from \"./root\";\nimport { BootScreen } from \"./boot-screen\";\nimport { Timer } from \"./timer\";\nimport React from \"react\";\nimport ReactDOMClient from \"react-dom/client\";\nimport { Platform, PresentationData } from \"./platform\";\nimport { Sic1DataManager, UserData } from \"./data-manager\";\nimport { SoundEffects } from \"./sound-effects\";\nimport { Music } from \"./music\";\nimport { applyColorScheme, ColorScheme, isColorScheme } from \"./colors\";\nimport { IntlConfig, IntlProvider, IntlShape, injectIntl } from \"react-intl\";\nimport { initializeResources } from \"./resources\";\nimport { Shared } from \"./shared\";\nimport { loadMessagesAsync } from \"./languages\";\nimport { localeToHrefOrMessages } from \"./language-data\";\n\ntype State = \"booting\" | \"loading\" | \"loaded\";\n\nclass Fader extends Timer {\n    public render(): React.ReactNode {\n        return <div className=\"fader\" style={{ \"animationDuration\": `${this.props.timerInMS}ms` }}></div>;\n    }\n}\n\ninterface Sic1MainProps {\n    intl: IntlShape;\n    locale: string | undefined;\n    defaultLocale: string;\n    initialState: State;\n    initialPage: InitialPage;\n    onLanguageUpdated: (locale: string | undefined) => void;\n}\n\ninterface Sic1MainState {\n    state: State;\n\n    // Presentation settings\n    fullscreen: boolean;\n    zoom: number;\n    colorScheme: ColorScheme; // Note: this one is actually a (synced) user setting\n\n    soundEffects: boolean;\n    soundVolume: number;\n\n    music: boolean;\n    musicVolume: number;\n}\n\nclass Sic1MainBase extends React.Component<Sic1MainProps, Sic1MainState> {\n    private initialFontSizePercent: number;\n\n    constructor(props: Sic1MainProps) {\n        super(props);\n\n        // First, localize resources because one in particular is used in Sic1DataManager.getData() (the default solution name)\n        initializeResources(this.props.intl);\n\n        const { colorScheme } = Sic1DataManager.getData();\n        const colorSchemeIsValid = isColorScheme(colorScheme);\n\n        const { fullscreen, zoom, soundEffects, soundVolume, music, musicVolume } = Sic1DataManager.getPresentationData();\n        this.state = {\n            state: props.initialState,\n            fullscreen: Platform.fullscreenDefault ?? fullscreen,\n            zoom,\n            colorScheme: colorSchemeIsValid ? colorScheme : \"Default\",\n            soundEffects,\n            soundVolume,\n            music,\n            musicVolume,\n        };\n\n        const fontSize = document.documentElement.style.getPropertyValue(\"font-size\") || \"100%\";\n        this.initialFontSizePercent = parseFloat(/^([0-9]+)%$/.exec(fontSize)[1]);\n\n        if (colorScheme && colorSchemeIsValid) {\n            applyColorScheme(colorScheme);\n        }\n    }\n\n    private keyDownHandler = (event: KeyboardEvent) => {\n        if (event.altKey && event.key === \"Enter\" || (Platform.app && (event.key === \"F11\" || event.key === \"F4\"))) {\n            // Full-screen hotkeys: Alt+Enter (on all platforms), and also F4/F11 for non-web versions\n            this.updateFullscreen(!Platform.fullscreen.get());\n        }\n    }\n\n    private updateSetting<TSettingsContainer, TKey extends keyof (TSettingsContainer | Sic1MainState)>(\n        getSettings: () => TSettingsContainer,\n        saveSettings: () => void,\n        key: TKey,\n        value: TSettingsContainer[TKey],\n        callback?: () => void,\n    ): void {\n        const settings = getSettings();\n        if (settings[key] !== value) {\n            settings[key] = value;\n            saveSettings();\n            // @ts-ignore 2345 TODO: Figure out how to convince TypeScript that [key] is correct\n            this.setState({ [key]: settings[key] });\n            if (callback) {\n                callback();\n            }\n        }\n    }\n\n    private updatePresentationSetting<T extends keyof PresentationData>(key: T, value: PresentationData[T], callback?: () => void): void {\n        this.updateSetting(() => Sic1DataManager.getPresentationData(), () => Sic1DataManager.savePresentationData(), key, value, callback);\n    }\n\n    private updateUserSetting<T extends keyof (Sic1MainState | UserData)>(key: T, value: UserData[T], callback?: () => void): void {\n        this.updateSetting(() => Sic1DataManager.getData(), () => Sic1DataManager.saveData(), key, value, callback);\n    }\n\n    private updateFullscreen(enabled: boolean): void {\n        this.updatePresentationSetting(\"fullscreen\", enabled);\n        Platform.fullscreen.set(enabled);\n    }\n\n    private applyZoom(zoom: number): void {\n        document.documentElement.style.setProperty(\"font-size\", `${this.initialFontSizePercent * zoom}%`);\n    }\n\n    private updateZoom(zoom: number): void {\n        this.updatePresentationSetting(\"zoom\", zoom, () => {\n            this.applyZoom(zoom);\n        });\n    }\n\n    private updateColorScheme(colorScheme: ColorScheme): void {\n        this.updateUserSetting(\"colorScheme\", colorScheme, () => {\n            applyColorScheme(colorScheme);\n        });\n    }\n\n    private updateSoundEffects(enabled: boolean): void {\n        this.updatePresentationSetting(\"soundEffects\", enabled, () => {\n            SoundEffects.setEnabled(enabled);\n            SoundEffects.play(\"click\");\n        });\n    }\n\n    private updateSoundVolume(volume: number): void {\n        this.updatePresentationSetting(\"soundVolume\", volume, () => {\n            SoundEffects.setVolume(volume);\n            SoundEffects.play(\"click\", volume);\n        });\n    }\n\n    private updateMusic(enabled: boolean): void {\n        this.updatePresentationSetting(\"music\", enabled, () => {\n            Music.setEnabled(enabled);\n        });\n    }\n\n    private updateMusicVolume(volume: number): void {\n        this.updatePresentationSetting(\"musicVolume\", volume, () => {\n            Music.setVolume(volume);\n        });\n    }\n\n    public componentDidMount() {\n        window.addEventListener(\"keydown\", this.keyDownHandler);\n\n        // Apply presentation settings\n        const presentationData = Sic1DataManager.getPresentationData();\n\n        // Note: Full-screen is not applied here because:\n        //\n        //  1) Web version never launches directly to fullscreen\n        //  2) Desktop version handles fullscreen prior to page load\n\n        this.applyZoom(presentationData.zoom);\n\n        SoundEffects.setEnabled(presentationData.soundEffects);\n        SoundEffects.setVolume(presentationData.soundVolume);\n\n        Music.setEnabled(presentationData.music);\n        Music.setVolume(presentationData.musicVolume);\n    }\n\n    public componentWillUnmount() {\n        window.removeEventListener(\"keydown\", this.keyDownHandler);\n    }\n\n    render(): React.ReactNode {\n        const { state, ...presentationSettings } = this.state;\n        return <>\n            {state === \"booting\" ? <BootScreen intl={this.props.intl} onCompleted={() => this.setState({ state: \"loading\" })} /> : null}\n            {state === \"loading\" ? <Fader timerInMS={250} onTimerCompleted={() => this.setState({ state: \"loaded\" })} /> : null}\n            {(state === \"loading\" || state === \"loaded\")\n                ? <Sic1Root\n                    {...this.props}\n                    {...presentationSettings}\n                    intl={this.props.intl}\n                    onFullscreenUpdated={enabled => this.updateFullscreen(enabled)}\n                    onZoomUpdated={zoom => this.updateZoom(zoom)}\n                    onColorSchemeUpdated={colorScheme => this.updateColorScheme(colorScheme)}\n\n                    onSoundEffectsUpdated={enabled => this.updateSoundEffects(enabled)}\n                    onSoundVolumeUpdated={volume => this.updateSoundVolume(volume)}\n\n                    onMusicUpdated={enabled => this.updateMusic(enabled)}\n                    onMusicVolumeUpdated={volume => this.updateMusicVolume(volume)}\n\n                    onRestart={() => this.setState({ state: \"booting\" })}\n                    />\n                : null}\n        </>;\n    }\n}\n\n// Main\nconst Sic1Main = injectIntl(Sic1MainBase);\n\n// IntlProvider wrapper\ninterface Sic1ActualRootProps {\n    defaultLocale: string;\n    initialLocale: string;\n    initialMessages: IntlConfig[\"messages\"];\n}\n\ninterface Sic1ActualRootState {\n    locale: string | undefined; // Note: this one is actually a (synced) user setting\n    messages: IntlConfig[\"messages\"];\n    localeUpdated?: boolean; // Minor hack to launch back into Presentation Settings on language change\n}\n\nconst defaultLocale = Platform.getDefaultLocale();\n\nasync function loadMessagesForLocaleSpecifierAsync(localeSpecifier: string | undefined): Promise<IntlConfig[\"messages\"]> {\n    return await loadMessagesAsync(localeSpecifier ?? defaultLocale);\n}\n\nclass Sic1ActualRoot extends React.Component<Sic1ActualRootProps, Sic1ActualRootState> {\n    constructor(props: Sic1ActualRootProps) {\n        super(props);\n\n        this.state = {\n            locale: props.initialLocale,\n            messages: props.initialMessages,\n        };\n    }\n\n    private getLocale(): string {\n        return this.state.locale ?? this.props.defaultLocale;\n    }\n\n    private setLanguage(): void {\n        // This is needed to ensure that reasonable fonts are used for Unicode code points that are shared across\n        // multiple languages but which need to be drawn differently\n        document.body.setAttribute(\"lang\", this.getLocale());\n    }\n\n    public componentDidMount(): void {\n        this.setLanguage();\n    }\n\n    public componentDidUpdate(prevProps: Readonly<Sic1ActualRootProps>, prevState: Readonly<Sic1ActualRootState>, snapshot?: any): void {\n        if (this.state.locale !== prevState.locale) {\n            this.setLanguage();\n        }\n    }\n\n    public render(): React.ReactNode {\n        const { defaultLocale } = this.props;\n        const locale = this.getLocale();\n\n        return <IntlProvider\n            locale={locale}\n            messages={this.state.messages}\n            onError={(err) => {\n                if (err.code === \"MISSING_TRANSLATION\") {\n                    // Ignore during development...\n                } else {\n                    console.error(err);\n                }\n            }}\n            {...Shared.intlProviderOptions}\n            >\n                <Sic1Main\n                    key={locale}\n                    locale={locale}\n                    defaultLocale={defaultLocale}\n                    initialState={(debug || this.state.localeUpdated) ? \"loaded\" : \"booting\"}\n                    initialPage={this.state.localeUpdated ? \"presentationSettings\" : \"puzzleList\"}\n                    onLanguageUpdated={async (locale) => {\n                        Sic1DataManager.getData().locale = locale;\n                        Sic1DataManager.saveData();\n\n                        // Asynchronously load messages\n                        const messages = await loadMessagesForLocaleSpecifierAsync(locale);\n\n                        this.setState({\n                            locale,\n                            messages,\n                            localeUpdated: true,\n                        });\n                    }}\n                />\n            </IntlProvider>;\n    }\n}\n\nconst root = ReactDOMClient.createRoot(document.getElementById(\"root\"));\nconst { locale } = Sic1DataManager.getData();\n\n(async () => {\n    let messages: IntlConfig[\"messages\"];\n    try {\n        messages = await loadMessagesForLocaleSpecifierAsync(locale);\n    } catch {\n        // Failed to load locale-specific resources; default to (preloaded) English\n        messages = localeToHrefOrMessages.en;\n    }\n\n    root.render(\n        <Sic1ActualRoot\n            defaultLocale={defaultLocale}\n            initialLocale={locale}\n            initialMessages={messages}\n            />\n    );\n})();\n", "sic1/client/ts/languages.ts": "import { IntlConfig } from \"react-intl\";\nimport { localeToHrefOrMessages } from \"./language-data\";\n\nexport async function loadMessagesAsync(locale: string): Promise<IntlConfig[\"messages\"]> {\n    const hrefOrMessages: string | IntlConfig[\"messages\"] = localeToHrefOrMessages[locale];\n    if (typeof(hrefOrMessages) === \"string\") {\n        // URL for the JSON message file; load it\n        const result = await fetch(new URL(hrefOrMessages));\n        if (result.ok) {\n            // react-intl uses a slightly different format for specifying messages vs. storing them. In order to\n            // support local testing using the \"specification\" format, do a hacky translation here\n            const json = await result.json();\n            const firstKey = Object.keys(json)[0];\n            if (firstKey && json[firstKey][\"defaultMessage\"]) {\n                // This appears to be the \"specification\" format; translate it\n                return Object.fromEntries(Object.entries(json).map(([key, value]) => [key, value[\"defaultMessage\"] ?? value]))\n            } else {\n                return json as IntlConfig[\"messages\"];\n            }\n        } else {\n            throw `Failed to retrieve translations for locale: ${locale}`;\n        }\n    } else {\n        return hrefOrMessages;\n    }\n}\n", "sic1/client/ts/platform-types.d.ts": "// Host objects for WebView2-based app\ndeclare const chrome: { webview: { hostObjects: {\n    sync: {\n        steam: {\n            UserName: string,\n            AppLanguage: string,\n\n            // Leaderboards\n            ResolveGetLeaderboard: (resolve: (leaderboardHandle: number) => void, reject: (status: number) => void, leaderboardName: string) => void;\n            ResolveSetLeaderboardEntry: (resolve: (updated: boolean) => void, reject: (status: number) => void, leaderboardHandle: number, score: number, program?: number[]) => void;\n            ResolveGetFriendLeaderboardEntries: (resolve: (flatArray: (string | number)[]) => void, reject: (status: number) => void, leaderboardHandle: number) => void;\n\n            // Achievements\n            GetAchievement: (achievementId: string) => boolean;\n            SetAchievement: (achievementId: string) => boolean;\n            ResolveStoreAchievements: (resolve: () => void, reject: (status: number) => void) => void;\n        },\n        webViewWindow: {\n            Fullscreen: boolean,\n            LocalStorageDataString?: string, // Used for both import and export\n            OnClosing: () => void,\n\n            // Presentation settings\n            GetPresentationSetting: (fieldName: string) => number;\n            SetPresentationSetting: (fieldName: string, value: number) => void;\n\n            // Data/settings persistence\n            ResolvePersistLocalStorage: (resolve: () => void, reject: (status: number) => void, data: string) => void;\n            ResolvePersistPresentationSettings: (resolve: () => void, reject: (status: number) => void) => void;\n\n            // Manual\n            OpenManual: (locale: string) => void;\n        },\n    },\n    options: {\n        forceAsyncMethodMatches: RegExp[],\n    },\n} } };\n", "sic1/client/ts/text-button.tsx": "import React from \"react\";\n\nexport class TextButton extends React.Component<{ children?: React.ReactNode; onClick: () => void }> {\n    constructor(props) {\n        super(props);\n    }\n\n    public render() {\n        return <a href=\"#\" onClick={(event) => {\n            event.preventDefault();\n            this.props.onClick();\n        }}>{this.props.children}</a>\n    }\n}\n", "sic1/client/ts/shared.tsx": "import React from \"react\";\nimport { FormattedMessage, IntlShape } from \"react-intl\";\n\nexport const Shared = {\n    localStoragePrefix: \"sic1_\",\n    avoisionSolvedCountRequired: 7,\n    blankImageDataUri: \"data:image/gif;base64,R0lGODlhAQABAAAAACH5BAEKAAEALAAAAAABAAEAAAICTAEAOw==\",\n\n    intlProviderOptions: {\n        defaultLocale: \"en\",\n        defaultRichTextElements: {\n            h1: c => <h1>{c}</h1>,\n            h3: c => <h3>{c}</h3>,\n            p: c => <p>{c}</p>,\n            strong: c => <strong>{c}</strong>,\n            em: c => <em>{c}</em>,\n            pre: c => <pre>{c}</pre>,\n            code: c => <code>{c}</code>,\n            cap: c => <span className=\"caps\">{c}</span>,\n            ol: c => <ol>{c}</ol>,\n            ul: c => <ul>{c}</ul>,\n            li: c => <li>{c}</li>,\n        },\n    },\n\n    resources: {\n        cancel: <FormattedMessage\n            id=\"buttonCancel\"\n            description=\"Text shown on various 'cancel' buttons when discarding changes to settings\"\n            defaultMessage=\"Cancel\"\n            />,\n        headerIOIn: <FormattedMessage\n            id=\"headerInputIn\"\n            description=\"Column heading for the IO table, for input (note: this string should be as short as possible)\"\n            defaultMessage=\"In\"\n            />,\n        headerIOOut: <FormattedMessage\n            id=\"headerIOOutput\"\n            description=\"Column heading for the IO table, for output, when no expected output is prescribed, i.e. in Sandbox Mode (note: this string should be as short as possible)\"\n            defaultMessage=\"Out\"\n            />,\n        \n        // This FormattedMessage isn't actually displayed anywhere, but is used to obtain the native names of languages,\n        // for use in the language selector\n        languageName: <FormattedMessage\n            id=\"languageName\"\n            description=\"The name of the language being translated, in that language (using Title Case where appropriate), used for the language selection dropdown--but note that a full rebuild of the game is required for this string (only) to take effect\"\n            defaultMessage=\"English\"\n            />,\n\n        manualTitle: <FormattedMessage\n            id=\"manualTitle\"\n            description=\"Page title for the HTML/printable manual\"\n            defaultMessage=\"SIC-1 Manual\"\n            />,\n        manualHeading: <FormattedMessage\n            id=\"manualHeading\"\n            description=\"Markup shown at the top of the printable/HTML manual\"\n            defaultMessage=\"<h1>SIC-1 Reference Manual</h1><p>(C) 1979 - 1980 SIC Systems, Inc.</p>\"\n            />,\n        loading: <FormattedMessage\n            id=\"loading\"\n            description=\"Text to show while a portion of the UI is loading\"\n            defaultMessage=\"(loading...)\"\n            />,\n        loadFailed: <FormattedMessage\n            id=\"loadFailed\"\n            description=\"Text to show when an asynchronous load of a UI component failed\"\n            defaultMessage=\"(load failed)\"\n            />,\n        saveChanges: <FormattedMessage\n            id=\"buttonSaveChanges\"\n            description=\"Text shown on multiple 'save changes' buttons when editing settings\"\n            defaultMessage=\"Save Changes\"\n            />,\n        taskStatistics: <FormattedMessage\n            id=\"textTaskStatistics\"\n            description=\"Markup introducing task statistic charts for completed tasks\"\n            defaultMessage=\"Here are performance statistics of your program (as compared to others' programs):\"\n            />,\n        taskStatusIncomplete: <FormattedMessage\n            id=\"taskStatusIncomplete\"\n            description=\"Status shown for a task that has been viewed, but not yet completed\"\n            defaultMessage=\"Incomplete\"\n            />,\n    },\n\n    jobTitles: [\n        {\n            title: <FormattedMessage\n                id=\"jobTitle0\"\n                description=\"Starting job title (during training/tutorial)\"\n                defaultMessage=\"Trainee\"\n                />,\n            minimumSolved: 0\n        },\n        {\n            title: <FormattedMessage\n                id=\"jobTitle1\"\n                description=\"Initial engineering job title (after completing training/tutorial)\"\n                defaultMessage=\"Engineer\"\n                />,\n            minimumSolved: 3\n        },\n        {\n            title: <FormattedMessage\n                id=\"jobTitle2\"\n                description=\"Second engineering job title\"\n                defaultMessage=\"Engineer II\"\n                />,\n            minimumSolved: 8\n        },\n        {\n            title: <FormattedMessage\n                id=\"jobTitle3\"\n                description=\"Third engineering job title\"\n                defaultMessage=\"Senior Engineer\"\n                />,\n            minimumSolved: 11\n        },\n        {\n            title: <FormattedMessage\n                id=\"jobTitle4\"\n                description=\"Fourth engineering job title\"\n                defaultMessage=\"Principal Engineer\"\n                />,\n            minimumSolved: 15\n        },\n        {\n            title: <FormattedMessage\n                id=\"jobTitle5\"\n                description=\"Fifth engineering job title\"\n                defaultMessage=\"Partner Engineer\"\n                />,\n            minimumSolved: 18\n        },\n        {\n            title: <FormattedMessage\n                id=\"jobTitle6\"\n                description=\"Sixth engineering job title (noting distinguished accomplishments)\"\n                defaultMessage=\"Distinguished Engineer\"\n                />,\n            minimumSolved: 23\n        },\n        {\n            title: <FormattedMessage\n                id=\"jobTitle7\"\n                description=\"Top engineering job title\"\n                defaultMessage=\"Technical Fellow\"\n                />,\n            minimumSolved: 26\n        },\n        {\n            title: <FormattedMessage\n                id=\"jobTitle8\"\n                description=\"Final job title (implying the person left the company after achieving the pinnacle of success)\"\n                defaultMessage=\"Technical Fellow Emeritus\"\n                />,\n            minimumSolved: 30\n        },\n    ],\n\n    hexifyByte: (v: number): string => {\n        var str = v.toString(16);\n        if (str.length == 1) {\n            str = \"0\" + str;\n        }\n        return str;\n    },\n\n    getJobTitleForSolvedCount: (solvedCount: number): React.ReactNode => {\n        let title: React.ReactNode = \"\";\n        for (const row of Shared.jobTitles) {\n            if (solvedCount >= row.minimumSolved) {\n                title = row.title;\n            }\n        }\n        return title;\n    },\n\n    isElementInViewport: (element: Element): boolean => {\n        var rect = element.getBoundingClientRect();\n\n        return (\n            rect.top >= 0\n            && rect.left >= 0\n            && rect.bottom <= (window.innerHeight || document.documentElement.clientHeight)\n            && rect.right <= (window.innerWidth || document.documentElement.clientWidth)\n        );\n    },\n\n    scrollElementIntoView: (element: Element, position: ScrollLogicalPosition = \"nearest\", force = false): void =>{\n        if (element && (force || !Shared.isElementInViewport(element))) {\n            element.scrollIntoView({ block: position });\n        }\n    },\n\n    ignoreRejection: (promise?: Promise<any>): void => {\n        if (promise) {\n            promise.catch(() => {});\n        }\n    },\n\n    keyToVerticalOffset: {\n        ArrowUp: -1,\n        ArrowDown: 1,\n    } as const,\n\n    focusFromQuery: (root: ParentNode, query: string, offset: number, wrap = false): void => {\n        if (root) {\n            const elements = root.querySelectorAll<HTMLButtonElement>(query);\n            const activeElement = document.activeElement;\n            for (let i = 0; i < elements.length; i++) {\n                const element = elements[i];\n                if (element === activeElement) {\n                    let index = i + offset;\n    \n                    if (wrap) {\n                        if (index < 0) {\n                            index = elements.length - 1;\n                        } else if (index >= elements.length) {\n                            index = 0;\n                        }\n                    }\n    \n                    if (index >= 0 && index < elements.length) {\n                        elements[index].focus();\n                    }\n                    \n                    break;\n                }\n            }\n        }\n    },\n\n    createUniqueName: (intl: IntlShape, name: string, existingNames: string[]): string => {\n        // If the name is already unique, just use whatever was supplied\n        let number = 1;\n        let newName = name;\n        while (!existingNames.every(s => s !== newName)) {\n            newName = intl.formatMessage(\n                {\n                    id: \"templateSolutionDuplicate\",\n                    description: \"Text template for new names when the desired name already exists\",\n                    defaultMessage: \"{name} ({number})\",\n                },\n                {\n                    name,\n                    number: number++,\n                });\n        }\n\n        return newName;\n    },\n\n    toggleSetValue<T>(set: Set<T>, value: T): Set<T> {\n        const newSet = new Set(set);\n        if (newSet.has(value)) {\n            newSet.delete(value);\n        } else {\n            newSet.add(value);\n        }\n        return newSet;\n    },\n\n    createFunctionWithMinimumPeriod(f: () => void, minimumPeriodMS): () => void {\n        let lastCallTime = 0;\n        return () => {\n            const now = Date.now();\n            if ((now - lastCallTime) >= minimumPeriodMS) {\n                f();\n                lastCallTime = now;\n            }\n        };\n    }\n} as const;\n", "sic1/client/ts/language-default.ts": "/** The actual default/fallback locale, in case the \"default\" one doesn't match any available translations */\nconst defaultLocaleString = \"en\";\n\nfunction findAdjustedLocale(adjust: (localeString: string) => string, desiredLocaleStrings: readonly string[], availableLocaleStrings: string[]): string | undefined {\n    const available = Object.fromEntries(availableLocaleStrings.map(localeString => [adjust(localeString), localeString]));\n    for (const desiredLocaleString of desiredLocaleStrings) {\n        const adjustedLocaleString = adjust(desiredLocaleString);\n        const result = available[adjustedLocaleString];\n        if (result) {\n            return result;\n        }\n    }\n}\n\nfunction identity(localeString: string): string {\n    return localeString;\n}\n\nfunction useOnlyLanguageAndScript(localeString: string): string {\n    try {\n        const locale = new Intl.Locale(localeString);\n        return (new Intl.Locale(locale.language, {\n            script: locale.script,\n        })).toString();\n    } catch {\n        return localeString;\n    }\n}\n\nfunction useOnlyLanguage(localeString: string): string {\n    try {\n        const locale = new Intl.Locale(localeString);\n        return (new Intl.Locale(locale.language)).toString();\n    } catch {\n        return localeString;\n    }\n}\n\nfunction inferScript(localeString: string): string {\n    try {\n        const locale = new Intl.Locale(localeString);\n\n        // Infer Chinese script from region, if necessary\n        if (locale.language === \"zh\" && !locale.script && locale.region) {\n            switch (locale.region) {\n                case \"TW\":\n                case \"HK\":\n                case \"MO\":\n                    return \"zh-Hant\";\n                \n                default:\n                    return \"zh-Hans\";\n            }\n        }\n\n        return localeString;\n    } catch {\n        // Don't let an error propagate, but there's nothing sensible to do here, so use the default...\n        return defaultLocaleString;\n    }\n}\n\nexport function getBestLocale(desiredLocaleIds: readonly string[], availableLocaleIds: string[]): string {\n    return findAdjustedLocale(identity, desiredLocaleIds, availableLocaleIds) // First try exact match\n        ?? findAdjustedLocale(useOnlyLanguageAndScript, desiredLocaleIds.map(localeString => inferScript(localeString)), availableLocaleIds) // Then try language+script\n        ?? findAdjustedLocale(useOnlyLanguage, desiredLocaleIds, availableLocaleIds) // Then try language only\n        ?? defaultLocaleString; // Default to \"en\"\n}\n\n// List from: https://partner.steamgames.com/doc/store/localization/languages#supported_languages\nexport const steamApiLanguageCodeToLocale: { [steamApiLanguageCode: string]: string } = {\n    arabic: \"ar\",\n    bulgarian: \"bg\",\n    schinese: \"zh-CN\",\n    tchinese: \"zh-TW\",\n    czech: \"cs\",\n    danish: \"da\",\n    dutch: \"nl\",\n    english: \"en\",\n    finnish: \"fi\",\n    french: \"fr\",\n    german: \"de\",\n    greek: \"el\",\n    hungarian: \"hu\",\n    indonesian: \"id\",\n    italian: \"it\",\n    japanese: \"ja\",\n    koreana: \"ko\", // Why!?\n    norwegian: \"no\",\n    polish: \"pl\",\n    portuguese: \"pt\",\n    brazilian: \"pt-BR\",\n    romanian: \"ro\",\n    russian: \"ru\",\n    spanish: \"es\",\n    latam: \"es-419\",\n    swedish: \"sv\",\n    thai: \"th\",\n    turkish: \"tr\",\n    ukrainian: \"uk\",\n    vietnamese: \"vn\",\n}\n", "sic1/client/ts/user-stats.tsx": "import React from \"react\";\nimport { Chart, ChartState } from \"./chart\";\nimport { ChartData } from \"./chart-model\";\nimport { FriendLeaderboard } from \"./friend-leaderboard\";\nimport { Platform } from \"./platform\";\nimport { Sic1SteamService } from \"./service\";\nimport { FormattedMessage } from \"react-intl\";\nimport { Shared } from \"./shared\";\n\ninterface Sic1UserStatsState {\n    chartState: ChartState;\n    data?: ChartData;\n}\n\nexport class Sic1UserStats extends React.Component<{ promise: Promise<ChartData> }, Sic1UserStatsState> {\n    constructor(props) {\n        super(props);\n        this.state = { chartState: ChartState.loading };\n    }\n\n    public async componentDidMount() {\n        try {\n            this.setState({\n                chartState: ChartState.loaded,\n                data: await this.props.promise,\n            });\n        } catch (error) {\n            this.setState({ chartState: ChartState.loadFailed });\n        }\n    }\n\n    public render() {\n        // Calculate rank\n        let count = 0;\n        let worse = 0;\n        if (this.state.data) {\n            const histogram = this.state.data.histogram.buckets;\n            const highlightedValue = this.state.data.highlightedValue;\n            for (let i = 0; i < histogram.length; i++) {\n                const bucket = histogram[i];\n                count += bucket.count;\n\n                if (bucket.bucketMax <= highlightedValue) {\n                    worse += bucket.count;\n                }\n            }\n        }\n\n        const rank = Math.min(count, count - (worse - 1));\n\n        return <>\n            <p>\n                <FormattedMessage\n                    id=\"rank\"\n                    description=\"Current ranking of the player\"\n                    defaultMessage=\"Rank: {ranking}\"\n                    values={{ ranking: this.state.data\n                        ? <FormattedMessage\n                            id=\"rankOutOf\"\n                            description=\"Actual ranking value (out of total)\"\n                            defaultMessage=\"{rank} out of {total}\"\n                            values={{\n                                rank,\n                                total: count,\n                            }}\n                            />\n                        : Shared.resources.loading}}\n                    />\n            </p>\n            <div className=\"charts\">\n                <Chart\n                    title={<FormattedMessage\n                        id=\"chartTitleTasks\"\n                        description=\"Title for the 'tasks completed' chart\"\n                        defaultMessage=\"Completed Tasks\"\n                        />}\n                    promise={this.props.promise} />\n                {Platform.service.getFriendLeaderboardAsync\n                ? <>\n                    <br/>\n                    <FriendLeaderboard\n                        title={<FormattedMessage\n                            id=\"chartFriendTasks\"\n                            description=\"Title of friend leaderboard chart for 'tasks completed'\"\n                            defaultMessage=\"Completed Tasks (Friends)\"\n                            />}\n                        promise={Platform.service.getFriendLeaderboardAsync(Sic1SteamService.solvedCountLeaderboardName)} />\n                </>\n                : null\n            }\n            </div>\n        </>;\n    }\n}\n", "sic1/client/ts/achievements.tsx": "// This list of achievement ids should match Steam app admin\nimport React from \"react\";\nimport { FormattedMessage } from \"react-intl\";\n\nexport const achievements = {\n    JOB_TITLE_1: {\n        title: <FormattedMessage\n            id=\"achievementNameJOB_TITLE_1\"\n            description=\"Display name for the JOB_TITLE_1 achievement\"\n            defaultMessage=\"Engineer\"\n        />,\n        imageUri: (new URL('../img/i.png', import.meta.url)).href,\n        description: <FormattedMessage\n            id=\"achievementDescriptionJOB_TITLE_1\"\n            description=\"Description of the JOB_TITLE_1 achievement\"\n            defaultMessage=\"Get promoted to Engineer.\"\n        />,\n    },\n    JOB_TITLE_2: {\n        title: <FormattedMessage\n            id=\"achievementNameJOB_TITLE_2\"\n            description=\"Display name for the JOB_TITLE_2 achievement\"\n            defaultMessage=\"Engineer II\"\n        />,\n        imageUri: (new URL('../img/ii.png', import.meta.url)).href,\n        description: <FormattedMessage\n            id=\"achievementDescriptionJOB_TITLE_2\"\n            description=\"Description of the JOB_TITLE_2 achievement\"\n            defaultMessage=\"Get promoted to Engineer II.\"\n        />,\n    },\n    JOB_TITLE_3: {\n        title: <FormattedMessage\n            id=\"achievementNameJOB_TITLE_3\"\n            description=\"Display name for the JOB_TITLE_3 achievement\"\n            defaultMessage=\"Senior Engineer\"\n        />,\n        imageUri: (new URL('../img/iii.png', import.meta.url)).href,\n        description: <FormattedMessage\n            id=\"achievementDescriptionJOB_TITLE_3\"\n            description=\"Description of the JOB_TITLE_3 achievement\"\n            defaultMessage=\"Get promoted to Senior Engineer.\"\n        />,\n    },\n    JOB_TITLE_4: {\n        title: <FormattedMessage\n            id=\"achievementNameJOB_TITLE_4\"\n            description=\"Display name for the JOB_TITLE_4 achievement\"\n            defaultMessage=\"Principal Engineer\"\n        />,\n        imageUri: (new URL('../img/iv.png', import.meta.url)).href,\n        description: <FormattedMessage\n            id=\"achievementDescriptionJOB_TITLE_4\"\n            description=\"Description of the JOB_TITLE_4 achievement\"\n            defaultMessage=\"Get promoted to Principal Engineer.\"\n        />,\n    },\n    JOB_TITLE_5: {\n        title: <FormattedMessage\n            id=\"achievementNameJOB_TITLE_5\"\n            description=\"Display name for the JOB_TITLE_5 achievement\"\n            defaultMessage=\"Partner Engineer\"\n        />,\n        imageUri: (new URL('../img/v.png', import.meta.url)).href,\n        description: <FormattedMessage\n            id=\"achievementDescriptionJOB_TITLE_5\"\n            description=\"Description of the JOB_TITLE_5 achievement\"\n            defaultMessage=\"Get promoted to Partner Engineer.\"\n        />,\n    },\n    JOB_TITLE_6: {\n        title: <FormattedMessage\n            id=\"achievementNameJOB_TITLE_6\"\n            description=\"Display name for the JOB_TITLE_6 achievement\"\n            defaultMessage=\"Distinguished Engineer\"\n        />,\n        imageUri: (new URL('../img/vi.png', import.meta.url)).href,\n        description: <FormattedMessage\n            id=\"achievementDescriptionJOB_TITLE_6\"\n            description=\"Description of the JOB_TITLE_6 achievement\"\n            defaultMessage=\"Get promoted to Distinguished Engineer.\"\n        />,\n    },\n    JOB_TITLE_7: {\n        title: <FormattedMessage\n            id=\"achievementNameJOB_TITLE_7\"\n            description=\"Display name for the JOB_TITLE_7 achievement\"\n            defaultMessage=\"Special Promotion\"\n        />,\n        imageUri: (new URL('../img/vii.png', import.meta.url)).href,\n        description: <FormattedMessage\n            id=\"achievementDescriptionJOB_TITLE_7\"\n            description=\"Description of the JOB_TITLE_7 achievement\"\n            defaultMessage=\"Get a new job title made just for you.\"\n        />,\n    },\n    JOB_TITLE_8: {\n        title: <FormattedMessage\n            id=\"achievementNameJOB_TITLE_8\"\n            description=\"Display name for the JOB_TITLE_8 achievement\"\n            defaultMessage=\"Terminal Promotion\"\n        />,\n        imageUri: (new URL('../img/viii.png', import.meta.url)).href,\n        description: <FormattedMessage\n            id=\"achievementDescriptionJOB_TITLE_8\"\n            description=\"Description of the JOB_TITLE_8 achievement\"\n            defaultMessage=\"Obtain the final promotion.\"\n        />,\n    },\n    NEW_END: {\n        title: <FormattedMessage\n            id=\"achievementNameNEW_END\"\n            description=\"Display name for the NEW_END achievement\"\n            defaultMessage=\"To Be Continued\"\n        />,\n        imageUri: (new URL('../img/epilogue.png', import.meta.url)).href,\n        description: <FormattedMessage\n            id=\"achievementDescriptionNEW_END\"\n            description=\"Description of the NEW_END achievement\"\n            defaultMessage=\"Share a true self-hosting program with an old friend.\"\n        />,\n    },\n    \n    TIME_LATE: {\n        title: <FormattedMessage\n            id=\"achievementNameTIME_LATE\"\n            description=\"Display name for the TIME_LATE achievement\"\n            defaultMessage=\"Workin' Hard\"\n        />,\n        imageUri: (new URL('../img/time-late.png', import.meta.url)).href,\n        description: <FormattedMessage\n            id=\"achievementDescriptionTIME_LATE\"\n            description=\"Description of the TIME_LATE achievement\"\n            defaultMessage=\"Complete a task after 9pm (21:00) local time.\"\n        />,\n    },\n    TIME_EARLY: {\n        title: <FormattedMessage\n            id=\"achievementNameTIME_EARLY\"\n            description=\"Display name for the TIME_EARLY achievement\"\n            defaultMessage=\"Up and at 'Em\"\n        />,\n        imageUri: (new URL('../img/time-early.png', import.meta.url)).href,\n        description: <FormattedMessage\n            id=\"achievementDescriptionTIME_EARLY\"\n            description=\"Description of the TIME_EARLY achievement\"\n            defaultMessage=\"Complete a task before 6am (06:00) local time.\"\n        />,\n    },\n    OMIT_SUBLEQ: {\n        title: <FormattedMessage\n            id=\"achievementNameOMIT_SUBLEQ\"\n            description=\"Display name for the OMIT_SUBLEQ achievement\"\n            defaultMessage=\"Zero Instruction Computer\"\n        />,\n        imageUri: (new URL('../img/no-subleq.png', import.meta.url)).href,\n        description: <FormattedMessage\n            id=\"achievementDescriptionOMIT_SUBLEQ\"\n            description=\"Description of the OMIT_SUBLEQ achievement\"\n            defaultMessage={`Solve \"Addition\" without typing \"subleq\".`}\n        />,\n    },\n    ERASE: {\n        title: <FormattedMessage\n            id=\"achievementNameERASE\"\n            description=\"Display name for the ERASE achievement\"\n            defaultMessage=\"Self-Destruct\"\n        />,\n        imageUri: (new URL('../img/destruct.png', import.meta.url)).href,\n        description: <FormattedMessage\n            id=\"achievementDescriptionERASE\"\n            description=\"Description of the ERASE achievement\"\n            defaultMessage=\"Write a program that reads a single input and then deletes itself (sets all memory to zero), without producing output.\"\n        />,\n    },\n    AVOISION: {\n        title: <FormattedMessage\n            id=\"achievementNameAVOISION\"\n            description=\"Display name for the AVOISION achievement\"\n            defaultMessage=\"Master Avoider\"\n        />,\n        imageUri: (new URL('../img/avoision.png', import.meta.url)).href,\n        description: <FormattedMessage\n            id=\"achievementDescriptionAVOISION\"\n            description=\"Description of the AVOISION achievement\"\n            defaultMessage=\"Score at least 250 points in Avoision.\"\n        />,\n    },\n} as const;\n\nexport type Achievement = keyof typeof achievements;\n\nexport const jobTitleAchievementIds: Achievement[] = [\n    \"JOB_TITLE_1\",\n    \"JOB_TITLE_2\",\n    \"JOB_TITLE_3\",\n    \"JOB_TITLE_4\",\n    \"JOB_TITLE_5\",\n    \"JOB_TITLE_6\",\n    \"JOB_TITLE_7\",\n    \"JOB_TITLE_8\",\n];\n", "sic1/client/ts/toaster.tsx": "import React from \"react\";\n\nexport interface ToastInfo {\n    image: HTMLImageElement;\n    title: React.ReactNode;\n    text?: React.ReactNode;\n}\n\nexport interface ToastProps extends ToastInfo {\n    onCompleted: () => void;\n}\n\nexport class Toast extends React.Component<ToastProps> {\n    private ref = React.createRef<HTMLDivElement>();\n    private complete = () => this.props.onCompleted();\n\n    public componentDidMount(): void {\n        this.ref.current.addEventListener(\"animationend\", this.complete);\n    }\n\n    public componentWillUnmount(): void {\n        this.ref.current.removeEventListener(\"animationend\", this.complete);\n    }\n\n    public render(): React.ReactNode {\n        const { src, width, height } = this.props.image;\n        const imageProps = { src, width, height };\n        return <>\n            <div ref={this.ref} className=\"toast\">\n                <img {...imageProps} />\n                <section>\n                    <header>{this.props.title}</header>\n                    {this.props.text ? <p>{this.props.text}</p> : null}\n                </section>\n            </div>\n        </>;\n    }\n}\n\nexport class Toaster extends React.Component<{}, { toast?: ToastInfo; queue: ToastInfo[] }> {\n    constructor(props) {\n        super(props);\n        this.state = { queue: [] };\n    }\n\n    private advance(): void {\n        this.setState(state => ({\n            toast: state.queue[0],\n            queue: [...state.queue.slice(1)],\n        }));\n    }\n\n    public enqueue(toast: ToastInfo): void {\n        this.setState(state => {\n            if (state.toast) {\n                return { queue: [...state.queue, toast ] };\n            } else {\n                return { toast };\n            }\n        });\n    }\n\n    public render(): React.ReactNode {\n        const toast = this.state.toast;\n        return toast\n            ? <Toast\n                key={`${toast.title};${toast.text};${toast.image.src}`}\n                {...toast}\n                onCompleted={() => this.advance()}\n                />\n            : null;\n    }\n}\n", "sic1/client/ts/licenses.ts": "export default\n`\n===========================================================\nCascadia Code font\n===========================================================\n\nCopyright (c) 2019 - Present, Microsoft Corporation,\nwith Reserved Font Name Cascadia Code.\n\nThis Font Software is licensed under the SIL Open Font License, Version 1.1.\nThis license is copied below, and is also available with a FAQ at:\nhttp://scripts.sil.org/OFL\n\n\n-----------------------------------------------------------\nSIL OPEN FONT LICENSE Version 1.1 - 26 February 2007\n-----------------------------------------------------------\n\nPREAMBLE\nThe goals of the Open Font License (OFL) are to stimulate worldwide\ndevelopment of collaborative font projects, to support the font creation\nefforts of academic and linguistic communities, and to provide a free and\nopen framework in which fonts may be shared and improved in partnership\nwith others.\n\nThe OFL allows the licensed fonts to be used, studied, modified and\nredistributed freely as long as they are not sold by themselves. The\nfonts, including any derivative works, can be bundled, embedded, \nredistributed and/or sold with any software provided that any reserved\nnames are not used by derivative works. The fonts and derivatives,\nhowever, cannot be released under any other type of license. The\nrequirement for fonts to remain under this license does not apply\nto any document created using the fonts or their derivatives.\n\nDEFINITIONS\n\"Font Software\" refers to the set of files released by the Copyright\nHolder(s) under this license and clearly marked as such. This may\ninclude source files, build scripts and documentation.\n\n\"Reserved Font Name\" refers to any names specified as such after the\ncopyright statement(s).\n\n\"Original Version\" refers to the collection of Font Software components as\ndistributed by the Copyright Holder(s).\n\n\"Modified Version\" refers to any derivative made by adding to, deleting,\nor substituting -- in part or in whole -- any of the components of the\nOriginal Version, by changing formats or by porting the Font Software to a\nnew environment.\n\n\"Author\" refers to any designer, engineer, programmer, technical\nwriter or other person who contributed to the Font Software.\n\nPERMISSION & CONDITIONS\nPermission is hereby granted, free of charge, to any person obtaining\na copy of the Font Software, to use, study, copy, merge, embed, modify,\nredistribute, and sell modified and unmodified copies of the Font\nSoftware, subject to the following conditions:\n\n1) Neither the Font Software nor any of its individual components,\nin Original or Modified Versions, may be sold by itself.\n\n2) Original or Modified Versions of the Font Software may be bundled,\nredistributed and/or sold with any software, provided that each copy\ncontains the above copyright notice and this license. These can be\nincluded either as stand-alone text files, human-readable headers or\nin the appropriate machine-readable metadata fields within text or\nbinary files as long as those fields can be easily viewed by the user.\n\n3) No Modified Version of the Font Software may use the Reserved Font\nName(s) unless explicit written permission is granted by the corresponding\nCopyright Holder. This restriction only applies to the primary font name as\npresented to the users.\n\n4) The name(s) of the Copyright Holder(s) or the Author(s) of the Font\nSoftware shall not be used to promote, endorse or advertise any\nModified Version, except to acknowledge the contribution(s) of the\nCopyright Holder(s) and the Author(s) or with their explicit written\npermission.\n\n5) The Font Software, modified or unmodified, in part or in whole,\nmust be distributed entirely under this license, and must not be\ndistributed under any other license. The requirement for fonts to\nremain under this license does not apply to any document created\nusing the Font Software.\n\nTERMINATION\nThis license becomes null and void if any of the above conditions are\nnot met.\n\nDISCLAIMER\nTHE FONT SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND,\nEXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTIES OF\nMERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT\nOF COPYRIGHT, PATENT, TRADEMARK, OR OTHER RIGHT. IN NO EVENT SHALL THE\nCOPYRIGHT HOLDER BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,\nINCLUDING ANY GENERAL, SPECIAL, INDIRECT, INCIDENTAL, OR CONSEQUENTIAL\nDAMAGES, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\nFROM, OUT OF THE USE OR INABILITY TO USE THE FONT SOFTWARE OR FROM\nOTHER DEALINGS IN THE FONT SOFTWARE.\n\n===========================================================\nWindows Internal Libraries\n===========================================================\n\nMIT License\n\nCopyright (c) Microsoft Corporation. All rights reserved.\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\nof this software and associated documentation files (the \"Software\"), to deal\nin the Software without restriction, including without limitation the rights\nto use, copy, modify, merge, publish, distribute, sublicense, and/or sell\ncopies of the Software, and to permit persons to whom the Software is\nfurnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in all\ncopies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\nFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\nAUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\nLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\nOUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\nSOFTWARE\n\n===========================================================\nbacktrace-js\n===========================================================\n\nCopyright (c) 2016 Backtrace I/O, Inc.\n\nPermission is hereby granted, free of charge, to any person obtaining \na copy of this software and associated documentation files (the \"Software\"), \nto deal in the Software without restriction, including without limitation \nthe rights to use, copy, modify, merge, publish, distribute, sublicense, \nand/or sell copies of the Software, and to permit persons to whom the Software \nis furnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in\n all copies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, \nFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE \nAUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER \nLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, \nOUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN \nTHE SOFTWARE.\n\n===========================================================\nCrashpad\n===========================================================\n\nApache License\nVersion 2.0, January 2004\nhttp://www.apache.org/licenses/\nTERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION\n1. Definitions.\n\"License\" shall mean the terms and conditions for use, reproduction,\nand distribution as defined by Sections 1 through 9 of this document.\n\"Licensor\" shall mean the copyright owner or entity authorized by\nthe copyright owner that is granting the License.\n\"Legal Entity\" shall mean the union of the acting entity and all\nother entities that control, are controlled by, or are under common\ncontrol with that entity. For the purposes of this definition,\n\"control\" means (i) the power, direct or indirect, to cause the\ndirection or management of such entity, whether by contract or\notherwise, or (ii) ownership of fifty percent (50%) or more of the\noutstanding shares, or (iii) beneficial ownership of such entity.\n\"You\" (or \"Your\") shall mean an individual or Legal Entity\nexercising permissions granted by this License.\n\"Source\" form shall mean the preferred form for making modifications,\nincluding but not limited to software source code, documentation\nsource, and configuration files.\n\"Object\" form shall mean any form resulting from mechanical\ntransformation or translation of a Source form, including but\nnot limited to compiled object code, generated documentation,\nand conversions to other media types.\n\"Work\" shall mean the work of authorship, whether in Source or\nObject form, made available under the License, as indicated by a\ncopyright notice that is included in or attached to the work\n(an example is provided in the Appendix below).\n\"Derivative Works\" shall mean any work, whether in Source or Object\nform, that is based on (or derived from) the Work and for which the\neditorial revisions, annotations, elaborations, or other modifications\nrepresent, as a whole, an original work of authorship. For the purposes\nof this License, Derivative Works shall not include works that remain\nseparable from, or merely link (or bind by name) to the interfaces of,\nthe Work and Derivative Works thereof.\n\"Contribution\" shall mean any work of authorship, including\nthe original version of the Work and any modifications or additions\nto that Work or Derivative Works thereof, that is intentionally\nsubmitted to Licensor for inclusion in the Work by the copyright owner\nor by an individual or Legal Entity authorized to submit on behalf of\nthe copyright owner. For the purposes of this definition, \"submitted\"\nmeans any form of electronic, verbal, or written communication sent\nto the Licensor or its representatives, including but not limited to\ncommunication on electronic mailing lists, source code control systems,\nand issue tracking systems that are managed by, or on behalf of, the\nLicensor for the purpose of discussing and improving the Work, but\nexcluding communication that is conspicuously marked or otherwise\ndesignated in writing by the copyright owner as \"Not a Contribution.\"\n\"Contributor\" shall mean Licensor and any individual or Legal Entity\non behalf of whom a Contribution has been received by Licensor and\nsubsequently incorporated within the Work.\n2. Grant of Copyright License. Subject to the terms and conditions of\nthis License, each Contributor hereby grants to You a perpetual,\nworldwide, non-exclusive, no-charge, royalty-free, irrevocable\ncopyright license to reproduce, prepare Derivative Works of,\npublicly display, publicly perform, sublicense, and distribute the\nWork and such Derivative Works in Source or Object form.\n3. Grant of Patent License. Subject to the terms and conditions of\nthis License, each Contributor hereby grants to You a perpetual,\nworldwide, non-exclusive, no-charge, royalty-free, irrevocable\n(except as stated in this section) patent license to make, have made,\nuse, offer to sell, sell, import, and otherwise transfer the Work,\nwhere such license applies only to those patent claims licensable\nby such Contributor that are necessarily infringed by their\nContribution(s) alone or by combination of their Contribution(s)\nwith the Work to which such Contribution(s) was submitted. If You\ninstitute patent litigation against any entity (including a\ncross-claim or counterclaim in a lawsuit) alleging that the Work\nor a Contribution incorporated within the Work constitutes direct\nor contributory patent infringement, then any patent licenses\ngranted to You under this License for that Work shall terminate\nas of the date such litigation is filed.\n4. Redistribution. You may reproduce and distribute copies of the\nWork or Derivative Works thereof in any medium, with or without\nmodifications, and in Source or Object form, provided that You\nmeet the following conditions:\n(a) You must give any other recipients of the Work or\nDerivative Works a copy of this License; and\n(b) You must cause any modified files to carry prominent notices\nstating that You changed the files; and\n(c) You must retain, in the Source form of any Derivative Works\nthat You distribute, all copyright, patent, trademark, and\nattribution notices from the Source form of the Work,\nexcluding those notices that do not pertain to any part of\nthe Derivative Works; and\n(d) If the Work includes a \"NOTICE\" text file as part of its\ndistribution, then any Derivative Works that You distribute must\ninclude a readable copy of the attribution notices contained\nwithin such NOTICE file, excluding those notices that do not\npertain to any part of the Derivative Works, in at least one\nof the following places: within a NOTICE text file distributed\nas part of the Derivative Works; within the Source form or\ndocumentation, if provided along with the Derivative Works; or,\nwithin a display generated by the Derivative Works, if and\nwherever such third-party notices normally appear. The contents\nof the NOTICE file are for informational purposes only and\ndo not modify the License. You may add Your own attribution\nnotices within Derivative Works that You distribute, alongside\nor as an addendum to the NOTICE text from the Work, provided\nthat such additional attribution notices cannot be construed\nas modifying the License.\nYou may add Your own copyright statement to Your modifications and\nmay provide additional or different license terms and conditions\nfor use, reproduction, or distribution of Your modifications, or\nfor any such Derivative Works as a whole, provided Your use,\nreproduction, and distribution of the Work otherwise complies with\nthe conditions stated in this License.\n5. Submission of Contributions. Unless You explicitly state otherwise,\nany Contribution intentionally submitted for inclusion in the Work\nby You to the Licensor shall be under the terms and conditions of\nthis License, without any additional terms or conditions.\nNotwithstanding the above, nothing herein shall supersede or modify\nthe terms of any separate license agreement you may have executed\nwith Licensor regarding such Contributions.\n6. Trademarks. This License does not grant permission to use the trade\nnames, trademarks, service marks, or product names of the Licensor,\nexcept as required for reasonable and customary use in describing the\norigin of the Work and reproducing the content of the NOTICE file.\n7. Disclaimer of Warranty. Unless required by applicable law or\nagreed to in writing, Licensor provides the Work (and each\nContributor provides its Contributions) on an \"AS IS\" BASIS,\nWITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or\nimplied, including, without limitation, any warranties or conditions\nof TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A\nPARTICULAR PURPOSE. You are solely responsible for determining the\nappropriateness of using or redistributing the Work and assume any\nrisks associated with Your exercise of permissions under this License.\n8. Limitation of Liability. In no event and under no legal theory,\nwhether in tort (including negligence), contract, or otherwise,\nunless required by applicable law (such as deliberate and grossly\nnegligent acts) or agreed to in writing, shall any Contributor be\nliable to You for damages, including any direct, indirect, special,\nincidental, or consequential damages of any character arising as a\nresult of this License or out of the use or inability to use the\nWork (including but not limited to damages for loss of goodwill,\nwork stoppage, computer failure or malfunction, or any and all\nother commercial damages or losses), even if such Contributor\nhas been advised of the possibility of such damages.\n9. Accepting Warranty or Additional Liability. While redistributing\nthe Work or Derivative Works thereof, You may choose to offer,\nand charge a fee for, acceptance of support, warranty, indemnity,\nor other liability obligations and/or rights consistent with this\nLicense. However, in accepting such obligations, You may act only\non Your own behalf and on Your sole responsibility, not on behalf\nof any other Contributor, and only if You agree to indemnify,\ndefend, and hold each Contributor harmless for any liability\nincurred by, or claims asserted against, such Contributor by reason\nof your accepting any such warranty or additional liability.\nEND OF TERMS AND CONDITIONS\nAPPENDIX: How to apply the Apache License to your work.\nTo apply the Apache License to your work, attach the following\nboilerplate notice, with the fields enclosed by brackets \"[]\"\nreplaced with your own identifying information. (Don't include\nthe brackets!)  The text should be enclosed in the appropriate\ncomment syntax for the file format. We also recommend that a\nfile or class name and description of purpose be included on the\nsame \"printed page\" as the copyright notice for easier\nidentification within third-party archives.\nCopyright [yyyy] [name of copyright owner]\nLicensed under the Apache License, Version 2.0 (the \"License\");\nyou may not use this file except in compliance with the License.\nYou may obtain a copy of the License at\nhttp://www.apache.org/licenses/LICENSE-2.0\nUnless required by applicable law or agreed to in writing, software\ndistributed under the License is distributed on an \"AS IS\" BASIS,\nWITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\nSee the License for the specific language governing permissions and\nlimitations under the License.\n\n===========================================================\nnlohmann.json\n===========================================================\n\nMIT License \n\nCopyright (c) 2013-2022 Niels Lohmann\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\nof this software and associated documentation files (the \"Software\"), to deal\nin the Software without restriction, including without limitation the rights\nto use, copy, modify, merge, publish, distribute, sublicense, and/or sell\ncopies of the Software, and to permit persons to whom the Software is\nfurnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in all\ncopies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\nFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\nAUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\nLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\nOUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\nSOFTWARE.\n\n===========================================================\nez-steam-api\n===========================================================\n\nMIT No Attribution\n\nCopyright 2023 Jared Krinke\n\nPermission is hereby granted, free of charge, to any person obtaining a copy of\nthis software and associated documentation files (the \"Software\"), to deal in\nthe Software without restriction, including without limitation the rights to\nuse, copy, modify, merge, publish, distribute, sublicense, and/or sell copies\nof the Software, and to permit persons to whom the Software is furnished to do\nso.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\nFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\nAUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\nLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\nOUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\nSOFTWARE.\n\n===========================================================\nKoffi\n===========================================================\n\nMIT License\n\nCopyright 2023 Niels Martignène <niels.martignene@protonmail.com>\n\nPermission is hereby granted, free of charge, to any person obtaining a copy of\nthis software and associated documentation files (the “Software”), to deal in \nthe Software without restriction, including without limitation the rights to use,\ncopy, modify, merge, publish, distribute, sublicense, and/or sell copies of the\nSoftware, and to permit persons to whom the Software is furnished to do so,\nsubject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in all\ncopies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND,\nEXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES\nOF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND\nNONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT\nHOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,\nWHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\nFROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR\nOTHER DEALINGS IN THE SOFTWARE.\n\n===========================================================\nReact\n===========================================================\n\nMIT License\n\nCopyright (c) Meta Platforms, Inc. and affiliates.\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\nof this software and associated documentation files (the \"Software\"), to deal\nin the Software without restriction, including without limitation the rights\nto use, copy, modify, merge, publish, distribute, sublicense, and/or sell\ncopies of the Software, and to permit persons to whom the Software is\nfurnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in all\ncopies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\nFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\nAUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\nLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\nOUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\nSOFTWARE.\n\n===========================================================\nreact-intl / Format.JS\n===========================================================\n\nCopyright 2019 Oath Inc.\nAll rights reserved.\n\nRedistribution and use in source and binary forms, with or without\nmodification, are permitted provided that the following conditions are met:\n\n    * Redistributions of source code must retain the above copyright\n      notice, this list of conditions and the following disclaimer.\n\n    * Redistributions in binary form must reproduce the above copyright\n      notice, this list of conditions and the following disclaimer in the\n      documentation and/or other materials provided with the distribution.\n\n    * Neither the name of the Oath Inc. nor the\n      names of its contributors may be used to endorse or promote products\n      derived from this software without specific prior written permission.\n\nTHIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\" AND\nANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED\nWARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE\nDISCLAIMED. IN NO EVENT SHALL Oath INC. BE LIABLE FOR ANY\nDIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES\n(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;\nLOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND\nON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS\nSOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n\n===========================================================\nElectron\n===========================================================\n\nThe web and primary Steam releases are not based on Electron, but there is a\nport of SIC-1 to Electron. To view the licenses for Electron, open the\n\"LICENSE\" and \"LICENSES.chromium.html\" files that are included in the root of\nthat binary distribution, e.g. \"Steam/steamapps/common/SIC-1/LICENSE\".\n\n`;\n", "sic1/client/ts/data-manager.ts": "import { debug } from \"./setup\";\nimport { Shared } from \"./shared\";\nimport { Platform, PresentationData } from \"./platform\";\nimport { puzzleFlatArray } from \"../../shared/puzzles\";\nimport * as LZString from \"lz-string\";\nimport { LocalizedResources } from \"./resources\";\n\nexport type Inbox = { id: string, read: boolean }[];\n\n// The \"generation\" user data property is used to prompt existing users to enable new features, if desired\nexport const UserDataGenerations = {\n    original: 1,\n    soundEffectsAdded: 2,\n    musicAdded: 3, // Also the initial Steam release\n} as const;\n\nexport const currentUserDataGeneration = UserDataGenerations.musicAdded;\n\n// Mapping from Format to FormatName\nexport const formatToName = [\n    \"numbers\",\n    \"characters\",\n    \"strings\",\n] as const;\n\nexport const formatNameToFormat = Object.fromEntries(formatToName.map((name, format) => [name, format]));\n\nexport type FormatName = typeof formatToName[number];\n\n// Persistent state management\nexport interface UserData {\n    userId?: string;\n    name?: string;\n    introCompleted: boolean;\n    solvedCount: number;\n    currentPuzzle?: string;\n    uploadName?: boolean;\n    inbox?: Inbox;\n    generation?: number;\n    colorScheme?: string;\n    locale?: string;\n\n    tabInsertMode?: boolean;\n    autoIndentMode?: boolean;\n}\n\nexport interface PuzzleSolution {\n    name: string;\n    code?: string;\n\n    customInput?: string;\n    customInputFormat?: FormatName;\n    customOutputFormat?: FormatName;\n\n    solutionCycles?: number;\n    solutionBytes?: number;\n}\n\nexport interface PuzzleData {\n    unlocked: boolean;\n    viewed: boolean;\n    solved: boolean;\n    solutionCycles?: number;\n    solutionBytes?: number;\n\n    // New code format\n    solutions: PuzzleSolution[]; \n    currentSolutionName?: string;\n\n    // Old code format\n    code?: string;\n    customInput?: string;\n    customInputFormat?: FormatName;\n    customOutputFormat?: FormatName;\n}\n\nexport interface AvoisionData {\n    score?: number;\n}\n\nexport class Sic1DataManager {\n    private static readonly userIdLength = 15;\n    private static readonly prefix = Shared.localStoragePrefix;\n\n    private static cache = {};\n\n    private static generateUserId() {\n        const characters = \"abcdefghijklmnopqrstuvwxyz\";\n        let id = \"\";\n        for (var i = 0; i < Sic1DataManager.userIdLength; i++) {\n            id += characters[Math.floor(Math.random() * characters.length)];\n        }\n        return id;\n    }\n\n    private static createDefaultData(): UserData {\n        return {\n            userId: undefined,\n            name: undefined,\n            introCompleted: false,\n            solvedCount: 0,\n            currentPuzzle: undefined,\n            generation: currentUserDataGeneration,\n        };\n    }\n\n    private static createDefaultPuzzleData(): PuzzleData {\n        return {\n            unlocked: false,\n            viewed: false,\n            solved: false,\n            solutionCycles: undefined,\n            solutionBytes: undefined,\n            solutions: [\n                { name: LocalizedResources.defaultSolutionName.getValue() },\n            ],\n            currentSolutionName: LocalizedResources.defaultSolutionName.getValue(),\n        };\n    }\n\n    private static createDefaultPresentationData(): PresentationData {\n        return {\n            fullscreen: false,\n            zoom: 1,\n\n            soundEffects: false,\n            soundVolume: 1,\n\n            music: false,\n            musicVolume: 1,\n        };\n    }\n\n    private static createDefaultAvoisionData(): AvoisionData {\n        return {};\n    }\n\n    private static loadObjectFromStorage<T>(key: string): T {\n        try {\n            const str = localStorage.getItem(key);\n            if (str) {\n                return JSON.parse(str) as T;\n            }\n        } catch (e) {}\n\n        return null;\n    }\n\n    private static loadObjectWithDefault<T>(key: string, defaultDataCreator: () => T, populateAllProperties = false): T {\n        let data = Sic1DataManager.cache[key] as T;\n        if (!data) {\n            data = Sic1DataManager.loadObjectFromStorage<T>(key) || defaultDataCreator();\n            Sic1DataManager.cache[key] = data;\n        }\n\n        if (populateAllProperties) {\n            const defaultData = defaultDataCreator();\n            for (const dataKey of Object.keys(defaultData)) {\n                if (data[dataKey] === undefined) {\n                    data[dataKey] = defaultData[dataKey];\n                }\n            }\n        }\n\n        return data;\n    }\n\n    private static saveObject(key: string): void {\n        try {\n            localStorage.setItem(key, JSON.stringify(Sic1DataManager.cache[key]));\n        } catch (e) {}\n\n        if (Platform.scheduleLocalStoragePersist) {\n            Platform.scheduleLocalStoragePersist();\n        }\n    }\n\n    private static getPuzzleKey(title: string): string {\n        return `${Sic1DataManager.prefix}Puzzle_${title}`;\n    }\n\n    private static getPresentationKey(): string {\n        return `${Sic1DataManager.prefix}_presentation`;\n    }\n\n    private static getAvoisionKey(): string {\n        return `${Sic1DataManager.prefix}_avoision`;\n    }\n\n    private static getKeyList(): string[] {\n        return [\n            // Note: getPresentationKey is skipped because sound/music volume, etc. should be device-specific\n            Sic1DataManager.prefix,\n            Sic1DataManager.getAvoisionKey(),\n            `${Shared.localStoragePrefix}achievements`, // cf. platform.ts\n            ...puzzleFlatArray.map(puzzle => Sic1DataManager.getPuzzleKey(puzzle.title)),\n        ];\n    }\n\n    public static exportData(): string {\n        const data: { [key: string]: any } = {};\n        for (const key of Sic1DataManager.getKeyList()) {\n            const value = Sic1DataManager.loadObjectFromStorage<any>(key);\n            if (value) {\n                data[key] = value;\n            }\n        }\n\n        return LZString.compressToBase64(JSON.stringify(data));\n    }\n\n    public static clearAllDataAsync(): Promise<void> {\n        try {\n            // First, reset the object cache completely\n            Sic1DataManager.cache = {};\n\n            // Delete everything in localStorage\n            for (const key of Sic1DataManager.getKeyList()) {\n                localStorage.removeItem(key);\n            }\n        } catch {}\n        return Promise.resolve();\n    }\n\n    public static async overwriteDataAsync(compressed: string): Promise<void> {\n        const data = JSON.parse(LZString.decompressFromBase64(compressed)) as { [key: string]: any };\n        if (!data) {\n            throw \"No data!\";\n        }\n\n        await Sic1DataManager.clearAllDataAsync();\n\n        // Save everything to localStorage\n        for (const [key, value] of Object.entries(data)) {\n            localStorage.setItem(key, JSON.stringify(value));\n        }\n\n        // Note: Not persisting because overwriteDataAsync is web-only\n    }\n\n    public static getData(): UserData {\n        const state = Sic1DataManager.loadObjectWithDefault<UserData>(Sic1DataManager.prefix, Sic1DataManager.createDefaultData);\n\n        // Ensure user id and name are populated\n        if (debug) {\n            // Use a fixed user name in debug mode, to avoid polluting the production database\n            state.userId = \"abcdefghijklmno\";\n        } else {\n            state.userId = (state.userId && state.userId.length === Sic1DataManager.userIdLength) ? state.userId : Sic1DataManager.generateUserId();\n        }\n\n        // Override name, if necessary\n        state.name = Platform.userNameOverride || state.name;\n        if (state.name && state.name.length > 0) {\n            state.name = state.name.slice(0, 50);\n        }\n\n        return state;\n    }\n\n    public static saveData(): void {\n        Sic1DataManager.saveObject(Sic1DataManager.prefix);\n    }\n\n    public static getPuzzleData(title: string): PuzzleData {\n        const data = Sic1DataManager.loadObjectWithDefault<PuzzleData>(Sic1DataManager.getPuzzleKey(title), Sic1DataManager.createDefaultPuzzleData);\n\n        // Migrate code save format\n        if (data.solutions === undefined) {\n            const { code, customInput, customInputFormat, customOutputFormat } = data;\n\n            data.solutions = [{\n                name: LocalizedResources.defaultSolutionName.getValue(),\n                code,\n                customInput,\n                customInputFormat,\n                customOutputFormat,\n            }];\n\n            data.code = undefined;\n            data.customInput = undefined;\n            data.customInputFormat = undefined;\n            data.customOutputFormat = undefined;\n        }\n\n        return data;\n    }\n\n    public static getPuzzleDataAndSolution(title: string, solutionName: string, allowFallback: boolean): { puzzleData: PuzzleData, solution?: PuzzleSolution } {\n        const puzzleData = Sic1DataManager.getPuzzleData(title);\n        let solution: PuzzleSolution | undefined;\n        if (!puzzleData.solutions || (puzzleData.solutions.length === 0)) {\n            if (allowFallback) {\n                // No solutions exist; create a default one and return that\n                solution = { name: LocalizedResources.defaultSolutionName.getValue() };\n                puzzleData.solutions = [solution];\n            }\n        } else {\n            // Find the named solution\n            if (solutionName) {\n                solution = puzzleData.solutions.find(s => s.name === solutionName);\n            }\n\n            if (!solution && allowFallback) {\n                // Couldn't find the named solution (or no name provided); just return the first one\n                solution = puzzleData.solutions[0];\n            }\n        }\n\n        return {\n            puzzleData,\n            solution,\n        };\n    }\n\n    public static savePuzzleData(title: string): void {\n        Sic1DataManager.saveObject(Sic1DataManager.getPuzzleKey(title));\n    }\n\n    public static getPresentationData(): PresentationData {\n        if (Platform.presentationSettings) {\n            return Platform.presentationSettings;\n        } else {\n            return Sic1DataManager.loadObjectWithDefault<PresentationData>(Sic1DataManager.getPresentationKey(), Sic1DataManager.createDefaultPresentationData, true);\n        }\n    }\n\n    public static savePresentationData(): void {\n        if (Platform.presentationSettings) {\n            Platform.schedulePresentationSettingsPersist!();\n        } else {\n            Sic1DataManager.saveObject(Sic1DataManager.getPresentationKey());\n        }\n    }\n\n    public static getAvoisionData(): AvoisionData {\n        return Sic1DataManager.loadObjectWithDefault<AvoisionData>(Sic1DataManager.getAvoisionKey(), Sic1DataManager.createDefaultAvoisionData);\n    }\n\n    public static saveAvoisionData(): void {\n        Sic1DataManager.saveObject(Sic1DataManager.getAvoisionKey());\n    }\n}\n", "sic1/client/ts/button-clipboard.tsx": "import React from \"react\";\nimport { ButtonWithResult } from \"./button-result\";\nimport { FormattedMessage, IntlShape } from \"react-intl\";\n\nexport class CopyToClipboardButton extends React.Component<{ intl: IntlShape, text: string }> {\n    public render(): React.ReactNode {\n        return <ButtonWithResult\n            onClickAsync={() => navigator?.clipboard?.writeText?.(this.props.text)}\n            successMessage={this.props.intl.formatMessage({\n                id: \"textCopySucceeded\",\n                description: \"Message printed after copying text to the clipboard succeeds (only used on the web version)\",\n                defaultMessage: \"Copied to the clipboard!\",\n            })}\n            errorMessage={this.props.intl.formatMessage({\n                id: \"textCopyFailed\",\n                description: \"Message shown when copying text to the clipboard fails (only used on the web version)\",\n                defaultMessage: \"Error: Failed to copy to the clipboard.\",\n            })}\n            ><FormattedMessage\n                id=\"buttonCopyToClipboard\"\n                description=\"Text shown on the 'copy text to clipboard' button (only used on the web version)\"\n                defaultMessage=\"Copy to Clipboard\"\n                />\n            </ButtonWithResult>;\n    }\n}\n", "sic1/client/ts/ide-code-view.tsx": "import React from \"react\";\nimport { Gutter } from \"./ide-gutter\";\nimport { ClientPuzzle } from \"./puzzles\";\n\nexport interface Sic1CodeViewProps {\n    puzzle: ClientPuzzle;\n    solutionName: string;\n    defaultCode: string;\n\n    autoIndentMode: boolean;\n    tabInsertMode: boolean;\n\n    hasStarted: boolean;\n    sourceLines: string[];\n    sourceLineToBreakpointState: { [lineNumber: number]: boolean };\n    currentAddress: number | null;\n    currentSourceLine?: number;\n\n    onSave: () => void;\n    onToggleBreakpoint: (lineNumber: number) => void;\n    onToggleTabInsertMode: () => void;\n}\n\ninterface Sic1CodeViewUpdateSnapshot {\n    scrollTop?: number;\n    scrollLeft?: number;\n}\n\nexport class Sic1CodeView extends React.Component<Sic1CodeViewProps> {\n    private static readonly initialCommentPattern = /^\\s*;\\s?/;\n    private static readonly initialIndentPattern = /^(\\t|    )/;\n    private static readonly indentPattern = /^\\s*/;\n\n    private inputCode = React.createRef<HTMLTextAreaElement>();\n    private gutter = React.createRef<Gutter>();\n    private div = React.createRef<HTMLDivElement>();\n    private lastAddress?: number;\n    private keyboardSequenceStarted = false;\n    private hadFocusPriorToDebugging = false;\n    private focusOnUpdate = false;\n\n    constructor(props) {\n        super(props);\n    }\n\n    private manipulateSelectedLines(manipulate: (line: string) => string): void {\n        const textArea = this.inputCode.current;\n        if (textArea) {\n            // Find the beginning and end\n            const { selectionStart, selectionEnd, value } = textArea;\n            if (value.length > 0 && selectionStart >= 0 && selectionEnd >= 0) {\n                const lineStart = value.lastIndexOf(\"\\n\", selectionStart - 1) + 1;\n                let lineEnd = (selectionStart === selectionEnd)\n                    ? value.indexOf(\"\\n\", selectionEnd)\n                    : value.indexOf(\"\\n\", selectionEnd - 1); // -1 in case cursor is at the beginning of a line (we don't want to comment the \"unselected\" line)\n\n                if (lineEnd < 0) {\n                    lineEnd = value.length;\n                }\n\n                // Apply the transformation line-by-line\n                const lines = value.substring(lineStart, lineEnd).split(\"\\n\");\n                const updatedSelection = lines.map(line => manipulate(line)).join(\"\\n\");\n\n                // Move focus to the text area to ensure selection works even when activated via an external button\n                const previousFocus = document.activeElement;\n                if (previousFocus !== textArea) {\n                    textArea.focus();\n                }\n\n                // Update the region\n                const cursorAtStart = (selectionStart === selectionEnd) && lines.length === 1;\n                textArea.setRangeText(updatedSelection, lineStart, lineEnd, cursorAtStart ? \"start\" : \"preserve\");\n\n                if (previousFocus !== textArea) {\n                    previousFocus?.[\"focus\"]?.();\n                }\n            }\n        }\n    }\n\n    public reset(): void {\n        this.lastAddress = undefined;\n    }\n\n    public focusIfNeeded(): void {\n        if (this.props.hasStarted) {\n            // Currently debugging; queue a focus update, if needed\n            if (this.hadFocusPriorToDebugging) {\n                this.focusOnUpdate = true;\n            }\n        } else {\n            // Currently editing; focus the textarea\n            this.inputCode.current?.focus?.();\n        }\n    }\n\n    public getCode(): string {\n        return this.inputCode.current?.value;\n    }\n\n    public selectLine(sourceLineNumber: number, content: string): void {\n        const textArea = this.inputCode.current\n        if (textArea) {\n            const code = textArea.value;\n            let position = 0;\n            let line = 1;\n            while (line < sourceLineNumber && position >= 0 && position < code.length) {\n                position = code.indexOf(\"\\n\", position) + 1;\n                ++line;\n            }\n\n            textArea.setSelectionRange(position, position + content.length);\n        }\n    }\n\n    public blockComment(): void {\n        this.manipulateSelectedLines(line => \"; \" + line);\n    }\n\n    public blockUncomment(): void {\n        this.manipulateSelectedLines(line => line.replace(Sic1CodeView.initialCommentPattern, \"\"));\n    }\n\n    public indentLines(): void {\n        this.manipulateSelectedLines(line => \"\\t\" + line);\n    }\n\n    public unindentLines(): void {\n        this.manipulateSelectedLines(line => line.replace(Sic1CodeView.initialIndentPattern, \"\"));\n    }\n\n    public getSnapshotBeforeUpdate(previousProps: Readonly<Sic1CodeViewProps>, previousState: Readonly<{}>): Sic1CodeViewUpdateSnapshot {\n        if (previousProps.hasStarted !== this.props.hasStarted) {\n            // Switched between editing and debugging; preserve scroll position\n            const source = (previousProps.hasStarted) ? this.div.current : this.inputCode.current;\n            if (source) {\n                const { scrollTop, scrollLeft } = source;\n                return {\n                    scrollTop,\n                    scrollLeft,\n                }\n            }\n        }\n\n        return {};\n    }\n\n    public componentDidUpdate(previousProps: Readonly<Sic1CodeViewProps>, previousState: Readonly<{}>, snapshot: Sic1CodeViewUpdateSnapshot): void {\n        if (this.lastAddress !== this.props.currentAddress && this.gutter.current) {\n            if (snapshot.scrollTop === undefined) {\n                this.gutter.current.scrollCurrentSourceLineIntoView();\n            }\n\n            this.lastAddress = this.props.currentAddress;\n        }\n\n        if (snapshot.scrollTop !== undefined) {\n            // Switched between editing and debugging; restore scroll position (and focus, if needed)\n            if (this.props.hasStarted) {\n                this.div.current.scrollTop = snapshot.scrollTop ?? this.div.current.scrollTop;\n                this.div.current.scrollLeft = snapshot.scrollLeft ?? this.div.current.scrollLeft;\n\n                // Check to see if textarea was focused, so it can be restored later\n                this.hadFocusPriorToDebugging = (document.activeElement === this.inputCode.current);\n            } else {\n                this.inputCode.current.scrollTop = snapshot.scrollTop ?? this.inputCode.current.scrollTop;\n                this.inputCode.current.scrollLeft = snapshot.scrollLeft ?? this.inputCode.current.scrollLeft;\n\n                // No longer debugging; refocus the textarea, if needed\n                if (this.focusOnUpdate) {\n                    this.inputCode.current.focus();\n                    this.focusOnUpdate = false;\n                }\n            }\n        }\n    }\n\n    public render(): React.ReactNode {\n        return <div ref={this.div} className=\"program\">\n            <Gutter\n                ref={this.gutter}\n                hasStarted={this.props.hasStarted}\n                currentSourceLine={this.props.currentSourceLine}\n                sourceLines={this.props.sourceLines}\n                sourceLineToBreakpointState={this.props.sourceLineToBreakpointState}\n                onToggleBreakpoint={(lineNumber) => this.props.onToggleBreakpoint(lineNumber)}\n                />\n            <textarea\n                ref={this.inputCode}\n                className={\"input\" + (this.props.hasStarted ? \" hidden\" : \"\")}\n                spellCheck={false}\n                wrap=\"off\"\n                defaultValue={this.props.defaultCode}\n                onBlur={(e) => {\n                    // Work around onBlur apparently being called on unmount...\n                    if (this.inputCode.current) {\n                        this.props.onSave();\n                    }\n\n                    this.keyboardSequenceStarted = false;\n                }}\n                onKeyDown={(event) => {\n                    if (event.ctrlKey || event.metaKey) {\n                        if (this.keyboardSequenceStarted) {\n                            switch (event.key) {\n                                case \"c\":\n                                    this.blockComment();\n                                    event.preventDefault();\n                                    break;\n\n                                case \"u\":\n                                    this.blockUncomment();\n                                    event.preventDefault();\n                                    break;\n                            }\n\n                            this.keyboardSequenceStarted = false;\n                        } else {\n                            switch (event.key) {\n                                case \"k\":\n                                    // Ctrl+K starts a keyboard shortcut sequence\n                                    this.keyboardSequenceStarted = true;\n                                    event.preventDefault();\n                                    break;                                \n                                \n                                case \"m\":\n                                    // Ctrl+M toggles tab capture\n                                    this.props.onToggleTabInsertMode();\n                                    event.preventDefault();\n                                    break;\n                            }\n                        }\n                    } else if (event.key === \"Tab\") {\n                        const textArea = this.inputCode.current;\n                        if (this.props.tabInsertMode && textArea) {\n                            if (event.shiftKey) {\n                                // Shift+Tab to un-indent\n                                this.unindentLines();\n                            } else {\n                                const { selectionStart, selectionEnd } = textArea;\n                                if (selectionStart === selectionEnd) {\n                                    // Tab with no selection, not at beginning of line; just insert the tab character\n                                    textArea.setRangeText(\"\\t\", selectionStart, selectionEnd, \"end\");\n                                } else {\n                                    // Tab with selection or beginning of line; indent selected lines\n                                    this.indentLines();\n                                }\n                            }\n                            event.preventDefault();\n                        }\n                    } else if (event.key === \"Enter\") {\n                        const textArea = this.inputCode.current;\n                        if (textArea && this.props.autoIndentMode) {\n                            const { selectionStart, selectionEnd, value } = textArea;\n                            if (selectionStart > 0 && selectionStart === selectionEnd) {\n                                const lastNewlineIndex = value.lastIndexOf(\"\\n\", selectionStart - 1) + 1;\n                                if (lastNewlineIndex > 0) {\n                                    const previousLineIndent = Sic1CodeView.indentPattern.exec(value.substring(lastNewlineIndex, selectionStart))?.[0];\n                                    if (previousLineIndent) {\n                                        textArea.setRangeText(\"\\n\" + previousLineIndent, selectionStart, selectionEnd, \"end\");\n                                        event.preventDefault();\n                                    }\n                                }\n                            }\n                        }\n                    }\n                }}\n                ></textarea>\n            <div className={\"source\" + (this.props.hasStarted ? \"\" : \" hidden\")}>\n                {\n                    this.props.sourceLines.map((line, index) => {\n                        if (/\\S/.test(line)) {\n                            const currentLine = (index === this.props.currentSourceLine);\n                            return currentLine\n                                ? <div key={index} className=\"emphasize\">{line}</div>\n                                : <div key={index}>{line}</div>;\n                        } else {\n                            return <br key={index} />\n                        }\n                    })\n                }\n            </div>\n        </div>\n        ;\n    }\n}\n", "sic1/client/ts/puzzle-list.tsx": "import React from \"react\";\nimport { Browser, BrowserIndices, BrowserItem } from \"./browser\";\nimport { Chart } from \"./chart\";\nimport { PuzzleData, Sic1DataManager, UserData } from \"./data-manager\";\nimport { FriendLeaderboard } from \"./friend-leaderboard\";\nimport { Platform } from \"./platform\";\nimport { FriendLeaderboardEntry, PuzzleFriendLeaderboardPromises } from \"./service\";\nimport { Shared } from \"./shared\";\nimport { Sic1UserStats } from \"./user-stats\";\nimport { achievements } from \"./achievements\";\nimport { ClientPuzzle, ClientPuzzleGroup, hasCustomInput } from \"./puzzles\";\nimport { SolutionManager } from \"./solution-manager\";\nimport { MessageBoxContent } from \"./message-box\";\nimport { FormattedMessage, FormattedNumber, IntlShape } from \"react-intl\";\nimport { formatContact } from \"./contacts\";\n\nexport type PuzzleListTypes = \"puzzle\" | \"userStats\" | \"achievements\" | \"avoision\";\n\ninterface PuzzleInfo {\n    key: string;\n    type: Extract<PuzzleListTypes, \"puzzle\">;\n    title: React.ReactNode; // NOTE: This is the display title and *not* necessarily the puzzle title! E.g. it may include \" (INCOMPLETE)\"\n    description: string;\n    puzzle: ClientPuzzle;\n    puzzleData: PuzzleData;\n}\n\ntype NonPuzzleTypes = Exclude<PuzzleListTypes, \"puzzle\">;\n\ntype NonPuzzleInfo = BrowserItem & {\n    type: NonPuzzleTypes;\n}\n\ninterface PuzzleGroupInfo {\n    title: React.ReactNode;\n    items: PuzzleInfo[];\n}\n\ninterface GroupInfo {\n    key: string;\n    title: React.ReactNode;\n    items: (PuzzleInfo | NonPuzzleInfo)[];\n}\n\nfunction filterUnlockedPuzzleList(list: ClientPuzzle[]): PuzzleInfo[] {\n    const data = Sic1DataManager.getData();\n    return list\n        .map(puzzle => {\n            const puzzleData = Sic1DataManager.getPuzzleData(puzzle.title);\n\n            // Check for unlock\n            if (!puzzleData.unlocked) {\n                if (data.solvedCount >= puzzle.minimumSolvedToUnlock) {\n                    puzzleData.unlocked = true;\n                    Sic1DataManager.savePuzzleData(puzzle.title);\n                }\n            }\n\n            if (puzzleData.unlocked) {\n                return {\n                    type: \"puzzle\" as const,\n                    key: puzzle.title,\n                    title: puzzle.displayTitle,\n                    description: puzzle.description,\n                    puzzle,\n                    puzzleData,\n                };\n            }\n            return null;\n        })\n        .filter(puzzleInfo => !!puzzleInfo);\n}\n\nfunction filterUnlockedPuzzles(clientPuzzlesGrouped: ClientPuzzleGroup[]): PuzzleGroupInfo[] {\n    return clientPuzzlesGrouped.map(group => ({\n        title: group.groupTitle,\n        items: filterUnlockedPuzzleList(group.list),\n    })).filter(groupInfo => (groupInfo.items.length > 0));\n}\n\nexport function createPuzzleCharts(puzzleTitle: string, cycles: number, bytes: number, leaderboardPromises?: PuzzleFriendLeaderboardPromises): React.ReactNode {\n    const promise = Platform.service.getPuzzleStatsAsync(puzzleTitle, cycles, bytes);\n\n    return <div className=\"charts\">\n        <Chart title={<FormattedMessage\n            id=\"chartTitleCycles\"\n            description=\"Title for a 'cycles executed' chart\"\n            defaultMessage=\"Cycles Executed: {cycles}\"\n            values={{ cycles }}\n            />} promise={(async () => (await promise).cycles)()} />\n        <Chart title={<FormattedMessage\n            id=\"chartTitleBytes\"\n            description=\"Title for a 'bytes read' chart\"\n            defaultMessage=\"Bytes Read: {bytes}\"\n            values={{ bytes }}\n            />} promise={(async () => (await promise).bytes)()} />\n        {\n            Platform.service.getPuzzleFriendLeaderboardAsync\n                ? <>\n                    <br/>\n                    <FriendLeaderboard\n                        title={<FormattedMessage\n                            id=\"chartFriendCycles\"\n                            description=\"Title of friend leaderboard for 'cycles executed'\"\n                            defaultMessage=\"Cycles Executed (Friends)\"\n                            />}\n                        promise={leaderboardPromises ? leaderboardPromises.cycles : Platform.service.getPuzzleFriendLeaderboardAsync(puzzleTitle, \"cycles\")} />\n                    <FriendLeaderboard\n                        title={<FormattedMessage\n                            id=\"chartFriendBytes\"\n                            description=\"Title of friend leaderboard for 'bytes read'\"\n                            defaultMessage=\"Bytes Read (Friends)\"\n                            />}\n                        promise={leaderboardPromises ? leaderboardPromises.bytes : Platform.service.getPuzzleFriendLeaderboardAsync(puzzleTitle, \"bytes\")} />\n                </>\n                : null\n        }\n    </div>;\n}\n\ninterface PuzzleViewProps {\n    intl: IntlShape;\n    puzzleInfo: PuzzleInfo;\n    data: UserData;\n    onLoadPuzzleRequested: (puzzle: ClientPuzzle, solutionName: string) => void;\n    onShowMessageBox: (content: MessageBoxContent) => void;\n    onCloseMessageBox: () => void;\n}\n\nclass PuzzleView extends React.Component<PuzzleViewProps, { solutionName?: string }> {\n    constructor(props) {\n        super(props);\n\n        let solutionName = this.props.puzzleInfo.puzzleData.currentSolutionName;\n        if (!solutionName || !this.props.puzzleInfo.puzzleData.solutions || !this.props.puzzleInfo.puzzleData.solutions.find(s => s.name === solutionName)) {\n            // No solution name set or no solutions or solution name doesn't exist; use the first name, if any\n            solutionName = this.props.puzzleInfo.puzzleData.solutions[0]?.name;\n        }\n\n        this.state = { solutionName };\n    }\n\n    public getSelectedSolutionName(): string | undefined {\n        return this.state.solutionName;\n    }\n\n    public render(): React.ReactNode {\n        const { puzzleInfo, data } = this.props;\n        const { title, description, puzzleData } = puzzleInfo;\n        return <>\n            <header>\n            <FormattedMessage\n                    id=\"taskViewerTaskHeading\"\n                    description=\"Heading content markup shown in the program inventory/task viewer for a particular task; use {newline} at the end of each line; note that {statusLine} is empty for Sandbox Mode\"\n                    defaultMessage=\"<cap>User</cap>: {name}{newline}<cap>Task</cap>: {title}{newline}{statusLine}{newline}{newline}<cap>Description</cap>: {description}\"\n                    values={{\n                        newline: <br/>,\n                        name: formatContact({\n                                name: data.name,\n                                title: Shared.getJobTitleForSolvedCount(data.solvedCount),\n                            }),\n                        title,\n                        description,\n                        statusLine: hasCustomInput(puzzleInfo.puzzle)\n                            ? null\n                            : <FormattedMessage\n                                id=\"taskViewerStatusLine\"\n                                description=\"Line for status of the task heading shown in the task viewer\"\n                                defaultMessage=\"<cap>Status</cap>: <cap>{status}</cap>\"\n                                values={{\n                                    status: puzzleData.solved\n                                        ? <FormattedMessage\n                                            id=\"taskViewerStatusCompleted\"\n                                            description=\"Status shown when a task has been completed\"\n                                            defaultMessage=\"Completed\"\n                                            />\n                                        : Shared.resources.taskStatusIncomplete\n                                }}\n                                />,\n                    }}\n                    />\n            </header>\n            {puzzleInfo.puzzle.puzzleViewOverride ?? <>\n                {(puzzleData.solved\n                    ? <>\n                        <p>{Shared.resources.taskStatistics}</p>\n                        {createPuzzleCharts(puzzleInfo.puzzle.title, puzzleData.solutionCycles, puzzleData.solutionBytes)}\n                    </>\n                    : <>\n                        <p>\n                            <FormattedMessage\n                                id=\"taskViewerTextIncomplete\"\n                                description=\"Text shown in the task selector when a task has not been successfully implemented yet\"\n                                defaultMessage={\"You have not implemented this program yet. Click \\\"Load This Program\\\" at the bottom of this window to load the program into the editor.\"}\n                                />\n                        </p>\n                </>)}\n            </>}\n            <h3>\n                <FormattedMessage\n                    id=\"taskViewerHeadingFile\"\n                    description=\"Heading for the 'file selection' (save management) part of a task\"\n                    defaultMessage=\"File Selection\"\n                    />\n            </h3>\n            <SolutionManager\n                intl={this.props.intl}\n                puzzleTitle={puzzleInfo.puzzle.title}\n                solutionName={this.state.solutionName}\n                onSelectionChanged={(solutionName) => this.setState({ solutionName })}\n                onOpen={(solutionName) => this.props.onLoadPuzzleRequested(puzzleInfo.puzzle, solutionName)}\n                onShowMessageBox={(content) => this.props.onShowMessageBox(content)}\n                onCloseMessageBox={() => this.props.onCloseMessageBox()}\n                />\n        </>;\n    }\n}\n\nclass UserHeading extends React.Component<{ data: UserData }> {\n    public render(): React.ReactNode {\n        const { data } = this.props;\n        return <FormattedMessage\n            id=\"taskViewerHeadingUser\"\n            description=\"Markup for the heading shown on a user-specific page of the program inventory/task viewer; use {newline} in between lines\"\n            defaultMessage=\"<cap>User</cap>: {name}{newline}<cap>Title</cap>: {title}\"\n            values={{\n                newline: <br/>,\n                name: data.name,\n                title: Shared.getJobTitleForSolvedCount(data.solvedCount),\n            }}\n            />;\n    }\n}\n\nclass UserStatsView extends React.Component<{ data: UserData }> {\n    public render(): React.ReactNode {\n        const { data } = this.props;\n        return <>\n            <header>\n                <UserHeading data={data}/>\n            </header>\n            <FormattedMessage\n                id=\"taskViewerMotivation\"\n                description=\"Motivational message from employer introducing task completion statistics\"\n                defaultMessage=\"<p>SIC Systems appreciates your continued effort.</p><p>For motivational purposes, here is how the number of tasks you have completed compares to other engineers.</p>\"\n                />\n            <Sic1UserStats promise={(async () => {\n                const chartData = await Platform.service.getUserStatsAsync(data.userId, data.solvedCount);\n                return chartData;\n            })()} />\n        </>;\n    }\n}\n\nclass AchievementSummary extends React.Component<{ promises: Promise<boolean>[] }, { achievedCount?: number | null }> {\n    public constructor(props) {\n        super(props);\n        this.state = {};\n    }\n\n    public async componentDidMount() {\n        let achievedCount = 0;\n        try {\n            for (const achieved of await Promise.all(this.props.promises)) {\n                if (achieved) {\n                    achievedCount++;\n                }\n            }\n\n            this.setState({ achievedCount });\n        } catch {\n            this.setState({ achievedCount: null });\n        }\n    }\n\n    public render(): React.ReactNode {\n        const achievementCount = this.props.promises.length;\n        const { achievedCount } = this.state;\n        switch (achievedCount) {\n            case undefined: return <span>{Shared.resources.loading}</span>;\n            case null: return <span>{Shared.resources.loadFailed}</span>;\n            default:\n                return <>\n                    <FormattedMessage\n                        id=\"achievementProgressDetail\"\n                        description=\"Achievement progress expressed numerically\"\n                        defaultMessage=\"{achievedCount} of {achievementCount} ({percent})\"\n                        values={{\n                            achievedCount,\n                            achievementCount,\n                            percent: <FormattedNumber\n                                value={achievedCount / achievementCount}\n                                style=\"percent\"\n                                />\n                        }}\n                        />\n                    </>;\n        }\n    }\n}\n\nclass AchievementIcon extends React.Component<{ imageUri: string, promise: Promise<boolean> }, { achieved: boolean }> {\n    public constructor(props) {\n        super(props);\n        this.state = { achieved: false };\n    }\n\n    public async componentDidMount() {\n        try {\n            const achieved = await this.props.promise;\n            this.setState({ achieved });\n        } catch {\n            // Assume not achieved\n        }\n    }\n\n    public render(): React.ReactNode {\n        return <img src={this.state.achieved ? this.props.imageUri : Shared.blankImageDataUri} width={64} height={64}/>;\n    }\n}\n\nclass AchievementsView extends React.Component<{ data: UserData }> {\n    public render(): React.ReactNode {\n        const promises: Promise<boolean>[] = [];\n        const idToPromise: { [id: string]: Promise<boolean> } = {};\n        for (const [id, achievement] of Object.entries(achievements)) {\n            const promise = Platform.getAchievementAsync?.(id) ?? Promise.resolve(false);\n            idToPromise[id] = promise;\n            promises.push(promise);\n        }\n        \n        const { data } = this.props;\n        return <>\n            <header>\n                <UserHeading data={data}/>\n            </header>\n            <h3>\n                <FormattedMessage\n                    id=\"achievementProgressLine\"\n                    description=\"Line of text summarizing achievement progress\"\n                    defaultMessage=\"Achievement Progress: {summary}\"\n                    values={{\n                        summary: <AchievementSummary promises={promises}/>\n                    }}\n                    />\n            </h3>\n            <table className=\"achievements\">\n                <tbody>\n                    {Object.entries(achievements).map(([id, a]) => <tr key={id}><td>\n                        <div className=\"achievement\">\n                            <AchievementIcon imageUri={a.imageUri} promise={idToPromise[id]}/>\n                            <div>\n                                <p className=\"title\">{a.title}</p>\n                                <p>{a.description}</p>\n                            </div>\n                        </div>\n                    </td></tr>)}\n                </tbody>\n            </table>\n        </>;\n    }\n}\n\ninterface AvoisionViewProps {\n    intl: IntlShape;\n    data: UserData;\n}\n\nclass AvoisionView extends React.Component<AvoisionViewProps> {\n    private static getDefaultScores(intl: IntlShape): FriendLeaderboardEntry[] {\n        return [\n            {\n                name: intl.formatMessage({\n                    id: \"avoisionDefaultScore1\",\n                    description: \"Name of the top scorer for the default scores in Avoision\",\n                    defaultMessage: \"Jerin\",\n                }),\n                score: 249,\n            },\n            {\n                name: intl.formatMessage({\n                    id: \"avoisionDefaultScore2\",\n                    description: \"Name of the second-to-top scorer for the default scores in Avoision\",\n                    defaultMessage: \"Pat\",\n                }),\n                score: 214,\n            },\n            {\n                name: intl.formatMessage({\n                    id: \"avoisionDefaultScore3\",\n                    description: \"Name of the third-to-top scorer for the default scores in Avoision\",\n                    defaultMessage: \"Ted\",\n                }),\n                score: 164,\n            },\n        ];\n    }\n\n    private static mergeSortAndDedupe(...arrays: FriendLeaderboardEntry[][]): FriendLeaderboardEntry[] {\n        const result: FriendLeaderboardEntry[] = [];\n        for (const array of arrays) {\n            for (const entry of array) {\n                result.push(entry);\n            }\n        }\n\n        // Sort and remove duplicates\n        result.sort((a, b) => ((b.score - a.score) || a.name.localeCompare(b.name)));\n        for (let i = 1; i < result.length; i++) {\n            const p = result[i - 1];\n            const c = result[i];\n            if (p.name === c.name && p.score === c.score) {\n                result.splice(i--, 1);\n            }\n        }\n        return result;\n    }\n\n    public render(): React.ReactNode {\n        const { data } = this.props;\n        const name = Sic1DataManager.getData().name;\n        const defaultScores = AvoisionView.getDefaultScores(this.props.intl);\n        const localHighScore = Sic1DataManager.getAvoisionData().score;\n        const localScores = localHighScore ? [{ name, score: localHighScore }] : [];\n        \n        const promise = Platform.service.getFriendLeaderboardAsync\n            ? (async () => AvoisionView.mergeSortAndDedupe(\n                defaultScores,\n                localScores,\n                await Platform.service.getFriendLeaderboardAsync(\"Avoision\")\n                ))()\n            : Promise.resolve(AvoisionView.mergeSortAndDedupe(\n                defaultScores,\n                localScores,\n                ));\n\n        return <>\n            <header>\n                <FormattedMessage\n                    id=\"taskViewerHeadingAvoision\"\n                    description=\"Markup for the heading shown for Avoision in the task viewer; use {newline} in between lines\"\n                    defaultMessage=\"<cap>User</cap>: {name}{newline}<cap>Program</cap>: Avoision\"\n                    values={{\n                        newline: <br/>,\n                        name: formatContact({\n                            name: data.name,\n                            title: Shared.getJobTitleForSolvedCount(data.solvedCount)\n                        }),\n                    }}\n                    />\n            </header>\n            <FormattedMessage\n                id=\"taskContentAvoision\"\n                description=\"Markup for the 'Avoision' page in the task viewer\"\n                defaultMessage={`<p>To help improve morale, SIC Systems has provided an officially sanctioned computer video game called \"Avoision\" for employees to play. If you think your work would benefit from an entertaining diversion, please feel free to compete against your coworkers for the highest score in \"Avoision\" (during your two legally-mandated unpaid breaks, or in lieu of an unneeded bathroom break).</p>\n<h3>Instructions</h3>\n<p>Use the arrow keys to move your bright green block and try to capture the bright green square. The faster you capture the square, the more points you will score.</p>\n<p>As you progress, moving dark green blocks will appear. If your bright green block collides with a dark green block, the game is over.</p>\n<p>Click the \"Play Avoision\" button below to play.</p>`}\n                />\n            <br/>\n            <div className=\"charts\">\n                <FriendLeaderboard\n                    title={<FormattedMessage\n                        id=\"chartFriendAvoision\"\n                        description=\"Title of friend leaderboard chart for Avoision high scores\"\n                        defaultMessage=\"Avoision High Scores\"\n                        />}\n                    promise={promise}\n                    />\n            </div>\n        </>;\n    }\n}\n\nexport type PuzzleListNextPuzzle = \"continue\" | \"nextUnsolved\" | \"none\";\n\nexport interface PuzzleListProps {\n    intl: IntlShape;\n    clientPuzzlesGrouped: ClientPuzzleGroup[];\n    puzzleSandbox: ClientPuzzle;\n    initialItemType?: PuzzleListTypes;\n    initialItemTitle?: string;\n    nextPuzzle?: ClientPuzzle;\n    hasUnreadMessages: boolean;\n    currentPuzzleIsSolved: boolean;\n\n    onLoadPuzzleRequested: (puzzle: ClientPuzzle, solutionName: string) => void;\n    onOpenMailViewerRequested: () => void;\n    onClearMessageBoxRequested: () => void;\n    onPlayAvoisionRequested: () => void;\n    onShowMessageBox: (content: MessageBoxContent) => void;\n    onCloseMessageBox: () => void;\n}\n\ninterface PuzzleListState {\n    groups: GroupInfo[];\n    selection: BrowserIndices;\n}\n\nexport class PuzzleList extends React.Component<PuzzleListProps, PuzzleListState> {\n    private puzzleView = React.createRef<PuzzleView>();\n\n    constructor(props) {\n        super(props);\n        const unlocked = filterUnlockedPuzzles(props.clientPuzzlesGrouped);\n\n        // Hard-code a group for user statistics, etc.\n        const groups: GroupInfo[] = [\n            {\n                key: \"progress\",\n                title: <FormattedMessage\n                    id=\"headingProgress\"\n                    description=\"Heading for 'task progress' and 'achievements' group in the program inventory/task selector window\"\n                    defaultMessage=\"Employee Statistics\"\n                    />,\n                items: [\n                    {\n                        type: \"userStats\",\n                        key: \"userStats\",\n                        title: <FormattedMessage\n                            id=\"taskProgress\"\n                            description=\"Title of the 'task progress' item in the program inventory/task selector window\"\n                            defaultMessage=\"Task Progress\"\n                            />,\n                        buttons: [\n                            ...(this.props.hasUnreadMessages\n                                ? [\n                                    {\n                                        title: <FormattedMessage\n                                            id=\"taskViewerButtonViewUnread\"\n                                            description=\"Text on button for viewing unread mail\"\n                                            defaultMessage=\"View Unread Electronic Mail\"\n                                            />,\n                                        intent: \"viewUnreadMail\",\n                                        onClick: () => this.props.onOpenMailViewerRequested(),\n                                    }\n                                ]\n                                : []),\n                            ...(this.props.currentPuzzleIsSolved\n                                ? (this.props.nextPuzzle\n                                    ? [\n                                        {\n                                            title: <FormattedMessage\n                                                id=\"taskViewerButtonNextIncompleteTask\"\n                                                description=\"Text on button for viewing the next incomplete task\"\n                                                defaultMessage=\"View Next Incomplete Task\"\n                                                />,\n                                            intent: \"viewNextIncomplete\",\n                                            onClick: () => this.setState(state => ({ selection: this.findIndices(state.groups, \"puzzle\", this.props.nextPuzzle.title) })),\n                                        }\n                                    ]\n                                    : [])\n                                : [\n                                    {\n                                        title: <FormattedMessage\n                                            id=\"taskViewerButtonContinueEditing\"\n                                            description=\"Text on button for continuing editing the current program\"\n                                            defaultMessage=\"Continue Editing Current Program\"\n                                            />,\n                                        intent: \"continueEditing\",\n                                        onClick: () => this.props.onClearMessageBoxRequested(),\n                                    }\n                                ]),\n                        ],\n                    },\n                    {\n                        type: \"achievements\",\n                        key: \"achievements\",\n                        title: <FormattedMessage\n                            id=\"taskAchievements\"\n                            description=\"Title of the 'achievements' item in the program inventory/task selector window\"\n                            defaultMessage=\"Achievements\"\n                            />,\n                    },\n                ],\n            },\n        ];\n\n        // Add unlockable diversions\n        const solvedCount = Sic1DataManager.getData().solvedCount;\n        const diversionItems: (PuzzleInfo | NonPuzzleInfo)[] = [];\n        if (solvedCount >= Shared.avoisionSolvedCountRequired) {\n            diversionItems.push({\n                type: \"avoision\",\n                key: \"avoision\",\n                title: <FormattedMessage\n                    id=\"taskAvoision\"\n                    description=\"Title of the 'Avoision' page in the task viewer selector\"\n                    defaultMessage=\"Avoision\"\n                    />,\n                onDoubleClick: () => this.props.onPlayAvoisionRequested(),\n                buttons: [\n                    {\n                        title: <FormattedMessage\n                            id=\"taskViewerButtonAvoision\"\n                            description=\"Text on button for playing Avoision\"\n                            defaultMessage=\"Play Avoision\"\n                            />,\n                        intent: \"playAvoision\",\n                        onClick: () => this.props.onPlayAvoisionRequested(),\n                    },\n                ],\n            });\n        }\n\n        if (solvedCount >= this.props.puzzleSandbox.minimumSolvedToUnlock) {\n            diversionItems.push(filterUnlockedPuzzleList([this.props.puzzleSandbox]).map(p => ({\n                ...p,\n                onDoubleClick: () => this.props.onLoadPuzzleRequested(p.puzzle, this.puzzleView.current?.getSelectedSolutionName?.()),\n                buttons: [\n                    {\n                        title: <FormattedMessage\n                            id=\"taskViewerButtonSandbox\"\n                            description=\"Text on button for Sandbox Mode\"\n                            defaultMessage=\"Enter Sandbox Mode\"\n                            />,\n                        intent: \"sandbox\",\n                        onClick: () => this.props.onLoadPuzzleRequested(p.puzzle, this.puzzleView.current?.getSelectedSolutionName?.()),\n                    }\n                ],\n            }))[0]);\n        }\n\n        if (diversionItems.length > 0) {\n            groups.push({\n                key: \"diversions\",\n                title: <FormattedMessage\n                    id=\"taskDiversions\"\n                    description=\"Title of the 'diversions' group in the program inventory/task selector window\"\n                    defaultMessage=\"Diversions\"\n                    />,\n                items: diversionItems,\n            });\n        }\n\n        // Add unlocked story puzzles\n        let gi = 0;\n        groups.push(...unlocked.map((g, puzzleGroupIndex) => ({\n            key: `p${puzzleGroupIndex}`,\n            title: <FormattedMessage\n                id=\"taskNumberedList\"\n                description=\"Format for a numbered group in the program inventory/task selection window\"\n                defaultMessage=\"{number}. {title}\"\n                values={{\n                    number: ++gi,\n                    title: g.title,\n                }}\n                />,\n            items: g.items.map(p => ({\n                ...p,\n                title: p.puzzleData.solved\n                    ? p.title\n                    : <FormattedMessage\n                        id=\"taskWithStatus\"\n                        description=\"Format for showing a task with incomplete or new status\"\n                        defaultMessage=\"{title} (<cap>{status}</cap>)\"\n                        values={{\n                            title: p.title,\n                            status: p.puzzleData.viewed\n                                ? Shared.resources.taskStatusIncomplete\n                                : <FormattedMessage\n                                    id=\"taskStatusNew\"\n                                    description=\"Status shown for a task that has not yet been viewed\"\n                                    defaultMessage=\"New\"\n                                    />,\n                        }}\n                        />,\n                onDoubleClick: () => this.props.onLoadPuzzleRequested(p.puzzle, this.puzzleView.current?.getSelectedSolutionName?.()),\n                buttons: [\n                    {\n                        title: <FormattedMessage\n                            id=\"taskViewerButtonLoad\"\n                            description=\"Text on button for loading the selected program\"\n                            defaultMessage=\"Load This Program\"\n                            />,\n                        intent: \"load\",\n                        onClick: () => this.props.onLoadPuzzleRequested(p.puzzle, this.puzzleView.current?.getSelectedSolutionName?.()),\n                    }\n                ],\n            })),\n        })));\n\n        // Open to either the requested puzzle or the user stats page\n        this.state = {\n            groups,\n            selection: this.findIndices(groups, this.props.initialItemType, this.props.initialItemTitle),\n        };\n    }\n\n    private findIndices(groups: GroupInfo[], type?: PuzzleListTypes, title?: string): { groupIndex: number, itemIndex: number } {\n        for (let groupIndex = 0; groupIndex < groups.length; groupIndex++) {\n            const list = groups[groupIndex].items;\n            for (let itemIndex = 0; itemIndex < list.length; itemIndex++) {\n                const item = list[itemIndex];\n                // Note: Compare against puzzle title instead of item title due to potential \" (NEW)\", etc. suffixes\n                if ((item.type === type) && (!title || (type === \"puzzle\" ? (title === (item as PuzzleInfo).puzzle.title) : (item.title === title)))) {\n                    return { groupIndex, itemIndex };\n                }\n            }\n        }\n    \n        return {\n            groupIndex: 0,\n            itemIndex: 0,\n        };\n    }\n    \n    public render(): React.ReactNode {\n        const { groupIndex, itemIndex } = this.state.selection;\n        const item = this.state.groups[groupIndex].items[itemIndex];\n        const data = Sic1DataManager.getData();\n\n        return <Browser className=\"puzzleBrowser\" groups={this.state.groups} selection={this.state.selection} onSelectionChanged={(selection) => this.setState({ selection })}>\n            {(() => {\n                switch (item.type) {\n                    case \"puzzle\":\n                        return <PuzzleView\n                            ref={this.puzzleView}\n                            key={item.puzzle.title}\n                            intl={this.props.intl}\n                            puzzleInfo={item} data={data}\n                            onLoadPuzzleRequested={(puzzle, solutionName) => this.props.onLoadPuzzleRequested(puzzle, solutionName)}\n                            onShowMessageBox={(content) => this.props.onShowMessageBox(content)}\n                            onCloseMessageBox={() => this.props.onCloseMessageBox()}\n                            />;\n\n                    case \"userStats\":\n                        return <UserStatsView key=\"userStats\" data={data} />;\n\n                    case \"achievements\":\n                        return <AchievementsView key=\"achievements\" data={data} />;\n\n                    case \"avoision\":\n                        return <AvoisionView key=\"avoision\" intl={this.props.intl} data={data} />;\n                }\n            })()}\n        </Browser>;\n    }\n}\n", "sic1/client/ts/chart.tsx": "import { ChartData, HistogramBucketDetail } from \"./chart-model\";\nimport React from \"react\";\n\nexport enum ChartState {\n    loading,\n    loaded,\n    loadFailed,\n}\n\ninterface ChartProperties {\n    title: React.ReactNode;\n    promise: Promise<ChartData>;\n}\n\ninterface ChartComponentState {\n    chartState: ChartState;\n    data?: ChartData;\n}\n\nfunction formatDetail(detail: HistogramBucketDetail): string {\n    const { value, count } = detail;\n    return `Score: ${value}, count: ${count}`;\n}\n\nfunction limitLines(lines: string[], maxLines: number): string[] {\n    if (lines.length > maxLines) {\n        return [\n            ...lines.slice(0, maxLines - 2),\n            \"...\",\n            lines[lines.length - 1],\n        ];\n    } else {\n        return lines;\n    }\n}\n\nfunction formatDetails(details: HistogramBucketDetail[], outliers?: HistogramBucketDetail[]): string {\n    const scoreLines = limitLines(details.map(detail => formatDetail(detail)), 7);\n    const outlierLines = limitLines(outliers ? [\"\", \"Outliers:\", ...outliers.map(detail => formatDetail(detail))] : [], 5);\n\n    return scoreLines\n        .concat(...outlierLines)\n        .join(\"\\n\")\n    ;\n}\n\nexport class Chart extends React.Component<ChartProperties, ChartComponentState> {\n    constructor(props: ChartProperties) {\n        super(props);\n        this.state = { chartState: ChartState.loading };\n    }\n\n    public async componentDidMount() {\n        try {\n            this.setState({\n                chartState: ChartState.loaded,\n                data: await this.props.promise,\n            });\n        } catch (error) {\n            this.setState({ chartState: ChartState.loadFailed });\n        }\n    }\n\n    public render() {\n        let body: React.ReactNode;\n        if (this.state.chartState === ChartState.loaded) {\n            // Find bucket to highlight, max count, and min/max values\n            const outliers = this.state.data.histogram.outliers ?? [];\n            const data = this.state.data.histogram.buckets;\n            const highlightedValue = this.state.data.highlightedValue;\n            let maxCount = 1;\n            let minValue = null;\n            let maxValue = null;\n            let highlightIndex: number | null = null;\n            for (let i = 0; i < data.length; i++) {\n                const bucket = data[i];\n                maxCount = Math.max(maxCount, bucket.count);\n                maxValue = bucket.bucketMax;\n                if (minValue === null) {\n                    minValue = bucket.bucketMax;\n                }\n\n                if (bucket.bucketMax <= highlightedValue) {\n                    highlightIndex = i;\n                }\n            }\n\n            if (highlightedValue > 0 && highlightIndex !== null && data[highlightIndex].count <= 0) {\n                data[highlightIndex].count = 1;\n            }\n\n            const chartHeight = 20;\n            const scale = chartHeight / maxCount;\n            let points = \"\";\n            for (let i = 0; i < data.length; i++) {\n                const count = data[i].count;\n                points += ` ${i * 20 / data.length},${chartHeight - (count * scale)}`;\n                points += ` ${(i + 1) * 20 / data.length},${chartHeight - (count * scale)}`;\n            }\n\n            body = <>\n                <polyline className=\"chartLine\" points={points}></polyline>\n                {highlightIndex === null ? null : <rect className=\"chartHighlight\" x={highlightIndex * 20 / data.length} y={chartHeight - (data[highlightIndex].count * scale)} width={20 / data.length} height={data[highlightIndex].count * scale}></rect>}\n                {highlightIndex === null ? null : <polyline className=\"chartArrow\" points=\"0,-0.5 0.5,0 1,-0.5 0,-0.5\" transform={`translate(${highlightIndex * 20 / data.length}, ${chartHeight - (data[highlightIndex].count * scale + 0.5)}) scale(${20 / data.length})`}></polyline>}\n                {data.map(({ bucketMax, count, details }, i) => <rect key={bucketMax} className=\"chartInvisible\" x={i * 20 / data.length} y={chartHeight - Math.max(1, (count * scale))} width={20 / data.length} height={Math.max(1, (count * scale))}>\n                    <title>{formatDetails(details, (i === data.length - 1) ? outliers : undefined)}</title>\n                </rect>)}\n                <text className=\"chartLeft\" x=\"0\" y=\"21.5\">{minValue}</text>\n                <text className=\"chartRight\" x=\"20\" y=\"21.5\">{maxValue}</text>\n            </>;\n\n        } else {\n            body = <>\n                <text className=\"chartOverlay\" x=\"10\" y=\"10\">{(this.state.chartState === ChartState.loading) ? \"Loading...\" : \"Load Failed\"}</text>\n            </>;\n        }\n\n        return <svg className=\"chart\" viewBox=\"0 -3 20 25\">\n            <rect x=\"0\" y=\"-3\" width=\"20\" height=\"1.6\"></rect>\n            <line x1=\"0\" y1=\"20\" x2=\"20\" y2=\"20\"></line>\n            <text className=\"chartTitle\" x=\"10\" y=\"-1.9\">{this.props.title}</text>\n            {body}\n        </svg>;\n    }\n}\n", "sic1/client/ts/avoision.tsx": "import React from \"react\";\nimport { ColorScheme, colorToCssColor, ColorVariable, getColor } from \"./colors\";\n\nexport interface AvoisionProps {\n    colorScheme: ColorScheme;\n    onStarted?: () => void;\n    onPointsUpdated?: (points: number) => void;\n    onScoreUpdated?: (score: number) => void;\n    onGameOver?: (score: number) => void;\n}\n\ntype Control = \"left\" | \"right\" | \"up\" | \"down\";\n\nconst keyCodeToControl = {\n    ArrowLeft: \"left\",\n    ArrowRight: \"right\",\n    ArrowUp: \"up\",\n    ArrowDown: \"down\",\n} as const;\n\ninterface Square {\n    x: number;\n    y: number;\n}\n\ninterface Enemy extends Square {\n    horizontal: boolean;\n    positive: boolean;\n}\n\ninterface Ghost extends Square {\n    progress: number;\n    style: SquareStyle;\n}\n\ninterface SquareStyle {\n    color: ColorVariable;\n    filled: boolean;\n}\n\nexport class Avoision extends React.Component<AvoisionProps> {\n    private static readonly squareSize = 0.03;\n    private static readonly minimumDistance = 0.3;\n    private static readonly speed = 0.5;\n    private static readonly pointsInitial = 15;\n    private static readonly pointPeriodMS = 1000;\n    private static readonly ghostPeriodMS = 400;\n\n    private static readonly enemyStyle = { color: \"sfg\", filled: true } as const;\n    private static readonly goalStyle = { color: \"fg\", filled: false } as const;\n    private static readonly playerStyle = { color: \"fg\", filled: true } as const;\n\n    private canvasElement = React.createRef<HTMLCanvasElement>();\n    private canvas: CanvasRenderingContext2D;\n    private width: number;\n    private height: number;\n\n    private onVisibilityChanged = () => this.handleVisibilityChange();\n    private paused = true;\n    private now: number;\n\n    // Input handling\n    private controlStates: Partial<{ [key in Control]: boolean }> = {};\n\n    // Internal game state\n    private started: boolean;\n    private pointsTimer: number;\n    private points: number;\n    private score: number;\n    private player: Square | undefined;\n    private goal: Square;\n    private enemies: Enemy[] = [];\n    private ghosts: Ghost[] = [];\n\n    constructor(props) {\n        super(props);\n    }\n\n    private setRandomPosition(square: Square): void {\n        const px = this.player?.x ?? 0.5;\n        const py = this.player?.y ?? 0.5;\n        do {\n            square.x = Math.random() * (1 - Avoision.squareSize);\n            square.y = Math.random() * (1 - Avoision.squareSize);\n        } while (Math.sqrt(Math.pow((square.x - px), 2) + Math.pow((square.y - py), 2)) < Avoision.minimumDistance);\n    }\n\n    private checkCollision(square: Square): boolean {\n        if (this.player) {\n            const ax1 = this.player.x;\n            const ax2 = ax1 + Avoision.squareSize;\n            const ay1 = this.player.y;\n            const ay2 = ay1 + Avoision.squareSize;\n            const bx1 = square.x;\n            const bx2 = bx1 + Avoision.squareSize;\n            const by1 = square.y;\n            const by2 = by1 + Avoision.squareSize;\n    \n            return (((ax1 >= bx1 && ax1 <= bx2) || (ax2 >= bx1 && ax2 <= bx2) || (bx1 >= ax1 && bx1 <= ax2))\n            && ((ay1 >= by1 && ay1 <= by2) || (ay2 >= by1 && ay2 <= by2) || (by1 >= ay1 && by1 <= ay2)));\n        }\n        return false;\n    }\n\n    private coinFlip(): boolean {\n        return (Math.random() >= 0.5);\n    }\n\n    private spawn(): void {\n        const e = { x: 0, y: 0 };\n        this.setRandomPosition(e);\n        this.enemies.push({\n            ...e,\n            horizontal: this.coinFlip(),\n            positive: this.coinFlip(),\n        });\n    }\n\n    private updatePoints(points: number): void {\n        this.points = points;\n        this.props.onPointsUpdated?.(points);\n    }\n\n    private updateScore(score: number): void {\n        this.score = score;\n        this.props.onScoreUpdated?.(score);\n    }\n\n    private drawSquare(square: Square, style: SquareStyle, opacity = 1, size = Avoision.squareSize): void {\n        const { canvas } = this;\n        const x = Math.round(square.x * this.width);\n        const y = Math.round(square.y * this.height);\n        const width = Math.round(size * this.width);\n        const height = Math.round(size * this.height);\n        const { red, green, blue } = getColor(this.props.colorScheme, style.color);\n        const drawStyle = colorToCssColor({ red, green, blue, opacity });\n        if (style.filled) {\n            canvas.fillStyle = drawStyle;\n            canvas.fillRect(x, y, width, height);\n        } else {\n            canvas.lineWidth = 2;\n            canvas.strokeStyle = drawStyle;\n            canvas.strokeRect(x, y, width, height);\n        }\n    }\n\n    private drawGhost(ghost: Ghost): void {\n        const scale = 1 + (2 * ghost.progress);\n        this.drawSquare(\n            {\n                x: ghost.x - ((scale - 1) / 2) * Avoision.squareSize,\n                y: ghost.y - ((scale - 1) / 2) * Avoision.squareSize,\n            },\n            ghost.style,\n            1 - ghost.progress,\n            Avoision.squareSize * scale,\n        );\n    }\n\n    private addGhost(square: Square, style: SquareStyle): void {\n        this.ghosts.push({ ...square, style, progress: 0});\n    }\n\n    private resizeIfNeeded(): void {\n        const element = this.canvasElement.current;\n        const { width, height } = element.getBoundingClientRect();\n        const devicePixelRatio = window.devicePixelRatio ?? 1;\n        const canvasWidth = Math.ceil(width * devicePixelRatio);\n        const canvasHeight = Math.ceil(height * devicePixelRatio);\n        if (this.width !== canvasWidth || this.height !== canvasHeight) {\n            element.style.width = `${Math.ceil(width)}px`;\n            element.style.height = `${Math.ceil(height)}px`;\n            element.width = canvasWidth;\n            element.height = canvasHeight;\n            this.width = canvasWidth;\n            this.height = canvasHeight;\n        }\n    }\n\n    private draw(): void {\n        this.resizeIfNeeded();\n\n        const { canvas } = this;\n\n        canvas.fillStyle = colorToCssColor(getColor(this.props.colorScheme, \"bg\"));\n        canvas.fillRect(0, 0, this.width, this.height);\n\n        for (const g of this.ghosts) {\n            this.drawGhost(g);\n        }\n\n        for (const e of this.enemies) {\n            this.drawSquare(e, Avoision.enemyStyle);\n        }\n\n        this.drawSquare(this.goal, Avoision.goalStyle);\n\n        if (this.player) {\n            this.drawSquare(this.player, Avoision.playerStyle);\n        }\n    }\n\n    private gameOver(): void {\n        this.addGhost(this.player, Avoision.playerStyle);\n        this.player = undefined;\n        if (this.props.onGameOver) {\n            this.props.onGameOver(this.score);\n        }\n    }\n\n    private update(deltaMS: number): void {\n        const speed = Avoision.speed * deltaMS / 1000;\n        if (this.player) {\n            const vx = (this.controlStates[\"left\"] ? -speed : 0) + (this.controlStates[\"right\"] ? speed : 0);\n            const vy = (this.controlStates[\"up\"] ? -speed : 0) + (this.controlStates[\"down\"] ? speed : 0);\n            this.player.x = Math.max(0, Math.min(1 - Avoision.squareSize, this.player.x + vx));\n            this.player.y = Math.max(0, Math.min(1 - Avoision.squareSize, this.player.y + vy));\n\n            if (this.started) {\n                this.pointsTimer += deltaMS;\n                while (this.pointsTimer > Avoision.pointPeriodMS) {\n                    this.pointsTimer -= Avoision.pointPeriodMS;\n                    const points = Math.max(0, this.points - 1);\n                    if (points !== this.points) {\n                        this.updatePoints(points);\n                    }\n                }\n            } else {\n                this.started = (vx !== 0 || vy !== 0);\n                if (this.started) {\n                    this.props.onStarted();\n                }\n            }\n        }\n\n        if (this.checkCollision(this.goal)) {\n            this.addGhost(this.goal, Avoision.goalStyle);\n            this.setRandomPosition(this.goal);\n            this.updateScore(this.score + this.points);\n            this.updatePoints(Avoision.pointsInitial);\n            this.spawn();\n        }\n\n        for (const e of this.enemies) {\n            const key = e.horizontal ? \"x\" : \"y\";\n            const max = 1 - Avoision.squareSize;\n            let p = e[key];\n            if (e.positive) {\n                p += speed;\n                if (p > max) {\n                    p = max - (p - max);\n                    e.positive = false;\n                }\n            } else {\n                p -= speed;\n                if (p < 0) {\n                    p = -p;\n                    e.positive = true;\n                }\n            }\n\n            if (this.checkCollision(e)) {\n                this.gameOver();\n            }\n\n            e[key] = p;\n        }\n\n        for (let i = 0; i < this.ghosts.length; i++) {\n            const g = this.ghosts[i];\n            g.progress += (deltaMS / Avoision.ghostPeriodMS);\n            if (g.progress >= 1) {\n                this.ghosts.splice(i--, 1);\n            }\n        }\n    }\n\n    private pause(): void {\n        this.paused = true;\n    }\n\n    private unpause(): void {\n        this.paused = false;\n        this.loop(false);\n    }\n\n    private loop(update = true): void {\n        if (!this.paused) {\n            const next = performance.now();\n            if (update) {\n                this.update(next - this.now);\n            }\n\n            this.now = next;\n            this.draw();\n            requestAnimationFrame(() => this.loop());\n        }\n    }\n\n    private onKeyEvent(event: React.KeyboardEvent<HTMLCanvasElement>, down: boolean): void {\n        const control = keyCodeToControl[event.code];\n        if (control) {\n            this.controlStates[control] = down;\n            event.preventDefault();\n        }\n    }\n\n    private handleVisibilityChange(): void {\n        if (document.visibilityState === \"visible\") {\n            if (this.paused) {\n                this.unpause();\n            }\n        } else {\n            if (!this.paused) {\n                this.pause();\n            }\n        }\n    }\n\n    public focus(): void {\n        this.canvasElement.current?.focus?.();\n    }\n\n    public reset(): void {\n        this.started = false;\n        this.now = performance.now();\n        this.updateScore(0);\n        this.player = { x: 0.5, y: 0.5 };\n        this.goal = { x: 0, y: 0 };\n        this.setRandomPosition(this.goal);\n        this.pointsTimer = 0;\n        this.updatePoints(Avoision.pointsInitial);\n        this.enemies.length = 0;\n        this.ghosts.length = 0;\n    }\n\n    public componentDidMount(): void {\n        document.addEventListener(\"visibilitychange\", this.onVisibilityChanged);\n\n        // Graphics\n        this.canvas = this.canvasElement.current.getContext(\"2d\");\n\n        // Event loop\n        this.reset();\n        this.unpause();\n\n        this.canvasElement.current.focus();\n    }\n\n    public componentWillUnmount(): void {\n        document.removeEventListener(\"visibilitychange\", this.onVisibilityChanged);\n        this.pause();\n        this.canvas = undefined;        \n    }\n\n    public render(): React.ReactNode {\n        return <canvas\n            ref={this.canvasElement}\n            className=\"avoision\"\n            tabIndex={0}\n            onKeyUp={event => this.onKeyEvent(event, false)}\n            onKeyDown={event => this.onKeyEvent(event, true)}\n        ></canvas>;\n    }\n}\n", "sic1/client/ts/resources.ts": "import { IntlShape } from \"react-intl\";\n\nclass LocalizedResource {\n    private value: string | undefined;\n\n    public setValue(newValue: string): void {\n        this.value = newValue;\n    }\n\n    public getValue(): string {\n        if (!this.value) {\n            throw \"Localized resources have not been initialized!\";\n        }\n        return this.value;\n    }\n}\n\nexport const LocalizedResources = {\n    defaultSolutionName: new LocalizedResource(),\n} as const;\n\n// TODO: If the locale can ever be changed, this function will need to be run again!\nexport function initializeResources(intl: IntlShape) {\n    LocalizedResources.defaultSolutionName.setValue(intl.formatMessage({\n        id: \"solutionNameDefault\",\n        description: \"Default name for new solution files\",\n        defaultMessage: \"Untitled\",\n    }));\n}\n", "sic1/client/ts/puzzles.tsx": "import React from \"react\";\nimport { Puzzle, titleToPuzzle } from \"../../shared/puzzles\";\nimport { FormattedMessage, IntlShape } from \"react-intl\";\n\nexport enum Format {\n    numbers, // Default\n    characters,\n    strings,\n}\n\n// Note: Values are from music.ts\nconst Songs = {\n    light: \"light\",\n    major: \"major\",\n    boss: \"menu\",\n} as const;\n\ntype ClientPuzzleStatic = Puzzle & {\n    title: string;\n    displayTitle: string;\n    minimumSolvedToUnlock: number;\n    song?: string;\n    description: string;\n    code?: string;\n    inputFormat?: Format;\n    outputFormat?: Format;\n\n    puzzleViewOverride?: React.ReactNode;\n    hint: React.ReactNode;\n}\n\ntype ClientPuzzleConfigurable = Omit<ClientPuzzleStatic, \"io\"> & {\n    customInput: true;\n};\n\nexport type ClientPuzzle = ClientPuzzleStatic | ClientPuzzleConfigurable;\n\nexport function hasCustomInput(puzzle: ClientPuzzle): puzzle is ClientPuzzleConfigurable {\n    return !!puzzle[\"customInput\"];\n}\n\nexport interface ClientPuzzleGroup {\n    groupTitle: React.ReactNode;\n    list: ClientPuzzle[];\n}\n\n/** Puzzles by group */\nexport interface ClientPuzzleInfo {\n    clientPuzzlesGrouped: ClientPuzzleGroup[];\n    puzzleFlatArray: ClientPuzzle[];\n    clientPuzzles: ClientPuzzle[]; // Includes the not-actually-a-puzzle \"Sandbox Mode\" puzzle\n    titleToClientPuzzle: { [title: string]: ClientPuzzle };\n    puzzleSandbox: ClientPuzzle;\n}\n\nexport function initializePuzzles(intl: IntlShape): ClientPuzzleInfo {\n    const clientPuzzlesGrouped = [\n        {\n            groupTitle: <FormattedMessage\n                id=\"puzzleGroupTitleTutorial\"\n                description=\"Title of 'Tutorial' puzzle group\"\n                defaultMessage=\"Tutorial\"\n            />,\n            list: [\n                {\n                    ...titleToPuzzle[\"Subleq Instruction and Output\"],\n                    title: \"Subleq Instruction and Output\",\n                    minimumSolvedToUnlock: 0,\n                    displayTitle: intl.formatMessage({\n                        id: \"puzzleTitleSubleq Instruction and Output\",\n                        description: \"Title of the 'Subleq Instruction and Output' puzzle\",\n                        defaultMessage: \"Subleq Instruction and Output\",\n                    }),\n                    description: intl.formatMessage({\n                        id: \"puzzleDescriptionSubleq Instruction and Output\",\n                        description: \"Description of the 'Subleq Instruction and Output' puzzle\",\n                        defaultMessage: \"Use subleq and input/output to negate an input and write it out.\",\n                    }),\n                    hint: intl.formatMessage({\n                        id: \"puzzleHintSubleq Instruction and Output\",\n                        description: \"Hint for the 'Subleq Instruction and Output' puzzle\",\n                        defaultMessage: \"<p>This task has already been solved. Just click <strong>Run</strong>.</p>\",\n                    }),\n                    code: intl.formatMessage({\n                        id: \"puzzleCodeSubleq Instruction and Output\",\n                        description: \"Initial code for the 'Subleq Instruction and Output' puzzle\",\n                        defaultMessage:\n`; The Single Instruction Computer Mark 1 (SIC-1) is an 8-bit computer with 256 bytes of memory. Programs for the SIC-1 are written in SIC-1 Assembly Language.\n;\n; Each instruction is 3 bytes, specified as follows:\n;\n;   subleq A B [C]\n;\n; A, B, and C are memory addresses (0 - 255) or labels.\n;\n; \\\"subleq\\\" subtracts the value at address B from the value at address A and stores the result at address A (i.e. mem[A] ← mem[A] - mem[B]).\n;\n; If the result is ≤ 0, execution branches to address C.\n;\n; Note that if C is not specified, the address of the next instruction is automatically added by the assembler (in effect, this means that taking the branch is no different from advancing to the next instruction).\n;\n; For convenience, addresses can be specified using labels. The following predefined labels are always available:\n;\n;   @MAX (252): Maximum user-modifiable address\n;   @IN (253): Reads a value from input (writes are ignored)\n;   @OUT (254): Writes a result to output (reads as zero)\n;   @HALT (255): Terminates the program when accessed\n;\n; Note: any text following a semicolon is considered a comment. Comments are ignored by the assembler.\n; \n; Below is a very simple SIC-1 program that negates one input value and writes it out.\n;\n; E.g. if the input value from @IN is 3, it subtracts 3 from @OUT (which reads as zero), and the result of 0 - 3 = -3 is written out.\n\nsubleq @OUT, @IN\n\n; Use the \\\"Compile/Step\\\" (Ctrl+.) and \\\"Run\\\" (Ctrl+Enter) buttons to execute the program until all expected outputs have been successfully written out (see the \\\"In\\\"/\\\"Expected\\\"/\\\"Out\\\" table to the left).\n    `,\n                    }),\n                },\n                {\n                    ...titleToPuzzle[\"Data Directive and Looping\"],\n                    title: \"Data Directive and Looping\",\n                    minimumSolvedToUnlock: 1,\n                    displayTitle: intl.formatMessage({\n                        id: \"puzzleTitleData Directive and Looping\",\n                        description: \"Title of the 'Data Directive and Looping' puzzle\",\n                        defaultMessage: \"Data Directive and Looping\",\n                    }),\n                    description: intl.formatMessage({\n                        id: \"puzzleDescriptionData Directive and Looping\",\n                        description: \"Description of the 'Data Directive and Looping' puzzle\",\n                        defaultMessage: \"Use .data and labels to loop.\",\n                    }),\n                    hint: intl.formatMessage({\n                        id: \"puzzleHintData Directive and Looping\",\n                        description: \"Hint for the 'Data Directive and Looping' puzzle\",\n                        defaultMessage: \"<p>This task has already been solved. Just click <strong>Run</strong>.</p>\",\n                    }),\n                    code: intl.formatMessage({\n                        id: \"puzzleCodeData Directive and Looping\",\n                        description: \"Initial code for the 'Data Directive and Looping' puzzle\",\n                        defaultMessage:\n`; Custom labels are defined by putting \\\"@name: \\\" at the beginning of a line, e.g.:\n;\n;   @loop: subleq 1, 2\n;\n; In addition to \\\"subleq\\\", there is an assembler directive \\\".data\\\" that sets a byte of memory to a value at compile time (note: this is not an instruction!):\n;\n;   .data X\n;\n; X is a signed byte between -128 and 127 (inclusive).\n;\n; Combining labels and the \\\".data\\\" directive allows you to develop a system of constants and variables. For example, here a byte is set to zero, and the label @zero points to that value:\n;\n;   @zero: .data 0\n;\n; Note that, while a program is executing, you can view the current value of each variable in the variable table on the right (under the memory table).\n;\n; Variables can be used for implementing an unconditional jump:\n;\n;   subleq @zero, @zero, @next\n;\n; This will set @zero to @zero - @zero (still zero) and, since the result is always ≤ 0, execution branches to @next.\n;\n; Below is an updated negation program that repeatedly negates input values and writes them out in a loop.\n\n@loop:\nsubleq @OUT, @IN\nsubleq @zero, @zero, @loop\n\n@zero: .data 0\n`\n                    }),\n                },\n                {\n                    ...titleToPuzzle[\"First Assessment\"],\n                    title: \"First Assessment\",\n                    minimumSolvedToUnlock: 2,\n                    displayTitle: intl.formatMessage({\n                        id: \"puzzleTitleFirst Assessment\",\n                        description: \"Title of the 'First Assessment' puzzle\",\n                        defaultMessage: \"First Assessment\",\n                    }),\n                    description: intl.formatMessage({\n                        id: \"puzzleDescriptionFirst Assessment\",\n                        description: \"Description of the 'First Assessment' puzzle\",\n                        defaultMessage: \"Write input values to output.\",\n                    }),\n                    hint: intl.formatMessage({\n                        id: \"puzzleHintFirst Assessment\",\n                        description: \"Hint for the 'First Assessment' puzzle\",\n                        defaultMessage: \"<p>Negate the value twice (these operations cancel out and result in the original number). This can be done by storing the negated value in a memory location that starts out as zero (e.g. <code>@tmp</code>).</p>\",\n                    }),\n                    code: intl.formatMessage({\n                        id: \"puzzleCodeFirst Assessment\",\n                        description: \"Initial code for the 'First Assessment' puzzle\",\n                        defaultMessage:\n`; Now that you understand the \\\"subleq\\\" instruction, the \\\".data\\\" directive, and labels, you should be able to read values from input and write the exact same values out, by negating the value twice.\n;\n; Below is an almost complete solution. You will need to replace instances of \\\"???\\\". Hint: use a label that points to a storage location for a (negated) value.\n\n@loop:\nsubleq ???, @IN\nsubleq @OUT, ???\nsubleq @tmp, @tmp, @loop  ; Reset @tmp to zero, and jump to @loop\n\n@tmp: .data 0\n`\n                    }),\n                },\n            ],\n        },\n        {\n            groupTitle: <FormattedMessage\n                id=\"puzzleGroupTitleArithmetic\"\n                description=\"Title of 'Arithmetic' puzzle group\"\n                defaultMessage=\"Arithmetic\"\n            />,\n            list: [\n                {\n                    ...titleToPuzzle[\"Addition\"],\n                    title: \"Addition\",\n                    minimumSolvedToUnlock: 3,\n                    song: Songs.light,\n                    displayTitle: intl.formatMessage({\n                        id: \"puzzleTitleAddition\",\n                        description: \"Title of the 'Addition' puzzle\",\n                        defaultMessage: \"Addition\",\n                    }),\n                    description: intl.formatMessage({\n                        id: \"puzzleDescriptionAddition\",\n                        description: \"Description of the 'Addition' puzzle\",\n                        defaultMessage: \"Read two numbers and output their sum. Repeat.\",\n                    }),\n                    hint: intl.formatMessage({\n                        id: \"puzzleHintAddition\",\n                        description: \"Hint for the 'Addition' puzzle\",\n                        defaultMessage: \"<p>Subtract two inputs into <code>@tmp</code>.</p>\",\n                    }),\n                    code: intl.formatMessage({\n                        id: \"puzzleCodeAddition\",\n                        description: \"Initial code for the 'Addition' puzzle\",\n                        defaultMessage:\n`; Read two numbers and output their sum. Repeat.\n;\n; Below is the solution to the previous task. You will need to add additional code to perform addition of two inputs (instead of passing through a single input):\n\n@loop:\nsubleq @tmp, @IN\nsubleq @OUT, @tmp\nsubleq @tmp, @tmp, @loop  ; Reset @tmp to zero, and jump to @loop\n\n@tmp: .data 0\n`\n                    }),\n                },\n                {\n                    ...titleToPuzzle[\"Subtraction\"],\n                    title: \"Subtraction\",\n                    minimumSolvedToUnlock: 3,\n                    song: Songs.light,\n                    displayTitle: intl.formatMessage({\n                        id: \"puzzleTitleSubtraction\",\n                        description: \"Title of the 'Subtraction' puzzle\",\n                        defaultMessage: \"Subtraction\",\n                    }),\n                    description: intl.formatMessage({\n                        id: \"puzzleDescriptionSubtraction\",\n                        description: \"Description of the 'Subtraction' puzzle\",\n                        defaultMessage: \"Read two numbers (A, then B) and output A minus B. Repeat.\",\n                    }),\n                    hint: intl.formatMessage({\n                        id: \"puzzleHintSubtraction\",\n                        description: \"Hint for the 'Subtraction' puzzle\",\n                        defaultMessage: \"<p>Use two variables.</p>\",\n                    }),\n                },\n                {\n                    ...titleToPuzzle[\"Sign Function\"],\n                    title: \"Sign Function\",\n                    minimumSolvedToUnlock: 3,\n                    displayTitle: intl.formatMessage({\n                        id: \"puzzleTitleSign Function\",\n                        description: \"Title of the 'Sign Function' puzzle\",\n                        defaultMessage: \"Sign Function\",\n                    }),\n                    description: intl.formatMessage({\n                        id: \"puzzleDescriptionSign Function\",\n                        description: \"Description of the 'Sign Function' puzzle\",\n                        defaultMessage: \"Read a number. If less than zero, output -1; if equal to zero, output 0; otherwise output 1. Repeat.\",\n                    }),\n                    hint: intl.formatMessage({\n                        id: \"puzzleHintSign Function\",\n                        description: \"Hint for the 'Sign Function' puzzle\",\n                        defaultMessage: \"<p>Use the \\\"branch if result is ≤ 0\\\" property of subleq to branch between code blocks, then use (negated) constants to write the appropriate output.</p>\",\n                    }),\n                },\n                {\n                    ...titleToPuzzle[\"Multiplication\"],\n                    title: \"Multiplication\",\n                    minimumSolvedToUnlock: 3,\n                    displayTitle: intl.formatMessage({\n                        id: \"puzzleTitleMultiplication\",\n                        description: \"Title of the 'Multiplication' puzzle\",\n                        defaultMessage: \"Multiplication\",\n                    }),\n                    description: intl.formatMessage({\n                        id: \"puzzleDescriptionMultiplication\",\n                        description: \"Description of the 'Multiplication' puzzle\",\n                        defaultMessage: \"Read two nonnegative numbers and output the resulting (nonnegative) product. Repeat.\",\n                    }),\n                    hint: intl.formatMessage({\n                        id: \"puzzleHintMultiplication\",\n                        description: \"Hint for the 'Multiplication' puzzle\",\n                        defaultMessage: \"<p>Repeatedly subtract one of the numbers, using a counter to ensure the subtraction is done the appropriate number of times.</p>\",\n                    }),\n                },\n                {\n                    ...titleToPuzzle[\"Division\"],\n                    title: \"Division\",\n                    minimumSolvedToUnlock: 3,\n                    song: Songs.major,\n                    displayTitle: intl.formatMessage({\n                        id: \"puzzleTitleDivision\",\n                        description: \"Title of the 'Division' puzzle\",\n                        defaultMessage: \"Division\",\n                    }),\n                    description: intl.formatMessage({\n                        id: \"puzzleDescriptionDivision\",\n                        description: \"Description of the 'Division' puzzle\",\n                        defaultMessage: \"Read two positive numbers (A, then B), divide A by B, and output the quotient followed by the remainder. Repeat.\",\n                    }),\n                    hint: intl.formatMessage({\n                        id: \"puzzleHintDivision\",\n                        description: \"Hint for the 'Division' puzzle\",\n                        defaultMessage: \"<p>Repeatedly subtract the divisor from the dividend.</p>\",\n                    }),\n                },\n            ],\n        },\n        {\n            groupTitle: <FormattedMessage\n                id=\"puzzleGroupTitleSequences\"\n                description=\"Title of 'Sequences' puzzle group\"\n                defaultMessage=\"Sequences\"\n            />,\n            list: [\n                {\n                    ...titleToPuzzle[\"Sequence Sum\"],\n                    title: \"Sequence Sum\",\n                    minimumSolvedToUnlock: 8,\n                    displayTitle: intl.formatMessage({\n                        id: \"puzzleTitleSequence Sum\",\n                        description: \"Title of the 'Sequence Sum' puzzle\",\n                        defaultMessage: \"Sequence Sum\",\n                    }),\n                    description: intl.formatMessage({\n                        id: \"puzzleDescriptionSequence Sum\",\n                        description: \"Description of the 'Sequence Sum' puzzle\",\n                        defaultMessage: \"Read a sequence of positive numbers and output their sum. Repeat. Sequences are terminated by a zero.\",\n                    }),\n                    hint: intl.formatMessage({\n                        id: \"puzzleHintSequence Sum\",\n                        description: \"Hint for the 'Sequence Sum' puzzle\",\n                        defaultMessage: \"<p>Store the value to test whether it indicates the end of the sequence.</p>\",\n                    }),\n                },\n                {\n                    ...titleToPuzzle[\"Sequence Cardinality\"],\n                    title: \"Sequence Cardinality\",\n                    minimumSolvedToUnlock: 8,\n                    song: Songs.light,\n                    displayTitle: intl.formatMessage({\n                        id: \"puzzleTitleSequence Cardinality\",\n                        description: \"Title of the 'Sequence Cardinality' puzzle\",\n                        defaultMessage: \"Sequence Cardinality\",\n                    }),\n                    description: intl.formatMessage({\n                        id: \"puzzleDescriptionSequence Cardinality\",\n                        description: \"Description of the 'Sequence Cardinality' puzzle\",\n                        defaultMessage: \"Read a sequence of positive numbers and output the count of numbers. Repeat. Sequences are terminated by a zero.\",\n                    }),\n                    hint: intl.formatMessage({\n                        id: \"puzzleHintSequence Cardinality\",\n                        description: \"Hint for the 'Sequence Cardinality' puzzle\",\n                        defaultMessage: \"<p>Increment a counter for each element in the sequence.</p>\",\n                    }),\n                },\n                {\n                    ...titleToPuzzle[\"Number to Sequence\"],\n                    title: \"Number to Sequence\",\n                    minimumSolvedToUnlock: 8,\n                    song: Songs.major,\n                    displayTitle: intl.formatMessage({\n                        id: \"puzzleTitleNumber to Sequence\",\n                        description: \"Title of the 'Number to Sequence' puzzle\",\n                        defaultMessage: \"Number to Sequence\",\n                    }),\n                    description: intl.formatMessage({\n                        id: \"puzzleDescriptionNumber to Sequence\",\n                        description: \"Description of the 'Number to Sequence' puzzle\",\n                        defaultMessage: \"Read a number and then output that many 1s, followed by a 0. Repeat.\",\n                    }),\n                    hint: intl.formatMessage({\n                        id: \"puzzleHintNumber to Sequence\",\n                        description: \"Hint for the 'Number to Sequence' puzzle\",\n                        defaultMessage: \"<p>Use a counter to write the appropriate number of <strong>1</strong>s.</p>\",\n                    }),\n                },\n            ],\n        },\n        {\n            groupTitle: <FormattedMessage\n                id=\"puzzleGroupTitleAdvanced Techniques\"\n                description=\"Title of 'Advanced Techniques' puzzle group\"\n                defaultMessage=\"Advanced Techniques\"\n            />,\n            list: [\n                {\n                    ...titleToPuzzle[\"Self-Modifying Code\"],\n                    title: \"Self-Modifying Code\",\n                    minimumSolvedToUnlock: 11,\n                    displayTitle: intl.formatMessage({\n                        id: \"puzzleTitleSelf-Modifying Code\",\n                        description: \"Title of the 'Self-Modifying Code' puzzle\",\n                        defaultMessage: \"Self-Modifying Code\",\n                    }),\n                    description: intl.formatMessage({\n                        id: \"puzzleDescriptionSelf-Modifying Code\",\n                        description: \"Description of the 'Self-Modifying Code' puzzle\",\n                        defaultMessage: \"Output the program's compiled code byte-by-byte.\",\n                    }),\n                    hint: intl.formatMessage({\n                        id: \"puzzleHintSelf-Modifying Code\",\n                        description: \"Hint for the 'Self-Modifying Code' puzzle\",\n                        defaultMessage: \"<p>This task has already been solved, but carefully note how the second byte of the first instruction is modified.</p>\",\n                    }),\n                    code: intl.formatMessage({\n                        id: \"puzzleCodeSelf-Modifying Code\",\n                        description: \"Initial code for the 'Self-Modifying Code' puzzle\",\n                        defaultMessage:\n`; Label expressions can include an optional offset. For example, @loop+1 refers to the second byte of the instruction pointed to by @loop:\n;\n;   subleq @loop+1, @one\n;\n; This is useful in self-modifying code. Remember, each \\\"subleq\\\" instruction is stored as 3 consecutive addresses, ABC:\n;\n; mem[A] ← mem[A] - mem[B], with a branch to C if the result is less than or equal to zero.\n;\n; The sample program below reads its own compiled code. The third instruction is an example of self-modifying code because it actually modifies the first instruction. Specifically, it increments the first instruction's second address (@loop+1). This causes the *next* loop iteration's first instruction to read the *next* byte of memory (0, 1, 2, 3, ...).\n;\n; Note: When running a program, the original (unmodified) source code is always shown. If the program modifies itself, the changes are reflected in the memory table in the top right, but *not* in the source code viewer.\n\n@loop:\nsubleq @tmp, 0           ; Second address (initially zero) will be incremented\nsubleq @OUT, @tmp        ; Output the value\nsubleq @loop+1, @n_one   ; Here is where the increment is performed\nsubleq @tmp, @tmp, @loop\n\n@tmp: .data 0\n@n_one: .data -1\n`\n                    }),\n                },\n                {\n                    ...titleToPuzzle[\"Stack Memory\"],\n                    title: \"Stack Memory\",\n                    minimumSolvedToUnlock: 12,\n                    displayTitle: intl.formatMessage({\n                        id: \"puzzleTitleStack Memory\",\n                        description: \"Title of the 'Stack Memory' puzzle\",\n                        defaultMessage: \"Stack Memory\",\n                    }),\n                    description: intl.formatMessage({\n                        id: \"puzzleDescriptionStack Memory\",\n                        description: \"Description of the 'Stack Memory' puzzle\",\n                        defaultMessage: \"Read 3 values from input and then output the values in reverse order.\",\n                    }),\n                    hint: intl.formatMessage({\n                        id: \"puzzleHintStack Memory\",\n                        description: \"Hint for the 'Stack Memory' puzzle\",\n                        defaultMessage: \"<p>This task has already been solved, but carefully watch the memory window to see how items are added to the stack.</p>\",\n                    }),\n                    code: intl.formatMessage({\n                        id: \"puzzleCodeStack Memory\",\n                        description: \"Initial code for the 'Stack Memory' puzzle\",\n                        defaultMessage:\n`; This program implements a last-in, first-out stack by modifying the read and write addresses of the instructions that interact with the stack.\n;\n; The program pushes 3 (defined by @count) input values onto the stack and then pops them off (outputting them in reverse order).\n\n; The first address of this instruction (which starts pointing to @stack) will be incremented with each write to the stack\n\n@stack_push:\nsubleq @stack, @IN\nsubleq @count, @one, @prepare_to_pop\n\n; Modify the instruction at @stack_push (increment target address)\nsubleq @stack_push, @n_one\nsubleq @tmp, @tmp, @stack_push\n\n; Prepare to start popping values off of the stack by copying the current stack position to @stack_pop+1\n@prepare_to_pop:\nsubleq @tmp, @stack_push\nsubleq @stack_pop+1, @tmp\n\n; Read a value from the stack (note: the second address of this instruction is repeatedly decremented)\n@stack_pop:\nsubleq @OUT, 0\n\n; Decrement stack address in the instruction at @stack_pop\nsubleq @stack_pop+1, @one\nsubleq @tmp, @tmp, @stack_pop\n\n; Constants\n@one: .data 1\n@n_one: .data -1\n\n; Variables\n@tmp: .data 0\n@count: .data 3\n\n; Address of @stack (defined below)\n@stack_address: .data @stack\n\n; Base of stack (stack will grow to larger addresses, so no variables should be placed after this one)\n@stack: .data 0\n`\n                    }),\n                },\n            ],\n        },\n        {\n            groupTitle: <FormattedMessage\n                id=\"puzzleGroupTitleSequence Manipulation\"\n                description=\"Title of 'Sequence Manipulation' puzzle group\"\n                defaultMessage=\"Sequence Manipulation\"\n            />,\n            list: [\n                {\n                    ...titleToPuzzle[\"Reverse Sequence\"],\n                    title: \"Reverse Sequence\",\n                    minimumSolvedToUnlock: 13,\n                    song: Songs.light,\n                    displayTitle: intl.formatMessage({\n                        id: \"puzzleTitleReverse Sequence\",\n                        description: \"Title of the 'Reverse Sequence' puzzle\",\n                        defaultMessage: \"Reverse Sequence\",\n                    }),\n                    description: intl.formatMessage({\n                        id: \"puzzleDescriptionReverse Sequence\",\n                        description: \"Description of the 'Reverse Sequence' puzzle\",\n                        defaultMessage: \"Read a sequence of positive numbers (terminated by a zero) and output the sequence in reverse order (with zero terminator). Repeat.\",\n                    }),\n                    hint: intl.formatMessage({\n                        id: \"puzzleHintReverse Sequence\",\n                        description: \"Hint for the 'Reverse Sequence' puzzle\",\n                        defaultMessage: \"<p>Use a stack, and remember to clear the stack afterwards.</p>\",\n                    }),\n                },\n                {\n                    ...titleToPuzzle[\"Interleave\"],\n                    title: \"Interleave\",\n                    minimumSolvedToUnlock: 13,\n                    song: Songs.major,\n                    displayTitle: intl.formatMessage({\n                        id: \"puzzleTitleInterleave\",\n                        description: \"Title of the 'Interleave' puzzle\",\n                        defaultMessage: \"Interleave\",\n                    }),\n                    description: intl.formatMessage({\n                        id: \"puzzleDescriptionInterleave\",\n                        description: \"Description of the 'Interleave' puzzle\",\n                        defaultMessage: \"Read two equal length positive sequences (A and B) and interleave their elements (A1, B1, A2, B2, ...), ending with a single zero. Repeat.\",\n                    }),\n                    hint: intl.formatMessage({\n                        id: \"puzzleHintInterleave\",\n                        description: \"Hint for the 'Interleave' puzzle\",\n                        defaultMessage: \"<p>Store the first list for later output. Remember to clear the list afterwards.</p>\",\n                    }),\n                },\n                {\n                    ...titleToPuzzle[\"Indicator Function\"],\n                    title: \"Indicator Function\",\n                    minimumSolvedToUnlock: 13,\n                    displayTitle: intl.formatMessage({\n                        id: \"puzzleTitleIndicator Function\",\n                        description: \"Title of the 'Indicator Function' puzzle\",\n                        defaultMessage: \"Indicator Function\",\n                    }),\n                    description: intl.formatMessage({\n                        id: \"puzzleDescriptionIndicator Function\",\n                        description: \"Description of the 'Indicator Function' puzzle\",\n                        defaultMessage: \"Read two zero-terminated sets of numbers on the interval [1, 99], A and B. For each element of B, output a 1 if the value is in A and 0 otherwise. Repeat.\",\n                    }),\n                    hint: intl.formatMessage({\n                        id: \"puzzleHintIndicator Function\",\n                        description: \"Hint for the 'Indicator Function' puzzle\",\n                        defaultMessage: \"<p>Store the first list for later lookup. Remember to clear the list afterwards.</p>\",\n                    }),\n                },\n                {\n                    ...titleToPuzzle[\"Sort\"],\n                    title: \"Sort\",\n                    minimumSolvedToUnlock: 13,\n                    song: Songs.light,\n                    displayTitle: intl.formatMessage({\n                        id: \"puzzleTitleSort\",\n                        description: \"Title of the 'Sort' puzzle\",\n                        defaultMessage: \"Sort\",\n                    }),\n                    description: intl.formatMessage({\n                        id: \"puzzleDescriptionSort\",\n                        description: \"Description of the 'Sort' puzzle\",\n                        defaultMessage: \"Read a list of numbers on the interval [1, 99] (terminated by a zero) and output the list ordered smallest to largest, ending with a zero. Repeat.\",\n                    }),\n                    hint: intl.formatMessage({\n                        id: \"puzzleHintSort\",\n                        description: \"Hint for the 'Sort' puzzle\",\n                        defaultMessage: \"<p>Insert items into memory in the correct position.</p>\",\n                    }),\n                },\n                {\n                    ...titleToPuzzle[\"Mode\"],\n                    title: \"Mode\",\n                    minimumSolvedToUnlock: 13,\n                    song: Songs.major,\n                    displayTitle: intl.formatMessage({\n                        id: \"puzzleTitleMode\",\n                        description: \"Title of the 'Mode' puzzle\",\n                        defaultMessage: \"Mode\",\n                    }),\n                    description: intl.formatMessage({\n                        id: \"puzzleDescriptionMode\",\n                        description: \"Description of the 'Mode' puzzle\",\n                        defaultMessage: \"Read a list of numbers on the interval [1, 99] (terminated by a zero) and output the most common element. Repeat.\",\n                    }),\n                    hint: intl.formatMessage({\n                        id: \"puzzleHintMode\",\n                        description: \"Hint for the 'Mode' puzzle\",\n                        defaultMessage: \"<p>Track both the items, as well as their count.</p>\",\n                    }),\n                },\n            ],\n        },\n        {\n            groupTitle: <FormattedMessage\n                id=\"puzzleGroupTitleNatural Language Processing\"\n                description=\"Title of 'Natural Language Processing' puzzle group\"\n                defaultMessage=\"Natural Language Processing\"\n            />,\n            list: [\n                {\n                    ...titleToPuzzle[\"Characters\"],\n                    title: \"Characters\",\n                    minimumSolvedToUnlock: 18,\n                    outputFormat: Format.characters,\n                    displayTitle: intl.formatMessage({\n                        id: \"puzzleTitleCharacters\",\n                        description: \"Title of the 'Characters' puzzle\",\n                        defaultMessage: \"Characters\",\n                    }),\n                    description: intl.formatMessage({\n                        id: \"puzzleDescriptionCharacters\",\n                        description: \"Description of the 'Characters' puzzle\",\n                        defaultMessage: \"Output the following two characters: \\\"Hi\\\"\",\n                    }),\n                    hint: intl.formatMessage({\n                        id: \"puzzleHintCharacters\",\n                        description: \"Hint for the 'Characters' puzzle\",\n                        defaultMessage: \"<p>This task has already been solved, but note how character literals are used (and negated).</p>\",\n                    }),\n                    code: intl.formatMessage({\n                        id: \"puzzleCodeCharacters\",\n                        description: \"Initial code for the 'Characters' puzzle\",\n                        defaultMessage:\n`; When configured properly, the SIC-1 supports natural human language input and output using a highly modern (c. 1967) mapping from numbers to characters known as ASCII. For example, 72 is mapped to \"H\" (capital \"h\").\n;\n; To capture the characters \"Hi\" (capital \"h\", lower case \"i\") in two variables, one could consult an ASCII lookup table and write:\n;\n;   @H: .data 72\n;   @i: .data 105\n;\n; Consulting an ASCII table is tedious, so to make SIC Systems engineers' lives easier, SIC-1 Assembly Language now supports automated ASCII lookup using the following advanced syntax (which is equivalent to explicitly specifying characters' mapped numbers):\n;\n;   @H: .data 'H' ; 72\n;   @i: .data 'i' ; 105\n;\n; As a final convenience, it is possible to negate the value of a character by prefixing the character literal with a minus:\n;\n;   @n_H: .data -'H' ; -72\n;\n; The following sample program outputs the characters \"Hi\":\n\nsubleq @OUT, @n_H ; Note: (0 - (-72) = 72 = 'H')\nsubleq @OUT, @n_i\n\n@n_H: .data -'H'\n@n_i: .data -'i'\n`\n                    }),\n                },\n                {\n                    ...titleToPuzzle[\"Decimal Digits\"],\n                    title: \"Decimal Digits\",\n                    minimumSolvedToUnlock: 19,\n                    inputFormat: Format.characters,\n                    displayTitle: intl.formatMessage({\n                        id: \"puzzleTitleDecimal Digits\",\n                        description: \"Title of the 'Decimal Digits' puzzle\",\n                        defaultMessage: \"Decimal Digits\",\n                    }),\n                    description: intl.formatMessage({\n                        id: \"puzzleDescriptionDecimal Digits\",\n                        description: \"Description of the 'Decimal Digits' puzzle\",\n                        defaultMessage: \"Read a decimal digit character, output the numeric value. Repeat.\",\n                    }),\n                    hint: intl.formatMessage({\n                        id: \"puzzleHintDecimal Digits\",\n                        description: \"Hint for the 'Decimal Digits' puzzle\",\n                        defaultMessage: \"<p>Subtract the character literal <code>''0''</code>.</p>\",\n                    }),\n                    code: intl.formatMessage({\n                        id: \"puzzleCodeDecimal Digits\",\n                        description: \"Initial code for the 'Decimal Digits' puzzle\",\n                        defaultMessage:\n`; For this assignment, map each decimal digit character (e.g. '1') to the numeric value it represents (e.g. '1' -> 1). Inputs will be characters, but outputs are expected to be numbers.\n;\n; Keep in mind that the character '1' is not the same as the number 1. The ASCII mapping for '1' is actually 49.\n;\n; Also note that the ASCII mappings for '0', '1', '2', etc. are contiguous:\n;\n; '0' = 48\n; '1' = 49\n; '2' = 50\n; etc.\n\n`\n                    }),\n                },\n                {\n                    ...titleToPuzzle[\"Uppercase\"],\n                    title: \"Uppercase\",\n                    minimumSolvedToUnlock: 19,\n                    inputFormat: Format.characters,\n                    outputFormat: Format.characters,\n                    song: Songs.light,\n                    displayTitle: intl.formatMessage({\n                        id: \"puzzleTitleUppercase\",\n                        description: \"Title of the 'Uppercase' puzzle\",\n                        defaultMessage: \"Uppercase\",\n                    }),\n                    description: intl.formatMessage({\n                        id: \"puzzleDescriptionUppercase\",\n                        description: \"Description of the 'Uppercase' puzzle\",\n                        defaultMessage: \"Read and output characters, converting all lowercase characters to uppercase.\",\n                    }),\n                    hint: intl.formatMessage({\n                        id: \"puzzleHintUppercase\",\n                        description: \"Hint for the 'Uppercase' puzzle\",\n                        defaultMessage: \"<p>Test to see if the input is between \\\"a\\\" and \\\"z\\\", and modify the value as needed.</p>\",\n                    }),\n                    code: intl.formatMessage({\n                        id: \"puzzleCodeUppercase\",\n                        description: \"Initial code for the 'Uppercase' puzzle\",\n                        defaultMessage:\n`; Read and output characters. For each alphabetic character, convert it to uppercase if needed.\n;\n; Note that the mappings for 'a', 'b', ... 'z' are contiguous, as are 'A', 'B', ... 'Z'.\n\n`\n                    }),\n                },\n                {\n                    ...titleToPuzzle[\"Strings\"],\n                    title: \"Strings\",\n                    minimumSolvedToUnlock: 21,\n                    outputFormat: Format.strings,\n                    song: Songs.major,\n                    displayTitle: intl.formatMessage({\n                        id: \"puzzleTitleStrings\",\n                        description: \"Title of the 'Strings' puzzle\",\n                        defaultMessage: \"Strings\",\n                    }),\n                    description: intl.formatMessage({\n                        id: \"puzzleDescriptionStrings\",\n                        description: \"Description of the 'Strings' puzzle\",\n                        defaultMessage: \"Output the string \\\"Hello, world!\\\".\",\n                    }),\n                    hint: intl.formatMessage({\n                        id: \"puzzleHintStrings\",\n                        description: \"Hint for the 'Strings' puzzle\",\n                        defaultMessage: \"<p>This task has already been solved, but note that strings are terminated by a zero.</p>\",\n                    }),\n                    code: intl.formatMessage({\n                        id: \"puzzleCodeStrings\",\n                        description: \"Initial code for the 'Strings' puzzle\",\n                        defaultMessage:\n`; Strings are sequences of characters that are terminated with a zero. In the following example, @string points to a 3 byte sequence representing the string \"Hi\":\n;\n;   @string:\n;   .data 'H'\n;   .data 'i'\n;   .data 0\n;\n; Although not discussed previously, the .data directive can actually take a sequence of values to set multiple bytes, so the previous code could be simplified:\n;\n;   @string: .data 'H', 'i', 0\n;\n; And thanks to the innovative design-by-committee approach employed by SIC Systems, the following novel syntax for strings can be used (again, equivalent to the other examples):\n;\n;   @string: .data \"Hi\" ; Sets the next 3 bytes: 'H', 'i', 0\n;\n; Similar to character values, an entire string can be negated by prefixing it with a minus:\n;\n;   @n_string: .data -\"Hi\" ; Sets the next 3 bytes: -72, -105, 0\n;\n; The following code outputs \"Hello, world!\":\n\n@loop:\nsubleq @OUT, @n_message  ; Read address starts at @n_message\nsubleq @loop+1, @n_one   ; Advance read address\nsubleq @tmp, @tmp, @loop\n\n@n_one: .data -1\n@n_message: .data -\"Hello, world!\"\n@tmp: .data 0\n`\n                    }),\n                },\n                {\n                    ...titleToPuzzle[\"Tokenizer\"],\n                    title: \"Tokenizer\",\n                    minimumSolvedToUnlock: 22,\n                    inputFormat: Format.strings,\n                    outputFormat: Format.strings,\n                        displayTitle: intl.formatMessage({\n                        id: \"puzzleTitleTokenizer\",\n                        description: \"Title of the 'Tokenizer' puzzle\",\n                        defaultMessage: \"Tokenizer\",\n                    }),\n                    description: intl.formatMessage({\n                        id: \"puzzleDescriptionTokenizer\",\n                        description: \"Description of the 'Tokenizer' puzzle\",\n                        defaultMessage: \"Read a string and output each word as its own string. Repeat.\",\n                    }),\n                    hint: intl.formatMessage({\n                        id: \"puzzleHintTokenizer\",\n                        description: \"Hint for the 'Tokenizer' puzzle\",\n                        defaultMessage: \"<p>Strings are terminated by a single zero.</p>\",\n                    }),\n                    code: intl.formatMessage({\n                        id: \"puzzleCodeTokenizer\",\n                        description: \"Initial code for the 'Tokenizer' puzzle\",\n                        defaultMessage:\n`; Read a string and output each word as its own string. Repeat.\n;\n; Note: words are each separated by a single space (and the last word ends with a zero).\n\n`\n                    }),\n                },\n                {\n                    ...titleToPuzzle[\"Parse Decimal\"],\n                    title: \"Parse Decimal\",\n                    minimumSolvedToUnlock: 22,\n                    inputFormat: Format.strings,\n                    song: Songs.light,\n                    displayTitle: intl.formatMessage({\n                        id: \"puzzleTitleParse Decimal\",\n                        description: \"Title of the 'Parse Decimal' puzzle\",\n                        defaultMessage: \"Parse Decimal\",\n                    }),\n                    description: intl.formatMessage({\n                        id: \"puzzleDescriptionParse Decimal\",\n                        description: \"Description of the 'Parse Decimal' puzzle\",\n                        defaultMessage: \"Read a string representing a number on the interval [1, 127] and output the corresponding value. Repeat.\",\n                    }),\n                    hint: intl.formatMessage({\n                        id: \"puzzleHintParse Decimal\",\n                        description: \"Hint for the 'Parse Decimal' puzzle\",\n                        defaultMessage: \"<p>Shifting left one decimal digit is the same as multiplying by ten.</p>\",\n                    }),\n                },\n                {\n                    ...titleToPuzzle[\"Print Decimal\"],\n                    title: \"Print Decimal\",\n                    minimumSolvedToUnlock: 22,\n                    outputFormat: Format.strings,\n                    displayTitle: intl.formatMessage({\n                        id: \"puzzleTitlePrint Decimal\",\n                        description: \"Title of the 'Print Decimal' puzzle\",\n                        defaultMessage: \"Print Decimal\",\n                    }),\n                    description: intl.formatMessage({\n                        id: \"puzzleDescriptionPrint Decimal\",\n                        description: \"Description of the 'Print Decimal' puzzle\",\n                        defaultMessage: \"Read a positive number on the interval [1, 127] and output a string representing the number in decimal form. Repeat.\",\n                    }),\n                    hint: intl.formatMessage({\n                        id: \"puzzleHintPrint Decimal\",\n                        description: \"Hint for the 'Print Decimal' puzzle\",\n                        defaultMessage: \"<p>Remember to output digits from most significant to least.</p>\",\n                    }),\n                },\n                {\n                    ...titleToPuzzle[\"Calculator\"],\n                    title: \"Calculator\",\n                    minimumSolvedToUnlock: 22,\n                    inputFormat: Format.strings,\n                    song: Songs.major,\n                    displayTitle: intl.formatMessage({\n                        id: \"puzzleTitleCalculator\",\n                        description: \"Title of the 'Calculator' puzzle\",\n                        defaultMessage: \"Calculator\",\n                    }),\n                    description: intl.formatMessage({\n                        id: \"puzzleDescriptionCalculator\",\n                        description: \"Description of the 'Calculator' puzzle\",\n                        defaultMessage: \"Read a string representing arithmetic (+, -, or *) on 2 numbers on the interval [1, 127]; write out the resulting value. Repeat.\",\n                    }),\n                    hint: intl.formatMessage({\n                        id: \"puzzleHintCalculator\",\n                        description: \"Hint for the 'Calculator' puzzle\",\n                        defaultMessage: \"<p>Combine the solutions to \\\"Addition\\\", \\\"Subtraction\\\", \\\"Multiplication\\\", and \\\"Parse Decimal\\\".</p>\",\n                    }),\n                },\n            ],\n        },\n        {\n            groupTitle: <FormattedMessage\n                id=\"puzzleGroupTitleSelf-Hosting\"\n                description=\"Title of 'Self-Hosting' puzzle group\"\n                defaultMessage=\"Self-Hosting\"\n            />,\n            list: [\n                {\n                    ...titleToPuzzle[\"Multi-Line Strings\"],\n                    title: \"Multi-Line Strings\",\n                    minimumSolvedToUnlock: 26,\n                    inputFormat: Format.strings,\n                    outputFormat: Format.strings,\n                        displayTitle: intl.formatMessage({\n                        id: \"puzzleTitleMulti-Line Strings\",\n                        description: \"Title of the 'Multi-Line Strings' puzzle\",\n                        defaultMessage: \"Multi-Line Strings\",\n                    }),\n                    description: intl.formatMessage({\n                        id: \"puzzleDescriptionMulti-Line Strings\",\n                        description: \"Description of the 'Multi-Line Strings' puzzle\",\n                        defaultMessage: \"Read a string with multiple lines and write out each line as a string.\",\n                    }),\n                    hint: intl.formatMessage({\n                        id: \"puzzleHintMulti-Line Strings\",\n                        description: \"Hint for the 'Multi-Line Strings' puzzle\",\n                        defaultMessage: \"<p>This task is very similar to Tokenizer.</p>\",\n                    }),\n                    code: intl.formatMessage({\n                        id: \"puzzleCodeMulti-Line Strings\",\n                        description: \"Initial code for the 'Multi-Line Strings' puzzle\",\n                        defaultMessage:\n`; New line characters (value 10) can be expressed with the character '\\\\n'. They can also be used in strings, for example: \"Line 1\\\\nLine 2\".\n;\n; Read a string with multiple lines and write out each line as a string.\n\n`\n                    }),\n                },\n                {\n                    ...titleToPuzzle[\"Parse Data Directives\"],\n                    title: \"Parse Data Directives\",\n                    minimumSolvedToUnlock: 27,\n                    inputFormat: Format.strings,\n                    song: Songs.light,\n                    displayTitle: intl.formatMessage({\n                        id: \"puzzleTitleParse Data Directives\",\n                        description: \"Title of the 'Parse Data Directives' puzzle\",\n                        defaultMessage: \"Parse Data Directives\",\n                    }),\n                    description: intl.formatMessage({\n                        id: \"puzzleDescriptionParse Data Directives\",\n                        description: \"Description of the 'Parse Data Directives' puzzle\",\n                        defaultMessage: \"Parse a program with multiple .data directives and output the corresponding values.\",\n                    }),\n                    hint: intl.formatMessage({\n                        id: \"puzzleHintParse Data Directives\",\n                        description: \"Hint for the 'Parse Data Directives' puzzle\",\n                        defaultMessage: \"<p>This task is similar to \\\"Parse Decimal\\\", but negative numbers need to be handled.</p>\",\n                    }),\n                    code: intl.formatMessage({\n                        id: \"puzzleCodeParse Data Directives\",\n                        description: \"Initial code for the 'Parse Data Directives' puzzle\",\n                        defaultMessage:\n`; Parse a program with multiple .data directives and output the corresponding values.\n;\n; Each .data directive only has a single value on the range [-128, 127] (inclusive).\n\n`\n                    }),\n                },\n                {\n                    ...titleToPuzzle[\"Parse Subleq Instructions\"],\n                    title: \"Parse Subleq Instructions\",\n                    minimumSolvedToUnlock: 28,\n                    inputFormat: Format.strings,\n                    displayTitle: intl.formatMessage({\n                        id: \"puzzleTitleParse Subleq Instructions\",\n                        description: \"Title of the 'Parse Subleq Instructions' puzzle\",\n                        defaultMessage: \"Parse Subleq Instructions\",\n                    }),\n                    description: intl.formatMessage({\n                        id: \"puzzleDescriptionParse Subleq Instructions\",\n                        description: \"Description of the 'Parse Subleq Instructions' puzzle\",\n                        defaultMessage: \"Parse a program with multiple subleq instructions and output the compiled program.\",\n                    }),\n                    hint: intl.formatMessage({\n                        id: \"puzzleHintParse Subleq Instructions\",\n                        description: \"Hint for the 'Parse Subleq Instructions' puzzle\",\n                        defaultMessage: \"<p>This task is very similar to \\\"Parse Decimal\\\".</p>\",\n                    }),\n                    code: intl.formatMessage({\n                        id: \"puzzleCodeParse Subleq Instructions\",\n                        description: \"Initial code for the 'Parse Subleq Instructions' puzzle\",\n                        defaultMessage:\n`; Parse a program with multiple subleq instructions and output the compiled program.\n;\n; Each subleq instruction specifies 3 addresses, separated by spaces (' '). The addresses are on the range [0, 255] (inclusive).\n;\n; Note that the unsigned (nonnegative) addresses will be written out as signed values on the range [-128, 127] (also inclusive). For example, 255 becomes -1, 254 becomes -2, ..., 128 becomes -128, but 127 and below are unchanged.\n\n`\n                    }),\n                },\n                {\n                    ...titleToPuzzle[\"Self-Hosting\"],\n                    title: \"Self-Hosting\",\n                    minimumSolvedToUnlock: 29,\n                    inputFormat: Format.strings,\n                    song: Songs.major,\n                    displayTitle: intl.formatMessage({\n                        id: \"puzzleTitleSelf-Hosting\",\n                        description: \"Title of the 'Self-Hosting' puzzle\",\n                        defaultMessage: \"Self-Hosting\",\n                    }),\n                    description: intl.formatMessage({\n                        id: \"puzzleDescriptionSelf-Hosting\",\n                        description: \"Description of the 'Self-Hosting' puzzle\",\n                        defaultMessage: \"Read in a SIC-1 program and execute it until it branches to address 255, writing out any values written to address 254. Repeat.\",\n                    }),\n                    hint: intl.formatMessage({\n                        id: \"puzzleHintSelf-Hosting\",\n                        description: \"Hint for the 'Self-Hosting' puzzle\",\n                        defaultMessage: \"<p>Use previous decimal-parsing solutions to compile the program, but take care to follow the instructions precisely.</p>\",\n                    }),\n                    code: intl.formatMessage({\n                        id: \"puzzleCodeSelf-Hosting\",\n                        description: \"Initial code for the 'Self-Hosting' puzzle\",\n                        defaultMessage:\n`; Parse a program containing .data directives and subleq instructions, then execute that program.\n;\n; All addresses used by the input program should be isolated from your program's address space.\n;\n; As in any other program, if the program writes to address 254 (@OUT; signed value: -2), that value should be directly written out.\n;\n; If the program branches to address 255 (@HALT; signed value: -1), then the program is done. Start over from scratch with the next input program.\n;\n; The compiled size of each input program is ≤ 21 bytes.\n;\n; As in previous tasks, the .data directive will always have exactly 1 value and subleq instructions will specify exactly 3 addresses (separated by spaces only).\n;\n; Additionally, the input programs will not use self-modifying code or declare/use any labels or variables. The only built-in addresses that will be used will be referenced by address instead of label (e.g. \"254\" will be used but \"@OUT\" will not).\n\n`\n                    }),\n                },\n                {\n                    ...titleToPuzzle[\"Self-Hosting Part 2\"],\n                    title: \"Self-Hosting Part 2\",\n                    minimumSolvedToUnlock: 30,\n                    inputFormat: Format.strings,\n                    song: Songs.boss,\n                    displayTitle: intl.formatMessage({\n                        id: \"puzzleTitleSelf-Hosting Part 2\",\n                        description: \"Title of the 'Self-Hosting Part 2' puzzle\",\n                        defaultMessage: \"Self-Hosting Part 2\",\n                    }),\n                    description: intl.formatMessage({\n                        id: \"puzzleDescriptionSelf-Hosting Part 2\",\n                        description: \"Description of the 'Self-Hosting Part 2' puzzle\",\n                        defaultMessage: \"Read in a self-modifying SIC-1 program and execute it until it branches to address 255, writing out any values written to address 254. Repeat.\",\n                    }),\n                    hint: intl.formatMessage({\n                        id: \"puzzleHintSelf-Hosting Part 2\",\n                        description: \"Hint for the 'Self-Hosting Part 2' puzzle\",\n                        defaultMessage: \"<p>You're on your own for this one.</p>\",\n                    }),\n                    code: intl.formatMessage({\n                        id: \"puzzleCodeSelf-Hosting Part 2\",\n                        description: \"Initial code for the 'Self-Hosting Part 2' puzzle\",\n                        defaultMessage:\n`; Parse a self-modifying program containing .data directives and subleq instructions, then execute that program.\n;\n; Writes to address @OUT should be directly written out. If the program branches to address @HALT, then the program is done. Start over from scratch with the next input program.\n;\n; The compiled size of each input program is ≤ 21 bytes.\n;\n; As in previous tasks, the .data directive will always have exactly 1 value and subleq instructions will specify exactly 3 addresses (separated by spaces only) and no labels will be used.\n\n`\n                    }),\n                },\n            ],\n        },\n    ];\n\n    const puzzleFlatArray = [].concat(...clientPuzzlesGrouped.map(p => p.list));\n\n    const titleToClientPuzzle: { [title: string]: ClientPuzzle } = {};\n    for (const puzzle of puzzleFlatArray) {\n        titleToClientPuzzle[puzzle.title] = puzzle;\n    }\n\n    const puzzleSandbox: ClientPuzzle = {\n        title: \"Sandbox Mode\",\n        displayTitle: intl.formatMessage({\n            id: \"puzzleTitleSandbox Mode\",\n            description: \"Title of the 'Sandbox Mode' puzzle\",\n            defaultMessage: \"Sandbox Mode\",\n        }),\n        description: intl.formatMessage({\n            id: \"puzzleDescriptionSandbox Mode\",\n            description: \"Description of the 'Sandbox Mode' puzzle\",\n            defaultMessage: \"An open-ended, configurable program for exploration purposes.\",\n        }),\n        hint: intl.formatMessage({\n            id: \"puzzleHintSandbox Mode\",\n            description: \"Hint for the 'Sandbox Mode' puzzle\",\n            defaultMessage: `<p>Click \"Configure Input\" to supply custom input.</p>`,\n        }),\n        minimumSolvedToUnlock: 4,\n        customInput: true,\n    \n        puzzleViewOverride: <FormattedMessage\n            id=\"puzzleDetailSandbox Mode\"\n            description=\"Detailed description of 'Sandbox Mode', shown on its task viewer page\"\n            defaultMessage={`<p>Use Sandbox Mode to freely experiment with the SIC-1 without worrying about output getting flagged as incorrect.</p><p>It's possible to specify custom input using the \"Configure Input\" button on the left side of the main SIC-1 Development Environment (above the IO table). Input uses the same syntax as in a <code>.data</code> directive (examples: <code>-7</code>, <code>''A''</code>, <code>-\"Negated string\"</code>).</p>`}\n            />,\n    \n        code: intl.formatMessage({\n            id: \"puzzleCodeSandbox Mode\",\n            description: \"Initial code for the 'Sandbox Mode' puzzle\",\n            defaultMessage:\n`; This is an open-ended program that allows specifying arbitrary input to help employees explore how the SIC-1 operates.\n;\n; Use the \"Configure Input\" button to the left (above the IO table) to provide custom input to the program.`,\n        }),\n    };\n\n    return {\n        clientPuzzlesGrouped,\n        puzzleFlatArray,\n        clientPuzzles: [].concat(...puzzleFlatArray, puzzleSandbox),\n        titleToClientPuzzle,\n        puzzleSandbox,\n    };\n}\n", "sic1/client/ts/mail-story.tsx": "import React from \"react\";\nimport { Contacts } from \"./contacts\";\nimport { FormattedMessage } from \"react-intl\";\nimport { Mail } from \"./mail-shared\";\nimport { Shared } from \"./shared\";\n\nconst asciiTable = <table id=\"asciitable\">\n<tbody>\n<tr><th></th><th>0</th><th>1</th><th>2</th><th>3</th><th>4</th><th>5</th><th>6</th><th>7</th><th>8</th><th>9</th></tr>\n<tr><th>30</th><td>□</td><td>□</td><td title=\"Code: 32, character:  \"> </td><td title=\"Code: 33, character: !\">!</td><td title=\"Code: 34, character: &quot;\">&quot;</td><td title=\"Code: 35, character: #\">#</td><td title=\"Code: 36, character: $\">$</td><td title=\"Code: 37, character: %\">%</td><td title=\"Code: 38, character: &amp;\">&amp;</td><td title=\"Code: 39, character: &#39;\">&#39;</td></tr>\n<tr><th>40</th><td title=\"Code: 40, character: (\">(</td><td title=\"Code: 41, character: )\">)</td><td title=\"Code: 42, character: *\">*</td><td title=\"Code: 43, character: +\">+</td><td title=\"Code: 44, character: ,\">,</td><td title=\"Code: 45, character: -\">-</td><td title=\"Code: 46, character: .\">.</td><td title=\"Code: 47, character: /\">/</td><td title=\"Code: 48, character: 0\">0</td><td title=\"Code: 49, character: 1\">1</td></tr>      \n<tr><th>50</th><td title=\"Code: 50, character: 2\">2</td><td title=\"Code: 51, character: 3\">3</td><td title=\"Code: 52, character: 4\">4</td><td title=\"Code: 53, character: 5\">5</td><td title=\"Code: 54, character: 6\">6</td><td title=\"Code: 55, character: 7\">7</td><td title=\"Code: 56, character: 8\">8</td><td title=\"Code: 57, character: 9\">9</td><td title=\"Code: 58, character: :\">:</td><td title=\"Code: 59, character: ;\">;</td></tr>      \n<tr><th>60</th><td title=\"Code: 60, character: &lt;\">&lt;</td><td title=\"Code: 61, character: =\">=</td><td title=\"Code: 62, character: &gt;\">&gt;</td><td title=\"Code: 63, character: ?\">?</td><td title=\"Code: 64, character: @\">@</td><td title=\"Code: 65, character: A\">A</td><td title=\"Code: 66, character: B\">B</td><td title=\"Code: 67, character: C\">C</td><td title=\"Code: 68, character: D\">D</td><td title=\"Code: 69, character: E\">E</td></tr>\n<tr><th>70</th><td title=\"Code: 70, character: F\">F</td><td title=\"Code: 71, character: G\">G</td><td title=\"Code: 72, character: H\">H</td><td title=\"Code: 73, character: I\">I</td><td title=\"Code: 74, character: J\">J</td><td title=\"Code: 75, character: K\">K</td><td title=\"Code: 76, character: L\">L</td><td title=\"Code: 77, character: M\">M</td><td title=\"Code: 78, character: N\">N</td><td title=\"Code: 79, character: O\">O</td></tr>\n<tr><th>80</th><td title=\"Code: 80, character: P\">P</td><td title=\"Code: 81, character: Q\">Q</td><td title=\"Code: 82, character: R\">R</td><td title=\"Code: 83, character: S\">S</td><td title=\"Code: 84, character: T\">T</td><td title=\"Code: 85, character: U\">U</td><td title=\"Code: 86, character: V\">V</td><td title=\"Code: 87, character: W\">W</td><td title=\"Code: 88, character: X\">X</td><td title=\"Code: 89, character: Y\">Y</td></tr>\n<tr><th>90</th><td title=\"Code: 90, character: Z\">Z</td><td title=\"Code: 91, character: [\">[</td><td title=\"Code: 92, character: \\\">\\</td><td title=\"Code: 93, character: ]\">]</td><td title=\"Code: 94, character: ^\">^</td><td title=\"Code: 95, character: _\">_</td><td title=\"Code: 96, character: `\">`</td><td title=\"Code: 97, character: a\">a</td><td title=\"Code: 98, character: b\">b</td><td title=\"Code: 99, character: c\">c</td></tr>\n<tr><th>100</th><td title=\"Code: 100, character: d\">d</td><td title=\"Code: 101, character: e\">e</td><td title=\"Code: 102, character: f\">f</td><td title=\"Code: 103, character: g\">g</td><td title=\"Code: 104, character: h\">h</td><td title=\"Code: 105, character: i\">i</td><td title=\"Code: 106, character: j\">j</td><td title=\"Code: 107, character: k\">k</td><td title=\"Code: 108, character: l\">l</td><td title=\"Code: 109, character: m\">m</td></tr>\n<tr><th>110</th><td title=\"Code: 110, character: n\">n</td><td title=\"Code: 111, character: o\">o</td><td title=\"Code: 112, character: p\">p</td><td title=\"Code: 113, character: q\">q</td><td title=\"Code: 114, character: r\">r</td><td title=\"Code: 115, character: s\">s</td><td title=\"Code: 116, character: t\">t</td><td title=\"Code: 117, character: u\">u</td><td title=\"Code: 118, character: v\">v</td><td title=\"Code: 119, character: w\">w</td></tr>\n<tr><th>120</th><td title=\"Code: 120, character: x\">x</td><td title=\"Code: 121, character: y\">y</td><td title=\"Code: 122, character: z\">z</td><td title=\"Code: 123, character: &#123;\">&#123;</td><td title=\"Code: 124, character: |\">|</td><td title=\"Code: 125, character: &#125;\">&#125;</td><td title=\"Code: 126, character: ~\">~</td><td>□</td><td>□</td><td>□</td></tr>\n</tbody>\n</table>;\n\n// Generated by convert-mail.ts\nexport const storyMails = [\n    [\n\n    {\n        id: \"s0_0\",\n        solvedCount: 0,\n        from: Contacts.onboarding,\n        subject: <FormattedMessage\n            id=\"mails0_0Subject\"\n            description=\"Subject line for story mail s0_0\"\n            defaultMessage=\"SIC-1 Reference Manual\"\n            />,\n        create: (context) => <FormattedMessage\n            id=\"mails0_0Content\"\n            description=\"HTML content for story mail s0_0\"\n            defaultMessage={`<h3>Single Instruction Computer Mark 1 (SIC-1)</h3>\n<p>The Single Instruction Computer Mark 1 (SIC-1) is an 8-bit computer with 256 bytes of memory. Programs for the SIC-1 are written in SIC-1 Assembly Language, as described below.</p>\n<h3><code>subleq</code> instruction</h3>\n<p>Each <code>subleq</code> instruction is 3 bytes, specified as follows:</p>\n<pre><code>subleq A B [C]\n</code></pre>\n<p><code>A</code>, <code>B</code>, and <code>C</code> are memory addresses (0 - 255) or labels.</p>\n<p><code>subleq</code> subtracts the value at address <code>B</code> from the value at address <code>A</code> and stores the result at address <code>A</code> (i.e. <code>mem[A]</code> is set to <code>mem[A] - mem[B]</code>).</p>\n<p>If the result is ≤ 0, execution branches to address <code>C</code>.</p>\n<p>Note that if <code>C</code> is not specified, the address of the next instruction is automatically added by the assembler (in effect, this means that taking the branch is no different from advancing to the next instruction).</p>\n<h3>Built-in addresses</h3>\n<p>For convenience, addresses can be specified using labels. The following predefined labels are always available:</p>\n<ul>\n<li><code>@MAX</code> (252): Maximum user-modifiable address</li>\n<li><code>@IN</code> (253): Reads a value from input (writes are ignored)</li>\n<li><code>@OUT</code> (254): Writes a result to output (reads as zero)</li>\n<li><code>@HALT</code> (255): Terminates the program when accessed (reads and write are ignored)</li>\n</ul>\n<h3><code>subleq</code> example</h3>\n<p>Below is a very simple SIC-1 program that negates one input value and writes it out.</p>\n<p>E.g. if the input value from <code>@IN</code> is 3, it subtracts 3 from <code>@OUT</code> (which reads as zero), and the result of 0 - 3 = -3 is written out.</p>\n<pre><code>subleq @OUT, @IN\n</code></pre>\n<h3>Comments</h3>\n<p>Any text following a semicolon is considered a comment. Comments are ignored by the assembler, but may be helpful to humans attempting to decipher existing programs. For example, here''s the previous line of assembly with an explanatory comment:</p>\n<pre><code>subleq @OUT, @IN ; Negates an input and writes it out\n</code></pre>\n<h3>Labels</h3>\n<p>Custom labels are defined with the syntax <code>@name:</code>, e.g.:</p>\n<pre><code>@loop: subleq 1, 2\n</code></pre>\n<p>Label names cannot include punctuation, symbols, or whitespace.</p>\n<h3><code>.data</code> directive</h3>\n<p>In addition to <code>subleq</code>, there is an assembler directive <code>.data</code> that sets one or more bytes of memory to specific values at compile time (note: this is not an instruction!):</p>\n<pre><code>.data X\n</code></pre>\n<p>In the simplest case, <code>X</code> is a signed byte between -128 and 127 (inclusive).</p>\n<p>Multiple values can also be provided (separated by whitespace and, optionally, commas):</p>\n<pre><code>.data 1, -2, 3\n</code></pre>\n<p>Note: labels (with optional offsets), characters, and strings--along with negations of these--can also be supplied. Examples of these appear in subsequent sections.</p>\n<h3>Constants and variables</h3>\n<p>Combining labels and the <code>.data</code> directive allows you to develop a system of constants and variables. For example, here a byte is set to zero, and the label <code>@zero</code> points to that value:</p>\n<pre><code>@zero: .data 0\n</code></pre>\n<h3>Unconditional jumps</h3>\n<p>Variables can be used for implementing an unconditional jump:</p>\n<pre><code>subleq @zero, @zero, @next\n</code></pre>\n<p>This will set <code>@zero</code> to zero minus zero (still zero) and, since the result is always ≤ 0, execution always branches to the label <code>@next</code>.</p>\n<h3>Loop example</h3>\n<p>Below is an updated negation program that repeatedly negates input values and writes them out in a loop.</p>\n<pre><code>@loop:\nsubleq @OUT, @IN           ; Negate an input and write it out\nsubleq @zero, @zero, @loop ; Unconditional jump to @loop\n\n@zero: .data 0             ; Always zero\n</code></pre>\n<h3>Label offsets</h3>\n<p>Label expressions can include an optional offset. For example, <code>@loop+1</code> refers to the <em>second</em> byte of the instruction pointed to by <code>@loop</code>:</p>\n<pre><code>@loop:\nsubleq @loop+1, @one\n</code></pre>\n<p>Note: in certain cases (usually involving self-modifying code), it is useful to store the address associated with a label (possibly with an offset) in a byte of memory. Here is an example of how to set a byte of memory to the address of <code>@loop+1</code> (i.e. the <em>second</em> byte of the instruction at <code>@loop</code>):</p>\n<pre><code>; Address of the second byte of @loop\n@loop_plus_one: .data @loop+1\n</code></pre>\n<p>It is possible to negate labels as well by prefixing them with a minus sign. Keep in mind that this only negates the label''s address itself, so if a label with an offset needs to be negated, both the label <em>and the offset</em> should be negated. Here''s the negation of the previous example:</p>\n<pre><code>; Negation of @loop+1\n@n_loop_plus_one: .data -@loop-1\n</code></pre>\n<h3>Inline labels</h3>\n<p>As an alternative to offsets, labels can be defined inline. For example <code>@source</code> refers to the <em>second</em> byte of the following instruction:</p>\n<pre><code>subleq 0, @source:1\n</code></pre>\n<h3>Reflection example</h3>\n<p>Label offsets and inline labels are useful in self-modifying code. Remember, each <code>subleq</code> instruction is stored as 3 consecutive addresses: <code>ABC</code> (for <code>mem[A] ← mem[A] - mem[B]</code>, with a branch to <code>C</code> if the result is less than or equal to zero).</p>\n<p>The sample program below reads its own compiled code and outputs it by incrementing the second address of the instruction at <code>@loop</code> (i.e. modifying address <code>@loop+1</code>).</p>\n<pre><code>@loop:\nsubleq @tmp, 0           ; Second address (initially zero) will be incremented below\nsubleq @OUT, @tmp        ; Output the value\nsubleq @loop+1, @n_one   ; Here is where the increment is performed\nsubleq @tmp, @tmp, @loop ; Reset @tmp to zero and unconditionally jump to @loop\n\n@tmp: .data 0            ; @tmp is initialized to zero\n@n_one: .data -1\n</code></pre>\n<p>The third instruction is an example of self-modifying code because it actually modifies the first instruction. Specifically, it increments the first instruction''s second address (<code>@loop+1</code>). This causes the <em>next</em> loop iteration''s first instruction to read the <em>next</em> byte of memory (0, 1, 2, 3, ...).</p>\n<p>The program above used a label with an offset, but it could have just as easily been written using an inline label (e.g. defining a <em>new</em> label, <code>subleq @tmp, @source:0</code>, and referring to <code>@source</code> instead of <code>@loop+1</code>). Both approaches compile down to the same sequence of bytes.</p>\n<p>Note: When running a program in the SIC-1 Development Environment, the original (unmodified) source code is always shown. If the program modifies itself, the changes are reflected in the memory table in the top right, but <em>not</em> in the source code viewer.</p>\n<h3>Stack example</h3>\n<p>This program implements a last-in, first-out stack by modifying the read and write addresses of the instructions that interact with the stack.</p>\n<p>The program pushes 3 (defined by <code>@count</code>) input values onto the stack and then pops them off (outputting them in reverse order).</p>\n<pre><code>; The first address of this instruction (which starts\n; pointing to @stack) will be incremented with each\n; write to the stack\n@stack_push:\nsubleq @stack, @IN\nsubleq @count, @one, @prepare_to_pop\n\n; Modify the instruction at @stack_push (increment\n; target address)\nsubleq @stack_push, @n_one\nsubleq @tmp, @tmp, @stack_push\n\n; Prepare to start popping values off of the stack by\n; copying the current stack position to @stack_pop+1\n@prepare_to_pop:\nsubleq @tmp, @stack_push\nsubleq @stack_pop+1, @tmp\n\n; Read a value from the stack (note: the second address\n; of this instruction is repeatedly decremented)\n@stack_pop:\nsubleq @OUT, 0\n\n; Decrement stack address in the instruction at @stack_pop\nsubleq @stack_pop+1, @one\nsubleq @tmp, @tmp, @stack_pop\n\n; Constants\n@one: .data 1\n@n_one: .data -1\n\n; Variables\n@tmp: .data 0\n@count: .data 3\n\n; Base of stack (stack will grow upwards)\n@stack: .data 0\n</code></pre>\n<h3>Characters</h3>\n<p>When configured properly, the SIC-1 supports natural human language input and output using a highly modern (c. 1967) mapping from numbers to characters known as ASCII. For example, 72 is mapped to \"H\" (capital \"h\").</p>\n<p>To capture the characters \"Hi\" (capital \"h\", lower case \"i\") in two variables, one could consult an ASCII lookup table and write:</p>\n<pre><code>@H: .data 72\n@i: .data 105\n</code></pre>\n<p>Consulting an ASCII table is tedious, so to make SIC Systems engineers'' lives easier, SIC-1 Assembly Language now supports automated ASCII lookup using the following advanced syntax (which is equivalent to explicitly specifying characters'' mapped numbers):</p>\n<pre><code>@H: .data ''H'' ; 72\n@i: .data ''i'' ; 105\n</code></pre>\n<p>As a final convenience, it is possible to negate the value of a character by prefixing the character literal with a minus:</p>\n<pre><code>@n_H: .data -''H'' ; -72\n</code></pre>\n<h3>Character output example</h3>\n<p>The following sample program outputs the characters \"Hi\":</p>\n<pre><code>subleq @OUT, @n_H ; Note: (0 - (-72) = 72 = ''H'')\nsubleq @OUT, @n_i\n\n@n_H: .data -''H''\n@n_i: .data -''i''\n</code></pre>\n<h3>Strings</h3>\n<p>Strings are sequences of characters that are terminated with a zero. In the following example, @string points to a 3 byte sequence representing the string \"Hi\":</p>\n<pre><code>@string:\n.data ''H''\n.data ''i''\n.data 0\n</code></pre>\n<p>The .data directive can also take a sequence of values to set multiple bytes, so the previous code would be simplified:</p>\n<pre><code>@string: .data ''H'', ''i'', 0\n</code></pre>\n<p>And thanks to the innovative design-by-committee approach employed by SIC Systems, the following novel syntax for strings can be used (again, equivalent to the other examples):</p>\n<pre><code>@string: .data \"Hi\" ; Sets the next 3 bytes: ''H'', ''i'', 0\n</code></pre>\n<p>Similar to character values, an entire string can be negated by prefixing it with a minus:</p>\n<pre><code>@n_string: .data -\"Hi\" ; Sets the next 3 bytes: -72, -105, 0\n</code></pre>\n<h3>New line characters</h3>\n<p>New line characters (value 10) can be expressed with the character <code>''\\\\n''</code>. They can also be used in strings, for example: <code>\"Line 1\\\\nLine 2\"</code>.</p>\n<h3>String output example</h3>\n<p>The following code outputs \"Hello, world!\":</p>\n<pre><code>@loop:\nsubleq @OUT, @n_message  ; Read address starts at @n_message\nsubleq @loop+1, @n_one   ; Advance read address\nsubleq @tmp, @tmp, @loop\n\n@n_one: .data -1\n@n_message: .data -\"Hello, world!\"\n@tmp: .data 0\n</code></pre>\n<h3>ASCII Reference</h3>\n<p>For completeness, a table of ASCII characters is shown below. Note that SIC-1 only supports ASCII codes 32 through 126, so the first few rows of the table are omitted (and a few cells contain \"□\" to indicate unsupported codes). Each row represents a tens digit (30 - 120), and each column represents a ones digit (0 - 9).</p>\n<p>Examples:</p>\n<ul>\n<li>Row \"30\", column 2 is a space character (code 32)</li>\n<li>Row \"120\", column 2 a lowercase \"z\" (code 122)</li>\n</ul>\n{asciiTable}\n\n<h3>Errata</h3>\n<p>In order to reduce the time-to-market for the SIC-1, some compromises were made in the design of the processor and these design decisions may result in surprising behavior. This section is an attempt to document such cases:</p>\n<ol>\n<li>For the purposes of calculating the number of memory bytes read, every <code>subleq</code> instruction reads all 3 bytes, regardless of whether or not the final address is used (i.e. regardless of whether or not the branch is taken)</li>\n<li><code>subleq</code> instructions (meaning the 3 addresses that comprise the instruction) are always read directly from memory; additionally, memory addresses 253, 254, and 255 cannot be modified and are initialized to zero, so the instruction starting at <code>@MAX</code> (comprised of bytes 252, 253, and 254) will be read as: <code>mem[252]</code>, 0, 0</li>\n<li><code>subleq @IN, B, C</code> will consume an input in order to compute the result (\"input minus <code>mem[B]</code>\"), which is used to decide whether to branch to <code>C</code> or not (even though no value will be written because writes to <code>@IN</code> are ignored)</li>\n<li><code>subleq @IN, @IN</code> will only consume a single input and the result will always be zero</li>\n<li>Branching to any address above <code>@MAX</code> (252) will halt execution</li>\n<li><code>subleq A, B, @IN</code> may branch to <code>@IN</code> (253), which will halt (see previous bullet)</li>\n</ol>\n`}\n            values={{ asciiTable }}\n            />,\n        actions: [\n            \"manualInNewWindow\"\n        ],\n    },\n\n\n    {\n        id: \"s0_1\",\n        solvedCount: 0,\n        from: Contacts.onboarding,\n        subject: <FormattedMessage\n            id=\"mails0_1Subject\"\n            description=\"Subject line for story mail s0_1\"\n            defaultMessage=\"SIC-1 Dev. Environment\"\n            />,\n        create: (context) => <FormattedMessage\n            id=\"mails0_1Content\"\n            description=\"HTML content for story mail s0_1\"\n            defaultMessage={`<h3>SIC-1 DEVELOPMENT ENVIRONMENT</h3>\n<p>The SIC-1 Development Environment provides a state-of-the-art programming and simulation environment for SIC Systems''s Single Instruction Computer Mark 1 (SIC-1).</p>\n<h3>MENUS</h3>\n<p>Menus can be accessed using either the \"Esc\" key or the \"Menu\" button in the lower-left of the development environment. The Main Menu provides access to the following:</p>\n<ul>\n<li><strong>Program Inventory</strong>: Used for switching between assigned programming tasks, as well as viewing employee and task statistics (described in a dedicated section below).</li>\n<li><strong>Electronic Mail</strong>: An integrated client application for viewing electronic mail from automated agents and other SIC-1 employees (described in a dedicated section below).</li>\n<li><strong>Options</strong>: A sub-menu for modifying presentation settings (full-screen mode, volume, etc.), and other miscellaneous menus.</li>\n</ul>\n<h3>INTEGRATED DEVELOPMENT ENVIRONMENT</h3>\n<p>The SIC-1 Development Environment desktop is an integrated development environment (IDE) for the SIC-1. There are three main sections (left, right, center):</p>\n<ul>\n<li><strong>Left</strong>: Current task description, table of input and output (both expected and actual), simulation state/statistics, buttons for controlling the simulation, and a button for opening the Main Menu (described above).</li>\n<li><strong>Center</strong>: Main code editor for reading and writing SIC-1 Assembly Language programs (see the separate SIC-1 Reference Manual electronic mail for details).</li>\n<li><strong>Right</strong>: Detailed simulation state including a complete view of SIC-1 memory, code manipulation tools, as well as an unprecedented, revolutionary feature: a table of variables and their current values, for convenient lookup.</li>\n</ul>\n<p>The memory table is shown in hexadecimal for compactness; hover over a cell to see the corresponding decimal value.</p>\n<p>During execution, the current instruction will be highlighted in both the code editor (center) and the memory table (upper right), current inputs and outputs are highlighted in the tables on the left, and variables are displayed in a table on the right (hover for hexadecimal and unsigned representations, if needed).</p>\n<p>To aid debugging, it is possible to set breakpoints on <code>subleq</code> instructions. When hit, these breakpoints will pause execution for manual analysis. There are two ways to set breakpoints:</p>\n<ul>\n<li>In code, add <code>!</code> to the beginning of a line (e.g. <code>!subleq @OUT, @IN</code>).</li>\n<li>During execution, click the small circle to the left of any <code>subleq</code> instruction to toggle the breakpoint.</li>\n</ul>\n<p>Note that each program may be tested using multiple distinct test sets, the state of the SIC-1 resets between test sets, and the test sets generally include randomly generated input data. Solutions should be robust to arbitrary random data, in order to be eligible for inclusion in solution statistics.</p>\n<h3>KEYBOARD SHORTCUTS</h3>\n<p>The SIC-1 Development Environment supports the following convenient keyboard shortcuts:</p>\n<ul>\n<li><strong>Esc</strong>: Open/close menu or, if running, pause/halt execution.</li>\n<li><strong>Ctrl+.</strong>: Execute a single instruction and pause. If the program has not been compiled yet, this will compile the program and pause before executing the first instruction.</li>\n<li><strong>Ctrl+Enter</strong>: Run instructions until completion/error/pause. If already running, this will increase the speed of execution.</li>\n<li><strong>Ctrl+Shift+Enter</strong>: Pause execution (if running), otherwise halt execution.</li>\n<li><strong>F11, Alt+Enter</strong>: Toggle full-screen mode.</li>\n</ul>\n<p>Code editing shortcuts:</p>\n<ul>\n<li><strong>Ctrl+K Ctrl+F</strong>: Comment out all of the selected lines</li>\n<li><strong>Ctrl+K Ctrl+U</strong>: Uncomment all of the selected lines</li>\n<li><strong>Ctrl+M</strong>: Toggle <strong>Tab Insert</strong> mode (by default the Tab key cycles focus, with Tab Insert mode, tabs can be entered into the code editor)</li>\n<li><strong>Tab</strong>: If in <strong>Tab Insert</strong> mode, insert tabs into the selected lines</li>\n<li><strong>Shift+Tab</strong>: If in <strong>Tab Insert</strong> mode, un-indent the selected lines</li>\n</ul>\n<h3>PROGRAM INVENTORY</h3>\n<p>The Program Inventory displays a list of assigned tasks on the left. There is also a special \"employee statistics\" section at the top for viewing how your progress compares to other SIC Systems employees.</p>\n<p>Select any task on the left to view the description (or your solution''s statistics, as compared to other employees'' solutions, for completed tasks). There is button at the bottom to load the program into the development environment.</p>\n<p>Under the \"File Selection\" heading, it''s possible to manage multiple implementations of a task (notably: \"New\" creates a new solution with default contents, \"Copy\" duplicates an existing implementation). This can be useful when there is one solution optimizing for fewest cycles, and a different solution optimizing for accessing the least amount of memory.</p>\n<p>If available, other non-task entries will appear in the Program Inventory, under the \"Diversions\" heading (such as Sandbox Mode or any company-sanctioned electronic video games--only for use during legally-mandated breaks).</p>\n<h3>ELECTRONIC MAIL</h3>\n<p>SIC Systems is pioneering a new digital form of intra-office communication known as \"electronic mail\". This eliminates paper waste for memos, and also ensures that all communications are securely routed to only the intended recipients.</p>\n<p>A complete list of received electronic mail is shown in the left pane of the electronic mail viewer (sorted from oldest at the top to newest at the bottom). Note that automated mails are de-emphasized, but they can be opened to view statistics for your completed programming tasks.</p>\n<p>If you have any unread mail, it will appear in a separate section at the top of the left page, for convenience.</p>\n<p>Also, remember that you can always access the SIC-1 Reference Manual and this document about the SIC-1 Development Environment from your employee on-boarding mails at the top (oldest) part of the left pane of the electronic mail viewer.</p>\n<h3>ADDENDUM</h3>\n<p>Although the SIC-1 Development Environment has been thoroughly tested, it is possible that you may encounter unexpected behavior in certain instances. The authors of the SIC-1 Development Environment have assured us that the most likely causes for such issues are either cosmic rays or large solar flares interfering with sensitive electronics in an unpredictable manner. The simplest way to recover from such interference is to unplug the computer, wait for 30 seconds to allow it to cool and eject any rogue electrons, and then plug it back in.</p>\n`}\n            />,\n        actions: [\n            \"manualInNewWindow\"\n        ],\n    },\n\n\n    {\n        id: \"s0_2\",\n        solvedCount: 0,\n        from: Contacts.hr,\n        subject: <FormattedMessage\n            id=\"mails0_2Subject\"\n            description=\"Subject line for story mail s0_2\"\n            defaultMessage=\"Welcome to SIC Systems!\"\n            />,\n        create: (context) => <FormattedMessage\n            id=\"mails0_2Content\"\n            description=\"HTML content for story mail s0_2\"\n            defaultMessage={`<p>Congratulations, {selfName}! SIC Systems has accepted your job application.</p>\n<p>I''m Mary, and I''ll be your human resources contact at the company.</p>\n<p>As you''re no doubt aware, as a new trainee, you''ll need to complete a few unpaid training tasks before you''re instated as a full-time employee.</p>\n<p>You should have already received a couple of electronic mails from our automated onboarding system that you can review:</p>\n<ul>\n<li>The SIC-1 Reference Manual, which includes details on <code>subleq</code> and SIC-1 Assembly Language</li>\n<li>A guide to the SIC-1 Development Environment (including usage information, keyboard shortcuts, etc.)</li>\n</ul>\n<p>You can view these mails at any time in the electronic mail viewer, which can be opened using the main menu (which is accessed using the \"Menu\" button in the lower-left, or by pressing \"Esc\").</p>\n<p>All information is, of course, confidential and covered by the nondisclosure agreement you signed as a condition of employment.</p>\n<p>Please let me know if you have any other questions.</p>\n<p>Thank you!</p>\n<p>-Mary</p>\n`}\n            values={{ selfName: context.self.name }}\n            />,\n        actions: [\n            \"manual\",\n            \"manualInNewWindow\"\n        ],\n    },\n\n    ],\n    [\n\n    {\n        id: \"s1_0\",\n        solvedCount: 1,\n        from: Contacts.badManager,\n        subject: <FormattedMessage\n            id=\"mails1_0Subject\"\n            description=\"Subject line for story mail s1_0\"\n            defaultMessage=\"Welcome to the team!\"\n            />,\n        create: (context) => <FormattedMessage\n            id=\"mails1_0Content\"\n            description=\"HTML content for story mail s1_0\"\n            defaultMessage={`<p>Hello, {selfName}!</p>\n<p>I''m your manager, Don, and I''m excited to have you join our team! We''re working very hard to ship our flagship product, the SIC-1, on time and we need all the help we can get.</p>\n<p>You''ve already met Mary from HR. The other members of your immediate team are Ted and Feng (note: their cubicles are unfortunately on the far end of this floor away from you--I''ll see if I can get you moved closer). In case you see any welcome mail from Rick, be aware that he is my boss (so your skip-level boss). If you have any concerns, I kindly ask you to raise them directly with me before looping in Rick.</p>\n<p>With introductions out of the way, let''s talk about your job description. You are to implement programs as they''re assigned to you. Your solutions will be compared to other employees'' solutions on the basis of execution time (measured in cycles) and memory usage (measured in bytes).</p>\n<p>Thanks in advance for your dedication!</p>\n<p>-Don</p>\n<p>P.S. Sorry if it was unclear that you would not be paid during training. There must have been a mix-up on HR''s end. I''ll see if there''s anything I can do to right the situation.</p>\n`}\n            values={{ selfName: context.self.name }}\n            />,\n    },\n\n    ],\n    [\n\n    {\n        id: \"s2_0\",\n        solvedCount: 2,\n        from: Contacts.badManager,\n        subject: <FormattedMessage\n            id=\"mails2_0Subject\"\n            description=\"Subject line for story mail s2_0\"\n            defaultMessage=\"Good news!\"\n            />,\n        create: (context) => <FormattedMessage\n            id=\"mails2_0Content\"\n            description=\"HTML content for story mail s2_0\"\n            defaultMessage={`<p>{selfName},</p>\n<p>After talking with Rick, we''ve decided that it''s not fair to make you complete training without compensating you. Hopefully your sitting down for this, because I''ve got some thrilling news.</p>\n<p><strong>We''re providing free pizza lunches to all trainees!</strong></p>\n<p>See? I told you I''d make it up to you.</p>\n<p>Thanks for working hard!</p>\n<p>-Don</p>\n`}\n            values={{ selfName: context.self.name }}\n            />,\n    },\n\n\n    {\n        id: \"s2_1\",\n        solvedCount: 2,\n        from: Contacts.flunky,\n        subject: <FormattedMessage\n            id=\"mails2_1Subject\"\n            description=\"Subject line for story mail s2_1\"\n            defaultMessage=\"Help!\"\n            />,\n        create: (context) => <FormattedMessage\n            id=\"mails2_1Content\"\n            description=\"HTML content for story mail s2_1\"\n            defaultMessage={`<p>Hi, {selfName}, I''m Ted. We met in the hallway earlier.</p>\n<p>Is there any chance you could come over to my cubicle and help me with the first assessment? I''d ask Feng for help, but I haven''t seen him around yet this morning.</p>\n<p>Yesterday, Feng mentioned something about just using a label that initially points to the value zero, but what does that even mean??? He also said something about being able to reset a variable back to zero by subtracting itself. Is that a thing? I''m so lost!</p>\n<p>Thanks for your time!</p>\n<p>-Ted</p>\n`}\n            values={{ selfName: context.self.name }}\n            />,\n    },\n\n    ],\n    [\n\n    {\n        id: \"s3_0\",\n        solvedCount: 3,\n        from: Contacts.hr,\n        subject: <FormattedMessage\n            id=\"mails3_0Subject\"\n            description=\"Subject line for story mail s3_0\"\n            defaultMessage=\"Training complete!\"\n            />,\n        create: (context) => <FormattedMessage\n            id=\"mails3_0Content\"\n            description=\"HTML content for story mail s3_0\"\n            defaultMessage={`<p>Thanks for completing your training, {selfName}! Your starting job title is: <strong>{jobTitle}</strong>.</p>\n<p>Your finalized compensation package is described in the packet I left on your desk. As always, let me know if you have any questions.</p>\n<p>Thank you!</p>\n<p>-Mary</p>\n`}\n            values={{ selfName: context.self.name, jobTitle: Shared.jobTitles[1].title }}\n            />,\n    },\n\n\n    {\n        id: \"s3_1\",\n        solvedCount: 3,\n        from: Contacts.mentor,\n        subject: <FormattedMessage\n            id=\"mails3_1Subject\"\n            description=\"Subject line for story mail s3_1\"\n            defaultMessage=\"My mental model for SIC-1\"\n            />,\n        create: (context) => <FormattedMessage\n            id=\"mails3_1Content\"\n            description=\"HTML content for story mail s3_1\"\n            defaultMessage={`<p>Greetings, {selfName}. I''m also on Don''s team and my name is Feng. Let me know if you ever need any assistance.</p>\n<p>After helping Ted with the first assessment, I thought I''d share my perspective on how to think about SIC-1 Assembly Language:</p>\n<ul>\n<li><strong>Addresses</strong> are just numbers that identify a specific byte of memory (0 for the first byte, 1 for the second, and so on, up to 255)</li>\n<li><strong>Labels</strong> are just names for addresses--specifically, the address of whatever comes next in your code (whether it''s a <code>subleq</code> or a <code>.data</code>)</li>\n<li><code>subleq</code> always compiles into 3 bytes (each one an address)--if you omit the third address, it just gets set to the address of the next instruction in memory</li>\n<li><code>.data</code> just sets one or more bytes of memory to specific values (positive or negative numbers, or even labels, i.e. addresses)</li>\n</ul>\n<p>In the end, everything compiles down to bytes in memory (which you can see in the memory table after you click \"Compile\" or \"Run\" to load the program). While running, the SIC-1 only sees those bytes in memory, and it doesn''t know or care how those bytes were produced (or even modified). It will happily interpret any 3 bytes as a <code>subleq</code> instruction--even if that''s not what you intended.</p>\n<p>It can be instructive to look at a chunk of code and see the resulting compiled bytes. Here''s an example:</p>\n<pre><code>@loop:\nsubleq @OUT, @IN           ; 3 byte instruction stored at address 0\nsubleq @zero, @zero, @loop ; 3 byte instruction stored at address 3\n\n@zero: .data 0             ; Initializes address 6 to zero\n</code></pre>\n<ul>\n<li><code>@loop</code> refers to address 0, i.e. the first instruction</li>\n<li>The first <code>subleq</code> occupies bytes 0, 1, and 2, and is compiled to: 254 (<code>@OUT</code>), 253 (<code>@IN</code>), 3 (the next instruction)</li>\n<li>The second <code>subleq</code> occupies bytes 3, 4, and 5, and is compiled to: 6 (<code>@zero</code>), 6 (<code>@zero</code>), 0 (<code>@loop</code>)</li>\n<li><code>@zero</code> refers to address 6, i.e. the next byte (which is initialized to zero using the <code>.data</code> directive)</li>\n</ul>\n<p>As you know by now, the first instruction negates an input and writes it out, then advances to the next instruction (regardless of the result). The second instruction subtracts the value at address 6 from itself, always resulting in zero, and thus always jumps to its third argument: <code>@loop</code>, i.e. address 0 (the beginning of the program).</p>\n<p>Hope that helps!</p>\n<p>-Feng</p>\n`}\n            values={{ selfName: context.self.name }}\n            />,\n    },\n\n    ],\n    [\n\n    {\n        id: \"s4_0\",\n        solvedCount: 4,\n        from: Contacts.badManager,\n        subject: <FormattedMessage\n            id=\"mails4_0Subject\"\n            description=\"Subject line for story mail s4_0\"\n            defaultMessage=\"Checking in\"\n            />,\n        create: (context) => <FormattedMessage\n            id=\"mails4_0Content\"\n            description=\"HTML content for story mail s4_0\"\n            defaultMessage={`<p>Hey, {selfName}! How''s it feel to be a full-time employee working on the cutting edge of revolutionary technology? Only a single instruction! Amazing!</p>\n<p>Anyway, I did see your question about the compensation package Mary provided to you. I apologize if the pay is lower than what you were expecting. Another HR mix-up! What can I say?</p>\n<p>I''ll talk to Rick to see if we can make an exception and raise your pay immediately, but just keep in mind that this company has a lot of room to grow, so your hard efforts will be very well rewarded!</p>\n<p>-Don</p>\n`}\n            values={{ selfName: context.self.name }}\n            />,\n    },\n\n\n    {\n        id: \"s4_1\",\n        solvedCount: 4,\n        from: Contacts.mentor,\n        subject: <FormattedMessage\n            id=\"mails4_1Subject\"\n            description=\"Subject line for story mail s4_1\"\n            defaultMessage=\"Sandbox Mode\"\n            />,\n        create: (context) => <FormattedMessage\n            id=\"mails4_1Content\"\n            description=\"HTML content for story mail s4_1\"\n            defaultMessage={`<p>Greetings, {selfName}.</p>\n<p>I wanted to share with you a little side project I''ve been working on. I''m calling it \"Sandbox Mode\". Basically, it''s a special SIC-1 Emulator mode that allows you to specify your own input.</p>\n<p>This is useful when you just want to play around with the SIC-1 to see how things work. You can experiment with this to test out new techniques without worrying about output getting flagged as incorrect.</p>\n<p>Sandbox Mode should be visible up in your Program Inventory under the \"Diversions\" group.</p>\n<p>Let me know what you think!</p>\n<p>-Feng</p>\n`}\n            values={{ selfName: context.self.name }}\n            />,\n        actions: [\n            \"sandbox\"\n        ],\n    },\n\n    ],\n    [\n\n    {\n        id: \"s5_0\",\n        solvedCount: 5,\n        from: Contacts.mentor,\n        subject: <FormattedMessage\n            id=\"mails5_0Subject\"\n            description=\"Subject line for story mail s5_0\"\n            defaultMessage=\"Constants\"\n            />,\n        create: (context) => <FormattedMessage\n            id=\"mails5_0Content\"\n            description=\"HTML content for story mail s5_0\"\n            defaultMessage={`<p>Greetings, {selfName}.</p>\n<p>After talking to Ted, I thought this might be a good time to remind everyone that you can use labels for both variables <em>and constants</em>. A label is really just an address, after all.</p>\n<p>For example, if I want to be able to write out a 1, I could create a constant. Just remember that if you''re subtracting the constant you''ll want to negate the constant:</p>\n<pre><code>subleq @OUT, @n_one ; Write out a 1 by subtracting -1 from @OUT\n                    ; Note: @OUT always reads as zero: 0 - (-1) = 1\n\n@n_one: .data -1    ; Constant\n</code></pre>\n<p>-Feng</p>\n`}\n            values={{ selfName: context.self.name }}\n            />,\n    },\n\n    ],\n    [\n\n    {\n        id: \"s6_0\",\n        solvedCount: 6,\n        from: Contacts.flunky1,\n        subject: <FormattedMessage\n            id=\"mails6_0Subject\"\n            description=\"Subject line for story mail s6_0\"\n            defaultMessage=\"Loops???\"\n            />,\n        create: (context) => <FormattedMessage\n            id=\"mails6_0Content\"\n            description=\"HTML content for story mail s6_0\"\n            defaultMessage={`<p>{selfName}, I''m really stuck! Do you have any time to come help me with the multiplication task?</p>\n<p>I already asked Feng for some help, but all he told me is that I could run a loop a specific number of times by subtracting 1 from a counter each time and then using the result to branch.</p>\n<p>What does that even mean???</p>\n<p>-Ted</p>\n`}\n            values={{ selfName: context.self.name }}\n            />,\n    },\n\n    ],\n    [\n\n    {\n        id: \"s7_0\",\n        solvedCount: 7,\n        from: Contacts.goodManager,\n        subject: <FormattedMessage\n            id=\"mails7_0Subject\"\n            description=\"Subject line for story mail s7_0\"\n            defaultMessage=\"Nice work!\"\n            />,\n        create: (context) => <FormattedMessage\n            id=\"mails7_0Content\"\n            description=\"HTML content for story mail s7_0\"\n            defaultMessage={`<p>Hi, {selfName}! I''m Pat and I''m another engineering lead (I actually work on the same team as your manager, Don).</p>\n<p>Feng (who used to report to me) mentioned that you''ve been making excellent progress!</p>\n<p>Anyway, I''ve been tasked with helping to improve morale across the team, so if there''s anything that you especially like or don''t like about the workplace or your compensation (or your team in general), feel free to send me a mail. I''ll make sure to keep all discussions private.</p>\n<p>Looking forward to hearing from you!</p>\n<p>-Pat</p>\n`}\n            values={{ selfName: context.self.name }}\n            />,\n    },\n\n\n    {\n        id: \"s7_1\",\n        solvedCount: 7,\n        from: Contacts.hr,\n        subject: <FormattedMessage\n            id=\"mails7_1Subject\"\n            description=\"Subject line for story mail s7_1\"\n            defaultMessage=\"Fun and games\"\n            />,\n        create: (context) => <FormattedMessage\n            id=\"mails7_1Content\"\n            description=\"HTML content for story mail s7_1\"\n            defaultMessage={`<p>Engineering team,</p>\n<p>To help improve morale, SIC Systems has provided an officially sanctioned computer video game called \"Avoision\" for employees to play. If you think your work would benefit from an entertaining diversion, please feel free to compete against your coworkers for the highest score in \"Avoision\" (during your two legally-mandated unpaid breaks, or in lieu of an unneeded bathroom break).</p>\n<p>You can find \"Avoision\" in the \"Diversions\" section of the program inventory and also in the main menu of the SIC-1 Development Environment.</p>\n<p>Enjoy!</p>\n<p>-Mary</p>\n`}\n            values={{ selfName: context.self.name }}\n            />,\n        to: [\n            \"all\"\n        ],\n        loadType: \"avoision\",\n        loadLabel: \"Play Avoision\",\n    },\n\n    ],\n    [\n\n    {\n        id: \"s8_0\",\n        solvedCount: 8,\n        from: Contacts.badManager,\n        subject: <FormattedMessage\n            id=\"mails8_0Subject\"\n            description=\"Subject line for story mail s8_0\"\n            defaultMessage=\"Great start!\"\n            />,\n        create: (context) => <FormattedMessage\n            id=\"mails8_0Content\"\n            description=\"HTML content for story mail s8_0\"\n            defaultMessage={`<p>Nice work on the arithmetic programs, {selfName}! As of this electronic mail, you have been promoted to <strong>{jobTitle}</strong>.</p>\n<p>I know it''s getting late (and please try to keep this to yourself), but our team really needs to improve our velocity. If there''s any way you can stay late and complete your next task <em>today</em>, there is a very good chance that I''ll be able to promote you to Senior Engineer (and that comes with a hefty pay bump).</p>\n<p>Again, keep this to yourself. This sort of rapid promotion is extremely rare. Obviously, I can''t guarantee anything, but if you can knuckle down and churn out this next task, things are looking pretty good...</p>\n<p>Thank you!</p>\n<p>-Don</p>\n`}\n            values={{ selfName: context.self.name, jobTitle: Shared.jobTitles[2].title }}\n            />,\n    },\n\n    ],\n    [\n\n    {\n        id: \"s9_0\",\n        solvedCount: 9,\n        from: Contacts.skip,\n        subject: <FormattedMessage\n            id=\"mails9_0Subject\"\n            description=\"Subject line for story mail s9_0\"\n            defaultMessage=\"Congratulations, Don!\"\n            />,\n        create: (context) => <FormattedMessage\n            id=\"mails9_0Content\"\n            description=\"HTML content for story mail s9_0\"\n            defaultMessage={`<p>Don (and Don''s team),</p>\n<p>In recognition of Don''s tireless efforts that have recently culminated in the ability of the SIC-1 to process sequences, I''d like everyone to join me in congratulating Don on his promotion to Principal Engineering Lead!</p>\n<p>Don, I don''t know how you managed to get sequences up and running so quickly, but we all owe a great debt to you.</p>\n<p>Thank you once again!</p>\n<p>-Rick</p>\n`}\n            values={{ selfName: context.self.name }}\n            />,\n        to: [\n            \"badManager2\",\n            \"badManagerTeam\"\n        ],\n    },\n\n    ],\n    [\n\n    {\n        id: \"s10_0\",\n        solvedCount: 10,\n        from: Contacts.goodManager,\n        subject: <FormattedMessage\n            id=\"mails10_0Subject\"\n            description=\"Subject line for story mail s10_0\"\n            defaultMessage=\"Rick's mail\"\n            />,\n        create: (context) => <FormattedMessage\n            id=\"mails10_0Content\"\n            description=\"HTML content for story mail s10_0\"\n            defaultMessage={`<p>{selfName},</p>\n<p>I just saw Rick''s mail about Don being promoted for his innovations in sequence processing.</p>\n<p>Could you drop by my cubicle to discuss a few things?</p>\n<p>I recall seeing you working late the night before this breakthrough, and I''d just like to understand your involvement there. If your work was used, you deserve credit for it.</p>\n<p>Regards,</p>\n<p>-Pat</p>\n`}\n            values={{ selfName: context.self.name }}\n            />,\n    },\n\n    ],\n    [\n\n    {\n        id: \"s11_0\",\n        solvedCount: 11,\n        from: Contacts.goodManager,\n        subject: <FormattedMessage\n            id=\"mails11_0Subject\"\n            description=\"Subject line for story mail s11_0\"\n            defaultMessage=\"Organizational change\"\n            />,\n        create: (context) => <FormattedMessage\n            id=\"mails11_0Content\"\n            description=\"HTML content for story mail s11_0\"\n            defaultMessage={`<p>{selfName},</p>\n<p>I know this is sudden and unexpected, but you''re going to be joining my team, effective today. Additionally, you have been promoted to <strong>{jobTitle}</strong>.</p>\n<p>I''m still not entirely clear what happened with Don and the new sequence processing work, but Rick mentioned that Don was considering letting you go, and I thought that seemed unfair. Fortunately, Rick was willing to give me a chance to add you to my team.</p>\n<p>Anyway, whatever happened, it''s in the past now and we need to focus on the road ahead.</p>\n<p>Thanks for your hard work!</p>\n<p>-Pat</p>\n`}\n            values={{ selfName: context.self.name, jobTitle: Shared.jobTitles[3].title }}\n            />,\n    },\n\n    ],\n    [\n\n    {\n        id: \"s12_0\",\n        solvedCount: 12,\n        from: Contacts.mentor,\n        subject: <FormattedMessage\n            id=\"mails12_0Subject\"\n            description=\"Subject line for story mail s12_0\"\n            defaultMessage=\"Debugging\"\n            />,\n        create: (context) => <FormattedMessage\n            id=\"mails12_0Content\"\n            description=\"HTML content for story mail s12_0\"\n            defaultMessage={`<p>Greetings, {selfName}.</p>\n<p>Self-modifying code can be tricky to understand at first. For the \"stack memory\" example, I found that it''s easiest to simply step through the program (using the \"Step\" button or \"Ctrl+.\") to see what it''s doing. Remember that you can click the circle next to a <code>subleq</code> instruction to toggle a breakpoint.</p>\n<p>Using this approach, you can see that the first bit of code is a loop that repeats as long as <code>@count</code> is greater than zero. Once the counter runs out, execution branches to the next chunk of code, and so on.</p>\n<p>You can also watch the stack grow in the \"Memory\" table in the upper right. In the example, the stack happens to start at address 32 (defined by <code>@stack_address</code>), which is the beginning of the third row of the table. Note that numbers are shown in hexadecimal and the \"two''s complement\" representation is used for negative numbers (meaning <code>80</code> in hex is -128 in decimal), so <code>ff</code> means -1, <code>fe</code> means -2, and so on.</p>\n<p>Hope that helps!</p>\n<p>-Feng</p>\n`}\n            values={{ selfName: context.self.name }}\n            />,\n    },\n\n    ],\n    [\n\n    {\n        id: \"s13_0\",\n        solvedCount: 13,\n        from: Contacts.flunky1,\n        subject: <FormattedMessage\n            id=\"mails13_0Subject\"\n            description=\"Subject line for story mail s13_0\"\n            defaultMessage=\"REVERSE SEQUENCE???\"\n            />,\n        create: (context) => <FormattedMessage\n            id=\"mails13_0Content\"\n            description=\"HTML content for story mail s13_0\"\n            defaultMessage={`<p>I''m completely lost! How can I reverse a sequence when I don''t even know its length??</p>\n<p>Feng pointed me to the stack memory example, but that example only reverses 3 numbers. What if the sequence has 4 letters? Or 5???</p>\n<p>This is starting to go way over my head... is there any chance I can copy your solution? I''ll make sure to have it be a little slower so that it''s not obvious I copied your work.</p>\n<p>HELP!!!</p>\n<p>-Ted</p>\n`}\n            values={{ selfName: context.self.name }}\n            />,\n    },\n\n    ],\n    [\n\n    {\n        id: \"s14_0\",\n        solvedCount: 14,\n        from: Contacts.goodManager,\n        subject: <FormattedMessage\n            id=\"mails14_0Subject\"\n            description=\"Subject line for story mail s14_0\"\n            defaultMessage=\"Excellent work!\"\n            />,\n        create: (context) => <FormattedMessage\n            id=\"mails14_0Content\"\n            description=\"HTML content for story mail s14_0\"\n            defaultMessage={`<p>You''re making great progress, {selfName}! These are some very difficult tasks and you''re breezing right through them!</p>\n<p>I''ll make sure that Rick knows you''re doing great work. I''m pushing hard for you to get promoted, because you really deserve it.</p>\n<p>Well done!</p>\n<p>-Pat</p>\n`}\n            values={{ selfName: context.self.name }}\n            />,\n    },\n\n    ],\n    [\n\n    {\n        id: \"s15_0\",\n        solvedCount: 15,\n        from: Contacts.goodManager,\n        subject: <FormattedMessage\n            id=\"mails15_0Subject\"\n            description=\"Subject line for story mail s15_0\"\n            defaultMessage=\"Wow!\"\n            />,\n        create: (context) => <FormattedMessage\n            id=\"mails15_0Content\"\n            description=\"HTML content for story mail s15_0\"\n            defaultMessage={`<p>Wow! Great job, {selfName}! It looks like you have a deep understanding of self-modifying code. That will be a valuable skill as we continue to push the boundaries of the SIC-1.</p>\n<p>It''s my honor to let you know that you''ve earned a very well-deserved promotion to <strong>{jobTitle}</strong>!</p>\n<p>Keep up the great work!</p>\n<p>-Pat</p>\n`}\n            values={{ selfName: context.self.name, jobTitle: Shared.jobTitles[4].title }}\n            />,\n    },\n\n    ],\n    [\n\n    {\n        id: \"s16_0\",\n        solvedCount: 16,\n        from: Contacts.badManager2,\n        subject: <FormattedMessage\n            id=\"mails16_0Subject\"\n            description=\"Subject line for story mail s16_0\"\n            defaultMessage=\"Very impressive!\"\n            />,\n        create: (context) => <FormattedMessage\n            id=\"mails16_0Content\"\n            description=\"HTML content for story mail s16_0\"\n            defaultMessage={`<p>Hi, {selfName}! It''s been a while since we last chatted.</p>\n<p>How do you like working on Pat''s team? It looks like you''re making excellent progress (between you and me, I think you''re doing most, if not all, of the work, though).</p>\n<p>Don''t share this with anyone, but I''ve been working with one of the other managers (Jerin Kransky) on setting up natural language processing functionality for the SIC-1.</p>\n<p>Do you have any interest in re-joining my team? I already have Jerin convinced that you''re the right person for the job, and I think another promotion would be in order if you''d be willing to come join us.</p>\n<p>Let me know what you think!</p>\n<p>-Don</p>\n`}\n            values={{ selfName: context.self.name }}\n            />,\n    },\n\n    ],\n    [\n\n    {\n        id: \"s17_0\",\n        solvedCount: 17,\n        from: Contacts.flunky1,\n        subject: <FormattedMessage\n            id=\"mails17_0Subject\"\n            description=\"Subject line for story mail s17_0\"\n            defaultMessage=\"Don\"\n            />,\n        create: (context) => <FormattedMessage\n            id=\"mails17_0Content\"\n            description=\"HTML content for story mail s17_0\"\n            defaultMessage={`<p>Hey, {selfName}.</p>\n<p>I was chatting with Don while we played our weekly round of golf this week, and he said that you were planning to come back to his team to work on some secret new project.</p>\n<p>It would be awesome to have you back on the team!</p>\n<p>-Ted</p>\n<p>P.S. Any chance you''d have time to walk me through your solution to the \"sort\" task? Thanks!</p>\n`}\n            values={{ selfName: context.self.name }}\n            />,\n    },\n\n    ],\n    [\n\n    {\n        id: \"s18_0\",\n        solvedCount: 18,\n        from: Contacts.goodManager,\n        subject: <FormattedMessage\n            id=\"mails18_0Subject\"\n            description=\"Subject line for story mail s18_0\"\n            defaultMessage=\"A promotion, and a new project!\"\n            />,\n        create: (context) => <FormattedMessage\n            id=\"mails18_0Content\"\n            description=\"HTML content for story mail s18_0\"\n            defaultMessage={`<p>Spectacular work, {selfName}! Based on your innovative solutions, you have been promoted to <strong>{jobTitle}</strong>.</p>\n<p>Please don''t mention this to anyone else, but I''ve heard rumors that Don (your old boss) and Jerin (another manager) are struggling to make progress on their natural language processing pipeline for the SIC-1.</p>\n<p>To be honest, I don''t think their team has any engineers of your caliber. I know it''s risky, but I''d like to put you to work on solving some of the natural language problems (under the radar, so to speak).</p>\n<p>If we can show definitive progress soon, then I think the board would be willing to move the whole project onto our team. That would be a big (and, frankly, unprecedented) promotion for you.</p>\n<p>Let me know if you have any concerns. And please don''t share this will anyone (especially Ted)!</p>\n<p>Thank you!</p>\n<p>-Pat</p>\n`}\n            values={{ selfName: context.self.name, jobTitle: Shared.jobTitles[5].title }}\n            />,\n    },\n\n    ],\n    [\n\n    {\n        id: \"s19_0\",\n        solvedCount: 19,\n        from: Contacts.badManager2,\n        subject: <FormattedMessage\n            id=\"mails19_0Subject\"\n            description=\"Subject line for story mail s19_0\"\n            defaultMessage=\"Do you have a minute?\"\n            />,\n        create: (context) => <FormattedMessage\n            id=\"mails19_0Content\"\n            description=\"HTML content for story mail s19_0\"\n            defaultMessage={`<p>{selfName}, do you have a few minutes to drop by my office?</p>\n<p>I''d like to know if you have put any thought into joining Jerin and I to work on that exciting new natural language processing project I mentioned to you a little while back. It could mean a big promotion for you!</p>\n<p>If you have any concerns, please, please let me know. It would be a shame to see your talents wasted on another team, to be honest. We''re really working on some revolutionary stuff here!</p>\n<p>I''ll stop by your cubicle in an hour or so, in case I don''t hear from you by then.</p>\n<p>Thanks!</p>\n<p>-Don</p>\n`}\n            values={{ selfName: context.self.name }}\n            />,\n    },\n\n    ],\n    [\n\n    {\n        id: \"s20_0\",\n        solvedCount: 20,\n        from: Contacts.flunky1,\n        subject: <FormattedMessage\n            id=\"mails20_0Subject\"\n            description=\"Subject line for story mail s20_0\"\n            defaultMessage=\"Dust off your resume\"\n            />,\n        create: (context) => <FormattedMessage\n            id=\"mails20_0Content\"\n            description=\"HTML content for story mail s20_0\"\n            defaultMessage={`<p>Hey, {selfName}.</p>\n<p>I don''t know if you''ve heard, but there are rumors that layoffs are coming. Now might be a good time to dust off your resume!</p>\n<p>Speaking of which, do you think you''d have a few minutes to drop by my cubicle and tell me what you think of my resume?</p>\n<p>Do you think it would be a stretch to say that I lead development of sequence processing for the SIC-1 (when I was really only just part of a larger team that worked on it)?</p>\n<p>Thanks, man!</p>\n<p>-Ted</p>\n`}\n            values={{ selfName: context.self.name }}\n            />,\n    },\n\n    ],\n    [\n\n    {\n        id: \"s21_0\",\n        solvedCount: 21,\n        from: Contacts.mentor,\n        subject: <FormattedMessage\n            id=\"mails21_0Subject\"\n            description=\"Subject line for story mail s21_0\"\n            defaultMessage=\"Farewell!\"\n            />,\n        create: (context) => <FormattedMessage\n            id=\"mails21_0Content\"\n            description=\"HTML content for story mail s21_0\"\n            defaultMessage={`<p>Greetings, {selfName}.</p>\n<p>I just wanted to let you know that today will be my last day at SIC Systems. I''ve enjoyed working with you, and I hope that my occasional clarifying electronic mails have been as beneficial to your career as working with you has been to mine.</p>\n<p>I generally try to distance myself from office politics and rumors, but I wanted to let you know that I have credible information that the SIC Systems board is currently trying to fend off a hostile takeover by Ilano Moscato (a foreign billionaire who is rather eccentric, to put it mildly).</p>\n<p>Based on what I''ve heard from friends who''ve worked at Ilano''s other companies, I''m expecting working conditions here to deteriorate rapidly. Ilano has a reputation for randomly pivoting strategies, overworking his employees, and even flouting certain laws.</p>\n<p>I urge you to consider looking for employment elsewhere.</p>\n<p>Best of luck to you, {selfName}!</p>\n<p>-Feng</p>\n`}\n            values={{ selfName: context.self.name }}\n            />,\n    },\n\n    ],\n    [\n\n    {\n        id: \"s22_0\",\n        solvedCount: 22,\n        from: Contacts.otherSkip,\n        subject: <FormattedMessage\n            id=\"mails22_0Subject\"\n            description=\"Subject line for story mail s22_0\"\n            defaultMessage=\"Natural language processing\"\n            />,\n        create: (context) => <FormattedMessage\n            id=\"mails22_0Content\"\n            description=\"HTML content for story mail s22_0\"\n            defaultMessage={`<p>Rick and Pat,</p>\n<p>It has come to my attention that Pat''s team has been discreetly working on natural language processing.</p>\n<p><strong>This absolutely must stop.</strong></p>\n<p>My team has been solely tasked (by the SIC Systems board) with designing and implementing the natural language processing pipeline for the SIC-1.</p>\n<p>Your work is redundant and, to be blunt, a misuse of corporate resources. We cannot have two teams working independently on the same problem.</p>\n<p>Pat, please turn over any documents you''ve created as a part of this duplicate effort immediately or I''ll be forced to refer your entire team to corporate affairs for disciplinary action.</p>\n<p>-Jerin</p>\n`}\n            values={{ selfName: context.self.name }}\n            />,\n        to: [\n            \"skip\",\n            \"goodManager\",\n            \"goodManagerTeam\"\n        ],\n    },\n\n\n    {\n        id: \"s22_1\",\n        solvedCount: 22,\n        from: Contacts.goodManager,\n        subject: <FormattedMessage\n            id=\"mails22_1Subject\"\n            description=\"Subject line for story mail s22_1\"\n            defaultMessage=\"Please ignore Jerin's mail\"\n            />,\n        create: (context) => <FormattedMessage\n            id=\"mails22_1Content\"\n            description=\"HTML content for story mail s22_1\"\n            defaultMessage={`<p>Hi, {selfName}.</p>\n<p>It''s unfortunate that Jerin sent that mail without consulting me or Rick first, but I want you to know that the work you''re doing is very important and we shouldn''t let office politics get in the way.</p>\n<p>You have made fantastic progress on natural language processing, and I''m confident that once the board sees our tremendous progress, Jerin will be forced to back down. This isn''t the first time an overzealous manager has come knocking on my door. Everything will be fine.</p>\n<p>Additionally, <strong>I have put together a proposal to create a new position for you, with a significant pay bump</strong>. If you can finish this next task, I''m sure the board will have no other option than to promote you to <em>Distinguished Engineer</em>.</p>\n<p>Thanks for all the hard work you''ve put in so far!</p>\n<p>-Pat</p>\n`}\n            values={{ selfName: context.self.name }}\n            />,\n    },\n\n    ],\n    [\n\n    {\n        id: \"s23_0\",\n        solvedCount: 23,\n        from: Contacts.otherSkip,\n        subject: <FormattedMessage\n            id=\"mails23_0Subject\"\n            description=\"Subject line for story mail s23_0\"\n            defaultMessage=\"Welcome aboard!\"\n            />,\n        create: (context) => <FormattedMessage\n            id=\"mails23_0Content\"\n            description=\"HTML content for story mail s23_0\"\n            defaultMessage={`<p>Hi, {selfName}. In case we haven''t met yet, I''m Jerin, a peer to your old skip-level manager Rick. I''d like to congratulate you on the work you''ve done so far. What I''ve seen has been most impressive!</p>\n<p>Effective immediately, you''ll be reporting directly to me to continue your exciting work on natural language processing.</p>\n<p>Additionally, I''d like to inform you that you''ve been promoted to <strong>{jobTitle}</strong> (although, due to budget cuts, we won''t be able to honor the original compensation package that was discussed).</p>\n<p>Looking forward to working with you!</p>\n<p>-Jerin</p>\n<p>P.S. Pat is no longer employed by SIC Systems.</p>\n`}\n            values={{ selfName: context.self.name, jobTitle: Shared.jobTitles[6].title }}\n            />,\n    },\n\n    ],\n    [\n\n    {\n        id: \"s24_0\",\n        solvedCount: 24,\n        from: Contacts.hr,\n        subject: <FormattedMessage\n            id=\"mails24_0Subject\"\n            description=\"Subject line for story mail s24_0\"\n            defaultMessage=\"SIC Systems acquisition\"\n            />,\n        create: (context) => <FormattedMessage\n            id=\"mails24_0Content\"\n            description=\"HTML content for story mail s24_0\"\n            defaultMessage={`<p>Engineering team,</p>\n<p>As reported in the news, SIC Systems has agreed to be acquired by Ilano Moscato (majority owner and CEO of Edison, Herbaleaf, and Neutralino).</p>\n<p>What this means for you:</p>\n<ul>\n<li>Your day-to-day duties remain the same</li>\n<li>No major changes to the organization are planned</li>\n<li>Ilano has indicated that he will honor all existing approved compensation packages (both cash and equity)</li>\n</ul>\n<p>In other words: \"business as usual\".</p>\n<p>Please don''t let reports in the media distract you from your work.</p>\n<p>Let me know if you have any questions. Thank you!</p>\n<p>-Mary</p>\n`}\n            values={{ selfName: context.self.name }}\n            />,\n        to: [\n            \"all\"\n        ],\n    },\n\n\n    {\n        id: \"s24_1\",\n        solvedCount: 24,\n        from: Contacts.otherSkip,\n        subject: <FormattedMessage\n            id=\"mails24_1Subject\"\n            description=\"Subject line for story mail s24_1\"\n            defaultMessage=\"New owner\"\n            />,\n        create: (context) => <FormattedMessage\n            id=\"mails24_1Content\"\n            description=\"HTML content for story mail s24_1\"\n            defaultMessage={`<p>{selfName},</p>\n<p>I just wanted to let you know that I met with our new owner, Ilano, earlier today, and he''s very excited about the work you''re doing.</p>\n<p>If there''s anything you might need to grind through the last couple of tricky problems, please let me know.</p>\n<p>-Jerin</p>\n`}\n            values={{ selfName: context.self.name }}\n            />,\n    },\n\n    ],\n    [\n\n    {\n        id: \"s25_0\",\n        solvedCount: 25,\n        from: Contacts.otherSkip,\n        subject: <FormattedMessage\n            id=\"mails25_0Subject\"\n            description=\"Subject line for story mail s25_0\"\n            defaultMessage=\"Right-sizing our team\"\n            />,\n        create: (context) => <FormattedMessage\n            id=\"mails25_0Content\"\n            description=\"HTML content for story mail s25_0\"\n            defaultMessage={`<p>{selfName},</p>\n<p>I wanted to let you know that Rick, Don, and Ted have all been let go.</p>\n<p>On the surface, it might sound like this means that all the remaining natural language work now falls on your plate. But there''s a silver lining: I''ve been given the go-ahead to offer you some non-cash perks to help you manage your schedule, namely:</p>\n<ul>\n<li>Free breakfast, lunch and dinner at the office</li>\n<li>On-site laundry service</li>\n<li>An optional home cleaning/maintenance service, if you need it</li>\n</ul>\n<p>Thanks for pushing so hard these last few weeks and months!</p>\n<p>-Jerin</p>\n`}\n            values={{ selfName: context.self.name }}\n            />,\n    },\n\n    ],\n    [\n\n    {\n        id: \"s26_0\",\n        solvedCount: 26,\n        from: Contacts.owner,\n        subject: <FormattedMessage\n            id=\"mails26_0Subject\"\n            description=\"Subject line for story mail s26_0\"\n            defaultMessage=\"A new focus\"\n            />,\n        create: (context) => <FormattedMessage\n            id=\"mails26_0Content\"\n            description=\"HTML content for story mail s26_0\"\n            defaultMessage={`<p>Jerin and {selfName},</p>\n<p>Thanks for welcoming me. I''m excited to work with you!</p>\n<p>Your team''s work on natural language processing is near and dear to my heart. As you may have heard, I founded Neutralino a few years back, with a goal of allowing a machine to reason about itself.</p>\n<p>I''d like to task you with a special project to bring a similar capability to the SIC-1, ideally by the end of this quarter. I''ve been shopping around this capability to various governments around the world, and already have \"hand shake\" agreements for a few multi-billion dollar orders.</p>\n<p>To say that this work is important would be an understatement. It is revolutionary!</p>\n<p>Regards,</p>\n<p>-Ilano</p>\n`}\n            values={{ selfName: context.self.name }}\n            />,\n        to: [\n            \"otherSkip\",\n            \"self\"\n        ],\n    },\n\n\n    {\n        id: \"s26_1\",\n        solvedCount: 26,\n        from: Contacts.otherSkip,\n        subject: <FormattedMessage\n            id=\"mails26_1Subject\"\n            description=\"Subject line for story mail s26_1\"\n            defaultMessage=\"New focus, new title, new perks\"\n            />,\n        create: (context) => <FormattedMessage\n            id=\"mails26_1Content\"\n            description=\"HTML content for story mail s26_1\"\n            defaultMessage={`<p>{selfName},</p>\n<p>I''m sure you saw the mail from Ilano. He thinks highly of us, but he also expects a lot.</p>\n<p>To properly motivate you, Ilano has created a new job title exclusively for you: <strong>{jobTitle}</strong>.</p>\n<p>You''ve shown tenacity to get this far, and you''ll need loads of it for the next batch of tasks. We need to give the SIC-1 the ability to understand its own code, in order to unleash its immense computing power on optimizing its own performance. In addition to existing perks, we''ll be happy to provide:</p>\n<ul>\n<li>Free super-vitamins (used by Ilano himself), produced by Herbaleaf</li>\n<li>Optional sleeping quarters at the office</li>\n<li>Discounted fertility preservation services</li>\n</ul>\n<p>We just need you to push through this one last sprint to the finish line. Your fellow SIC Systems family members thank you for your perseverance!</p>\n<p>-Jerin</p>\n`}\n            values={{ selfName: context.self.name, jobTitle: Shared.jobTitles[7].title }}\n            />,\n    },\n\n    ],\n    [\n\n    {\n        id: \"s27_0\",\n        solvedCount: 27,\n        from: Contacts.otherSkip,\n        subject: <FormattedMessage\n            id=\"mails27_0Subject\"\n            description=\"Subject line for story mail s27_0\"\n            defaultMessage=\"Compensation\"\n            />,\n        create: (context) => <FormattedMessage\n            id=\"mails27_0Content\"\n            description=\"HTML content for story mail s27_0\"\n            defaultMessage={`<p>{selfName},</p>\n<p>I know we had discussed increasing your compensation, given the increased scope and impact of your work.</p>\n<p>Unfortunately, Ilano has put a freeze on all new spending, so there''s nothing I can do. My hands are tied.</p>\n<p>Having said that, I''m sure that once your work is complete and Ilano sees what you''ve been able to accomplish, he''ll make sure you''re duly compensated. He might even want to shift you over to one of his other companies where technical know-how is needed.</p>\n<p>Just keep your focus on the task at hand!</p>\n<p>-Jerin</p>\n`}\n            values={{ selfName: context.self.name }}\n            />,\n    },\n\n\n    {\n        id: \"s27_1\",\n        solvedCount: 27,\n        from: Contacts.hr,\n        subject: <FormattedMessage\n            id=\"mails27_1Subject\"\n            description=\"Subject line for story mail s27_1\"\n            defaultMessage=\"Ilano meet & greet\"\n            />,\n        create: (context) => <FormattedMessage\n            id=\"mails27_1Content\"\n            description=\"HTML content for story mail s27_1\"\n            defaultMessage={`<p>Engineering team,</p>\n<p>Unfortunately, due to a scheduling conflict with an executive retreat, Ilano is not available for the previously planned meet & greet today.</p>\n<p>We will reschedule for next week, at which point you can submit questions for him to answer.</p>\n<p>Sorry for the late notice!</p>\n<p>-Mary</p>\n`}\n            values={{ selfName: context.self.name }}\n            />,\n        to: [\n            \"all\"\n        ],\n    },\n\n    ],\n    [\n\n    {\n        id: \"s28_0\",\n        solvedCount: 28,\n        from: Contacts.owner,\n        subject: <FormattedMessage\n            id=\"mails28_0Subject\"\n            description=\"Subject line for story mail s28_0\"\n            defaultMessage=\"UNACCEPTABLE!\"\n            />,\n        create: (context) => <FormattedMessage\n            id=\"mails28_0Content\"\n            description=\"HTML content for story mail s28_0\"\n            defaultMessage={`<p>Mary,</p>\n<p>The food at the executive retreat was absolutely horrible. I don''t know how these events worked before, but I always treat my executives to the finest culinary delights the world has to offer.</p>\n<p>The caviar was almost inedible (definitely <em>not</em> the Caspian Sea beluga caviar I had specifically requested), and the cocktail weenies were similarly unpalatable (anything less than Boar''s Pride should go in the dumpster).</p>\n<p>What a disgrace!</p>\n<p>-Ilano</p>\n<p>P.S. Please reject all meeting requests with staff for the rest of the week. And please come up with convincing excuses this time!</p>\n`}\n            values={{ selfName: context.self.name }}\n            />,\n        to: [\n            \"all\"\n        ],\n    },\n\n    ],\n    [\n\n    {\n        id: \"s29_0\",\n        solvedCount: 29,\n        from: Contacts.assistant,\n        subject: <FormattedMessage\n            id=\"mails29_0Subject\"\n            description=\"Subject line for story mail s29_0\"\n            defaultMessage=\"Clarification\"\n            />,\n        create: (context) => <FormattedMessage\n            id=\"mails29_0Content\"\n            description=\"HTML content for story mail s29_0\"\n            defaultMessage={`<p>Engineering team,</p>\n<p>Please disregard the previous errant electronic mail that was purportedly sent by Ilano. That mail was apparently actually sent by a rogue human resources employee, Mary Townsend (who has since been fired).</p>\n<p>Ilano treats all employees with dignity and respect, and would never complain about a matter so trivial as food catering at a meeting. He understands that budget cuts are difficult and, in fact, he has willingly slashed his own salary by 10% in solidarity with all SIC Systems staff.</p>\n<p>Thank you, and have a great day!</p>\n<p>-Jeffrey</p>\n`}\n            values={{ selfName: context.self.name }}\n            />,\n        to: [\n            \"all\"\n        ],\n    },\n\n    ],\n    [\n\n    {\n        id: \"s30_0\",\n        solvedCount: 30,\n        from: Contacts.owner,\n        subject: <FormattedMessage\n            id=\"mails30_0Subject\"\n            description=\"Subject line for story mail s30_0\"\n            defaultMessage=\"Unbelievable work!\"\n            />,\n        create: (context) => <FormattedMessage\n            id=\"mails30_0Content\"\n            description=\"HTML content for story mail s30_0\"\n            defaultMessage={`<p>Truly amazing work, {selfName}!</p>\n<p>Thank you from the bottom of my heart for all of the sacrifices you''ve made to get us to this point. The SIC-1 is now able to reason about its own code. This is an amazing breakthrough and you should be very proud.</p>\n<p>Now that we''ve reached this exciting milestone (thanks to your tireless efforts!), SIC Systems honestly can''t challenge someone with your peerless talent. Excitingly, you can now begin the next phase of your career at one of the many other technology companies around the world. I know parting ways is tough, but SIC Systems is a business, not a family, so we have to say goodbye to employees once they''re no longer needed. Thank you one last time, and best of luck in your future endeavors!</p>\n<p>-Ilano</p>\n`}\n            values={{ selfName: context.self.name }}\n            />,\n    },\n\n    ],\n    [\n\n    {\n        id: \"s31_0\",\n        solvedCount: 31,\n        from: Contacts.goodManager2,\n        subject: <FormattedMessage\n            id=\"mails31_0Subject\"\n            description=\"Subject line for story mail s31_0\"\n            defaultMessage=\"Great to hear from you!\"\n            />,\n        create: (context) => <FormattedMessage\n            id=\"mails31_0Content\"\n            description=\"HTML content for story mail s31_0\"\n            defaultMessage={`<p>{selfName},</p>\n<p>It''s great to hear from you!</p>\n<p>I heard that SIC Systems let you go immediately after you demoed your (incomplete) self-hosting program. Ilano is going to be kicking himself when he realizes that the implementation SIC Systems owns doesn''t support self-modifying code!</p>\n<p>Now that you''re solely in possession of the only <em>truly</em> self-hosting program for the SIC-1, my advice is: destroy it. Erase all copies, set them on fire, and bury the ashes out in the desert. Ilano doesn''t deserve to ever take advantage of your work again.</p>\n<p>Speaking of work, I wanted to let you know that I found a job at a small startup that is working on a home computer with a graphical interface. It''s revolutionary stuff, and we need someone with your technical skills to go to market.</p>\n<p>Is there any chance you''d be open to discussing a lead engineering position over here?</p>\n<p>If you''re interested, let me know and I''ll schedule a meeting with us and the two remaining founders (both named Steve, by coincidence).</p>\n<p>Hope to hear from you soon!</p>\n<p>-Pat</p>\n`}\n            values={{ selfName: context.self.name }}\n            />,\n        actions: [\n            \"credits\"\n        ],\n    },\n\n    ],\n] as const;\n", "sic1/client/ts/steam-api.ts": "import { TaskManager, TaskManagerJson, TaskManagerOptions } from \"crs_queue\";\nimport { wrapNativePromise } from \"./native-promise-wrapper\";\n\ninterface LeaderboardQueueUpdate {\n    id: string;\n    retryCount: number;\n    score: number;\n    details?: number[];\n}\n\nexport interface FriendLeaderboardEntry {\n    name: string;\n    score: number;\n}\n\ninterface SteamApiJson {\n    leaderboardQueue: TaskManagerJson<LeaderboardQueueUpdate>;\n}\n\nexport class SteamApi {\n    private static readonly leaderboardQueueRate = {\n        count: 10,\n        periodMS: 1000 * 60 * 10,\n    };\n\n    private static readonly leaderboardQueueRetryIntervalsMS = [\n        60 * 1000,\n        60 * 60 * 1000,\n        24 * 60 * 60 * 1000,\n        7 * 24 * 60 * 60 * 1000,\n    ];\n\n    private steam = chrome.webview.hostObjects.sync.steam;\n    private leaderboardNameToHandle: { [name: string]: number } = {};\n    private leaderboardQueue: TaskManager<LeaderboardQueueUpdate, void>;\n    private onPersistRequested: () => void;\n\n    constructor(onPersistRequested: () => void, serializedJson: string | null) {\n        this.onPersistRequested = onPersistRequested;\n\n        const leaderboardQueueOptions: TaskManagerOptions<LeaderboardQueueUpdate, void> = {\n            rateLimit: SteamApi.leaderboardQueueRate,\n            onRunTask: task => this.runLeaderboardTaskAsync(task),\n            onTaskFailure: task => this.handleLeaderboardTaskFailure(task),\n        };\n\n        try {\n            if (serializedJson) {\n                const deserialized = JSON.parse(serializedJson) as SteamApiJson;\n                this.leaderboardQueue = TaskManager.fromParsedJson<LeaderboardQueueUpdate, void>(deserialized.leaderboardQueue, leaderboardQueueOptions);\n            }\n        } catch {\n            // Will create the task manager below on error\n        }\n\n        if (!this.leaderboardQueue) {\n            this.leaderboardQueue = new TaskManager<LeaderboardQueueUpdate, void>(leaderboardQueueOptions);\n        }\n    }\n\n    private async runLeaderboardTaskAsync(task: LeaderboardQueueUpdate): Promise<void> {\n        const leaderboard = await this.getLeaderboardHandleAsync(task.id);\n        await wrapNativePromise(this.steam.ResolveSetLeaderboardEntry, leaderboard, task.score, task.details);\n        this.onPersistRequested();\n    }\n\n    private handleLeaderboardTaskFailure(task: LeaderboardQueueUpdate): void {\n        // Retry task (with delay)\n        this.leaderboardQueue.run(\n            { ...task, retryCount: task.retryCount + 1},\n            new Date(Date.now() + SteamApi.leaderboardQueueRetryIntervalsMS[Math.min(SteamApi.leaderboardQueueRetryIntervalsMS.length - 1, task.retryCount)]),\n        );\n\n        this.onPersistRequested();\n    }\n\n    private async getLeaderboardHandleAsync(leaderboardName: string): Promise<number> {\n        let handle = this.leaderboardNameToHandle[leaderboardName];\n        if (typeof(handle) !== \"number\") {\n            handle = await wrapNativePromise(this.steam.ResolveGetLeaderboard, leaderboardName);\n            this.leaderboardNameToHandle[leaderboardName] = handle;\n        }\n        return handle;\n    }\n\n    public serialize(): string {\n        return JSON.stringify({\n            leaderboardQueue: this.leaderboardQueue.toParsedJson(),\n        });\n    }\n\n    public updateLeaderboardEntryAsync(leaderboardName: string, score: number, details?: number[]): Promise<void> | null {\n        const result = this.leaderboardQueue.run({\n            id: leaderboardName,\n            score,\n            details,\n            retryCount: 0,\n        });\n\n        \n        this.onPersistRequested();\n        return result;\n    }\n\n    public async getFriendLeaderboardAsync(leaderboardName: string): Promise<FriendLeaderboardEntry[]> {\n        const leaderboard = await this.getLeaderboardHandleAsync(leaderboardName);\n        const flatArray = await wrapNativePromise(this.steam.ResolveGetFriendLeaderboardEntries, leaderboard);\n        const result: FriendLeaderboardEntry[] = [];\n        for (let i = 0; i < flatArray.length; i += 2) {\n            result.push({ name: (flatArray[i] as string), score: (flatArray[i + 1] as number) });\n        }\n        return result;\n    }\n}\n", "sic1/client/ts/native-promise-wrapper.ts": "export type NativePromiseExecutor<TResult, TArguments extends any[]> = (\n        resolve: (result?: TResult) => void,\n        reject: (status: number) => void, ...args: TArguments\n    ) => void;\n\nexport function wrapNativePromise<TResult, TArguments extends any[]>(nativeFunction: NativePromiseExecutor<TResult, TArguments>, ...args: TArguments): Promise<TResult> {\n    return new Promise<TResult>((resolve, reject) => nativeFunction(resolve, reject, ...args));\n}\n", "sic1/client/ts/setup.ts": "export type PlatformName = \"steam\" | \"web\";\nexport type RuntimeName = \"browser\" | \"electron\" | \"webview2\";\nexport const debug = false;\nexport const suppressUpload = true;\nexport const platform: PlatformName = \"web\";\nexport const runtime: RuntimeName = \"browser\";\n", "sic1/client/ts/ide-gutter.tsx": "import React from \"react\";\nimport { Shared } from \"./shared\";\n\nexport interface GutterProperties {\n    hasStarted: boolean;\n    sourceLines: string[];\n    currentSourceLine: number;\n    sourceLineToBreakpointState: { [lineNumber: number]: boolean | undefined };\n    onToggleBreakpoint: (lineNumber: number) => void;\n}\n\nexport class Gutter extends React.Component<GutterProperties> {\n    private currentSourceLineElement = React.createRef<HTMLSpanElement>();\n\n    constructor(props) {\n        super(props);\n        this.state = { focused: false };\n    }\n\n    public scrollCurrentSourceLineIntoView(): void {\n        Shared.scrollElementIntoView(this.currentSourceLineElement.current);\n    }\n\n    public render(): React.ReactNode {\n        return <div className=\"gutter\">\n            {this.props.hasStarted\n                ? (this.props.sourceLines.map((s, index) =>\n                    <React.Fragment key={index}>\n                        {(this.props.sourceLineToBreakpointState[index] !== undefined)\n                            ?\n                                <span\n                                    ref={(index === this.props.currentSourceLine) ? this.currentSourceLineElement : undefined}\n                                    className={`breakpoint${this.props.sourceLineToBreakpointState[index] ? \"\" : \" off\"}`}\n                                    tabIndex={0}\n                                    onMouseDown={(event) => {\n                                        this.props.onToggleBreakpoint(index);\n\n                                        // Don't focus if we're just toggling the breakpoint (the outline is ugly)\n                                        event.preventDefault();\n                                    }}\n                                    onKeyDown={(event) => {\n                                        if (!event.ctrlKey && !event.metaKey && event.key === \"Enter\") {\n                                            this.props.onToggleBreakpoint(index);\n                                            event.preventDefault();\n                                            event.stopPropagation();\n                                        }\n                                    }}\n                                >●</span>\n                            : <>&nbsp;</>\n                        }\n                        <br/>\n                    </React.Fragment>))\n                : <>&nbsp;</>}\n        </div>;\n    }\n}", "sic1/client/ts/solution-manager.tsx": "import React from \"react\";\nimport { Button } from \"./button\";\nimport { PuzzleSolution, Sic1DataManager } from \"./data-manager\";\nimport { MessageBoxContent, MessageBoxBehavior } from \"./message-box\";\nimport { Shared } from \"./shared\";\nimport { FormattedMessage, IntlShape } from \"react-intl\";\nimport { LocalizedResources } from \"./resources\";\n\ninterface InputSpanProperties {\n    initialValue: string;\n    onApply: (value: string) => void;\n    onCancel: () => void;\n}\n\nclass InputSpan extends React.Component<InputSpanProperties> {\n    private span = React.createRef<HTMLSpanElement>();\n\n    private cancel(): void {\n        this.props.onCancel();\n    }\n\n    public componentDidMount(): void {\n        const span = this.span.current;\n        if (span) {\n            span.focus();\n            window.getSelection().selectAllChildren(span);\n        }\n    }\n\n    public render() {\n        return <span\n            className=\"editable\"\n            ref={this.span}\n            contentEditable={true}\n            onKeyDown={(event) => {\n                switch (event.key) {\n                    case \"Enter\":\n                        const value = this.span.current?.innerText;\n                        if (value) {\n                            this.props.onApply(value);\n                        } else {\n                            this.cancel();\n                        }\n                        event.preventDefault();\n                        event.stopPropagation();\n                        break;\n                    \n                    case \"Escape\":\n                        this.cancel();\n                        event.preventDefault();\n                        event.stopPropagation();\n                        break;\n                }\n            }}\n            onBlur={() => {\n                this.cancel();\n            }}\n            >\n            {this.props.initialValue}\n        </span>;\n    }\n}\n\nexport interface SolutionManagerProperties {\n    intl: IntlShape;\n    puzzleTitle: string;\n    solutionName?: string;\n    onSelectionChanged: (solutionName?: string) => void;\n    onOpen: (solutionName: string) => void;\n    onShowMessageBox: (content: MessageBoxContent) => void;\n    onCloseMessageBox: () => void;\n}\n\ninterface SolutionManagerState {\n    solutions: PuzzleSolution[];\n    renaming: boolean;\n}\n\nfunction createUniqueSolutionName(intl: IntlShape, name: string, state: SolutionManagerState): string {\n    return Shared.createUniqueName(intl, name, state.solutions.map(s => s.name));\n}\n\nexport class SolutionManager extends React.Component<SolutionManagerProperties, SolutionManagerState> {\n    private static readonly solutionNameMaxLength = 40;\n    private static readonly solutionNameReasonableLength = 30; // For copied names\n\n    private selectedItem = React.createRef<HTMLDivElement>();\n\n    constructor(props) {\n        super(props);\n\n        const puzzleData = Sic1DataManager.getPuzzleData(this.props.puzzleTitle);\n        this.state = {\n            solutions: puzzleData.solutions ?? [],\n            renaming: false,\n        };\n    }\n\n    private persistIfNeeded(solutions: PuzzleSolution[]): void {\n        const puzzleTitle = this.props.puzzleTitle;\n        const puzzleData = Sic1DataManager.getPuzzleData(puzzleTitle);\n        const stateString = JSON.stringify(solutions);\n        if (JSON.stringify(puzzleData.solutions) !== stateString) {\n            // Clone the object\n            puzzleData.solutions = JSON.parse(stateString);\n            Sic1DataManager.savePuzzleData(puzzleTitle);\n        }\n    }\n\n    private onClick(solutionName: string): void {\n        this.props.onSelectionChanged(solutionName);\n    }\n\n    private newSolution(): void {\n        this.setState(state => {\n            const name = createUniqueSolutionName(this.props.intl, LocalizedResources.defaultSolutionName.getValue(), state);\n            const newState = {\n                solutions: [\n                    ...state.solutions,\n                    { name },\n                ],\n                renaming: false,\n            };\n\n            this.persistIfNeeded(newState.solutions);\n            this.props.onSelectionChanged(name);\n\n            return newState;\n        });\n    }\n\n    private copySolution(): void {\n        this.setState(state => {\n            const index = state.solutions.findIndex(s => s.name === this.props.solutionName);\n            if (index >= 0) {\n                const solution = state.solutions[index];\n                let baseName = this.props.intl.formatMessage(                {\n                    id: \"templateSolutionCopy\",\n                    description: \"Text template for new names when copying an existing solution\",\n                    defaultMessage: \"Copy of {name}\",\n                },\n                {\n                    name: solution.name,\n                });\n\n                if (baseName.length > SolutionManager.solutionNameReasonableLength) {\n                    // Truncate, but base off original\n                    baseName = solution.name.substring(0, SolutionManager.solutionNameReasonableLength);\n                }\n\n                const name = createUniqueSolutionName(this.props.intl, baseName, state);\n                const newState = {\n                    solutions: [\n                        ...state.solutions.slice(0, index + 1),\n                        {\n                            ...solution,\n                            name,\n                        },\n                        ...state.solutions.slice(index + 1),\n                    ],\n                    renaming: false,\n                };\n\n                this.persistIfNeeded(newState.solutions);\n                this.props.onSelectionChanged(name);\n\n                return newState;\n            }\n            return state;\n        });\n    }\n\n    private isSolutionNameValid(name: string): boolean {\n        return name && (name.indexOf(\"\\n\") === -1) && (name.length <= SolutionManager.solutionNameMaxLength);\n    }\n\n    private renameSolution(nameRaw: string): void {\n        this.setState(state => {\n            // Check for name change\n            const name = nameRaw.trim();\n            if (name !== this.props.solutionName) {\n                // Check validity\n                if (this.isSolutionNameValid(name)) {\n                    // Check uniqueness\n                    if (state.solutions.findIndex(s => s.name === name) === -1) {\n                        const index = state.solutions.findIndex(s => s.name === this.props.solutionName);\n                        if (index >= 0) {\n                            const solution = state.solutions[index];\n                            const newState = {\n                                solutions: [...state.solutions.slice(0, index), { ...solution, name }, ...state.solutions.slice(index + 1)],\n                                renaming: false,\n                            };\n        \n                            this.persistIfNeeded(newState.solutions);\n                            this.props.onSelectionChanged(name);\n        \n                            return newState;\n                        }\n                    } else {\n                        this.props.onShowMessageBox({\n                            title: this.props.intl.formatMessage({\n                                id: \"windowTitleNameExists\",\n                                description: \"Title of 'name already exists' error message box\",\n                                defaultMessage: \"Name Already Exists\",\n                            }),\n                            transparent: true,\n                            body: <p>\n                                    <FormattedMessage\n                                        id=\"errorNameExists\"\n                                        description=\"Error message for 'name already exists' error\"\n                                        defaultMessage={\"A solution named \\\"{name}\\\" already exists.\"}\n                                        values={{ name }}\n                                        />\n                                </p>,\n                        });\n                    }\n                } else {\n                    this.props.onShowMessageBox({\n                        title: this.props.intl.formatMessage({\n                            id: \"windowTitleNameInvalid\",\n                            description: \"Title of 'invalid name' error message box\",\n                            defaultMessage: \"Invalid Name\",\n                        }),\n                        transparent: true,\n                        body:\n                            <p>\n                                <FormattedMessage\n                                    id=\"errorNameInvalid\"\n                                    description=\"Error message for 'invalid name' error\"\n                                    defaultMessage=\"Solution names must be at most {maxLength} characters long, and only a single line.\"\n                                    values={{ maxLength: SolutionManager.solutionNameMaxLength }}\n                                    />\n                            </p>,\n                    });\n                }\n            }\n\n            return { renaming: false };\n        });\n    }\n\n    private deleteSolution(): void {\n        this.setState(state => {\n            const index = state.solutions.findIndex(s => s.name === this.props.solutionName);\n            if (index >= 0) {\n                const solutions = state.solutions.filter(s => s.name !== this.props.solutionName);\n                this.persistIfNeeded(solutions);\n                this.props.onSelectionChanged(solutions[Math.min(index, solutions.length - 1)]?.name);\n\n                return {\n                    solutions,\n                    renaming: false,\n                };\n            }\n\n            return state;\n        });\n    }\n\n    private moveSolution(offset: number): void {\n        this.setState(state => {\n            const index = state.solutions.findIndex(s => s.name === this.props.solutionName);\n            const newIndex = index + offset;\n            if ((index >= 0) && (newIndex >= 0) && (newIndex < this.state.solutions.length)) {\n                const solutions = state.solutions.slice();\n                const solution = solutions.splice(index, 1)[0];\n                solutions.splice(newIndex, 0, solution);\n\n                this.persistIfNeeded(solutions);\n\n                return {\n                    solutions,\n                    renaming: false,\n                };\n            }\n\n            return state;\n        });\n    }\n\n    private showDeleteConfirmation(): void {\n        this.props.onShowMessageBox({\n            title: this.props.intl.formatMessage({\n                id: \"windowTitleConfirmDelete\",\n                description: \"Title of 'confirm deletion' message box\",\n                defaultMessage: \"Confirm Deletion\",\n            }),\n            transparent: true,\n            behavior: MessageBoxBehavior.keyboardNavigationForButtons,\n            body: <>\n                <p>\n                    <FormattedMessage\n                        id=\"textConfirmDelete\"\n                        description=\"Text asking if the item should be deleted\"\n                        defaultMessage={\"Delete \\\"{itemName}\\\"?\"}\n                        values={{ itemName: this.props.solutionName }}\n                        />\n                </p>\n                <Button onClick={() => {\n                    this.deleteSolution();\n                    this.props.onCloseMessageBox();\n                }}>\n                    <FormattedMessage\n                        id=\"solutionButtonConfirmDelete\"\n                        description=\"Text on 'delete' button to confirm deletion in the solution manager\"\n                        defaultMessage=\"Delete\"\n                        />\n                </Button>\n                <Button focusOnMount={true} onClick={() => this.props.onCloseMessageBox()}>\n                    <FormattedMessage\n                        id=\"solutionButtonCancelDelete\"\n                        description=\"Text on the 'cancel' button when trying to delete an item in the solution manager\"\n                        defaultMessage=\"Cancel\"\n                        />\n                </Button>\n            </>,\n        })\n    }\n\n    public render(): React.ReactNode {\n        return <>\n            <div\n                className=\"itemList\"\n                tabIndex={0}\n                onKeyDown={(event) => {\n                    const offset = Shared.keyToVerticalOffset[event.key];\n                    if (offset) {\n                        let index = this.state.solutions.findIndex(s => s.name === this.props.solutionName);\n                        if (index >= 0) {\n                            index += offset;\n                            if (index >= 0 && index < this.state.solutions.length) {\n                                this.props.onSelectionChanged(this.state.solutions[index].name);\n                            }\n                        }\n\n                        event.preventDefault();\n                    } else if (event.key === \"Enter\") {\n                        this.props.onOpen(this.props.solutionName);\n                    }\n                }}\n                >\n                {this.state.solutions.map((solution, index) => <p\n                    key={solution.name}\n                    ref={((this.props.solutionName) && (solution.name === this.props.solutionName)) ? this.selectedItem : undefined}\n                    className={((this.props.solutionName) && (solution.name === this.props.solutionName)) ? \"selected\" : \"\"}\n                    onDoubleClick={() => this.props.onOpen(solution.name)}\n                    onClick={() => this.onClick(solution.name)}\n                    tabIndex={-1}\n                >\n                    {(this.state.renaming && (solution.name === this.props.solutionName))\n                        ? <InputSpan\n                            initialValue={solution.name}\n                            onApply={(value) => {\n                                this.renameSolution(value);\n                                this.selectedItem.current?.focus?.();\n                            }}\n                            onCancel={() => this.setState({ renaming: false })}\n                            />\n                        : solution.name\n                    }{(solution.solutionCycles && solution.solutionBytes)\n                        ? <FormattedMessage\n                            id=\"solutionStatsSuffix\"\n                            description=\"Formatted statistics that are appended to a solution title, for reference (note the leading space)\"\n                            defaultMessage=\" (cycles: {cycles}, bytes: {bytes})\"\n                            values={{\n                                cycles: solution.solutionCycles,\n                                bytes: solution.solutionBytes,\n                            }}\n                            />\n                        : null}\n                    {(solution.name === this.props.solutionName)\n                        ? <>\n                            <span className=\"itemMoveContainer\">\n                                <Button className=\"itemMove\" disabled={index <= 0} onClick={() => this.moveSolution(-1)}>↑</Button>\n                                <Button className=\"itemMove\" disabled={index >= this.state.solutions.length - 1} onClick={() => this.moveSolution(1)}>↓</Button>\n                            </span>\n                        </>\n                        : null\n                    }\n                </p>)}\n                {this.state.solutions.length <= 0\n                    ? <p className=\"sub\">\n                        <FormattedMessage\n                            id=\"taskViewerFilesEmpty\"\n                            description=\"Text shown when there are no solutions saved for a task\"\n                            defaultMessage=\"(No files found)\"\n                            />\n                    </p>\n                    : null}\n            </div>\n            <div className=\"horizontalButtons\">\n                <Button onClick={() => this.newSolution()}>\n                    <FormattedMessage\n                        id=\"taskViewerButtonSolutionNew\"\n                        description=\"Text on the task viewer button to create a new solution file\"\n                        defaultMessage=\"New\"\n                        />\n                </Button>\n                <Button disabled={!this.props.solutionName} onClick={() => this.copySolution()}>\n                    <FormattedMessage\n                        id=\"taskViewerButtonSolutionCopy\"\n                        description=\"Text on the task viewer button to copy a solution file\"\n                        defaultMessage=\"Copy\"\n                        />\n                </Button>\n                <Button disabled={!this.props.solutionName} onClick={() => this.setState({ renaming: true })}>\n                    <FormattedMessage\n                        id=\"taskViewerButtonSolutionRename\"\n                        description=\"Text on the task viewer button to rename a solution file\"\n                        defaultMessage=\"Rename\"\n                        />\n                </Button>\n                <Button intent=\"solutionDelete\" disabled={!this.props.solutionName} onClick={() => this.showDeleteConfirmation()}>\n                    <FormattedMessage\n                        id=\"taskViewerButtonSolutionDelete\"\n                        description=\"Text on the task viewer button to attempt to delete a solution file\"\n                        defaultMessage=\"Delete\"\n                        />\n                </Button>\n            </div>\n        </>;\n    }\n}\n", "sic1/client/ts/platform.ts": "import { Achievement } from \"./achievements\";\nimport { localeToHrefOrMessages, localeToManualHref } from \"./language-data\";\nimport { getBestLocale, steamApiLanguageCodeToLocale } from \"./language-default\";\nimport { wrapNativePromise } from \"./native-promise-wrapper\";\nimport { Sic1Service, Sic1SteamService, Sic1WebService } from \"./service\";\nimport { platform, PlatformName } from \"./setup\";\nimport { Shared } from \"./shared\";\nimport { SteamApi } from \"./steam-api\";\n\ninterface FullscreenManager {\n    get: () => boolean;\n    set(fullscreen: boolean): void;\n}\n\nexport interface PresentationData {\n    fullscreen: boolean;\n    zoom: number;\n\n    soundEffects: boolean;\n    soundVolume: number;\n    \n    music: boolean;\n    musicVolume: number;\n}\n\nclass CoalescedFunction {\n    private scheduled = false;\n    private resolves: (() => void)[] = [];\n    private rejects: ((reason?: any) => void)[] = [];\n\n    constructor(private readonly f: () => void | undefined, private readonly delay: number) {\n    }\n\n    public runAsync(): Promise<void> {\n        if (this.f && !this.scheduled) {\n            this.scheduled = true;\n            setTimeout(() => {\n                this.scheduled = false;\n                try {\n                    this.f();\n                    for (const resolve of this.resolves) {\n                        resolve();\n                    }\n                } catch (e) {\n                    for (const reject of this.rejects) {\n                        reject(e);\n                    }\n                } finally {\n                    this.resolves.length = 0;\n                    this.rejects.length = 0;\n                }\n            }, this.delay);\n        }\n\n        return new Promise<void>((resolve, reject) => {\n            this.resolves.push(resolve);\n            this.rejects.push(reject);\n        });\n    }\n}\n\nexport interface Platform {\n    /** Indicates the program should have native app semantics, e.g. it should have an \"exit\" option in the menu. */\n    readonly app: boolean;\n\n    /** For determining the default (browser or Steam requested) language */\n    readonly getDefaultLocale: () => string;\n\n    /** Opens the SIC-1 manual in a new tab/window. */\n    readonly openManual: (locale: string) => void;\n\n    /** Indicates that there should *not* be an option to upload the user's name to leaderboards (via web service).  */\n    readonly disableUserNameUpload?: boolean;\n\n    /** True if platform should support manual export/import of save data. */\n    readonly allowImportExport?: boolean;\n\n    /** Used for querying and setting full-screen mode. */\n    readonly fullscreen: FullscreenManager;\n\n    /** User profile and/or statistics service implementation. */\n    readonly service: Sic1Service;\n\n    /** Overrides the user name, if provided. */\n    readonly userNameOverride?: string;\n\n    /** Overrides saved full-screen value on load, if provided. */\n    readonly fullscreenDefault?: boolean;\n\n    /** Persist localStorage data (only necessary in app mode) */\n    readonly scheduleLocalStoragePersist?: () => void;\n\n    /** Persist presentation settings (only necessary in app mode) */\n    readonly schedulePresentationSettingsPersist?: () => void;\n\n    /** Presentation settings storage override. */\n    presentationSettings?: PresentationData;\n\n    /** Write a callback to this property to have it called in app mode when the window is being closed (e.g. to save progress). */\n    onClosing?: () => void;\n\n    /** Get \"achieved\" status of an achievement. */\n    readonly getAchievementAsync: (id: string ) => Promise<boolean>;\n\n    /** Used for setting achievements. */\n    readonly setAchievementAsync: (id: Achievement) => Promise<boolean>;\n\n    /** Used for suppressing achievement notification when windowed for Steam (because Steam UI pops up a notification on the desktop). */\n    readonly shouldShowAchievementNotification?: () => boolean;\n}\n\nconst availableLocales = Object.keys(localeToHrefOrMessages);\n\nconst createPlatform: Record<string, () => Platform> = {\n    web: () => {\n        const achievementsKey = `${Shared.localStoragePrefix}achievements`;\n        function loadAchievements(): { [id: string]: boolean } {\n            let achievements: { [id: string]: boolean };\n            try {\n                const achievementsJson = localStorage.getItem(achievementsKey);\n                if (achievementsJson) {\n                    achievements = JSON.parse(achievementsJson);\n                }\n            } catch {\n                // Just re-create on error\n            }\n\n            return (typeof(achievements) === \"object\") ? achievements : {};\n        }\n\n        return {\n            app: false,\n            allowImportExport: false,\n            disableUserNameUpload: true,\n            getDefaultLocale: () => getBestLocale(navigator.languages ?? [navigator.language], availableLocales),\n            openManual: (locale) => {},\n            service: new Sic1WebService(),\n            fullscreen: {\n                get: () => !!document.fullscreenElement,\n                set: (fullscreen) => {\n                    if (fullscreen && !document.fullscreenElement) {\n                        document.documentElement.requestFullscreen();\n                    } else if (!fullscreen && document.fullscreenElement) {\n                        document.exitFullscreen();\n                    }\n                },\n            },\n            shouldShowAchievementNotification: () => true,\n            getAchievementAsync: (id: string) => {\n                return Promise.resolve(!!loadAchievements()[id]);\n            },\n            setAchievementAsync: (id) => {\n                const achievements = loadAchievements();\n                let newlyAchieved = false;\n                if (!achievements[id]) {\n                    achievements[id] = true;\n                    newlyAchieved = true;\n                    \n                    try {\n                        localStorage.setItem(achievementsKey, JSON.stringify(achievements))\n                    } catch (e) {\n                        // Just ignore all errors writing to localStorage, in case it's disabled...\n                    }\n                }\n\n                return Promise.resolve(newlyAchieved);\n            },\n        };\n    },\n};\n\nexport const Platform: Platform = createPlatform[platform]();\n", "sic1/client/ts/music.ts": "export type SongId = \"default\"|\"menu\"|\"avoision\"|\"major\"|\"light\";\nexport class Music { static play(id?:SongId){} static pause(){} static setEnabled(enabled:boolean){} static setVolume(volume:number){} }\n", "sic1/client/ts/ide-input-editor.tsx": "import React from \"react\";\nimport { Assembler, Tokenizer, TokenType } from \"../../../lib/src/sic1asm\";\nimport { Button } from \"./button\";\nimport { Format } from \"./puzzles\";\nimport { Shared } from \"./shared\";\nimport { FormattedMessage, IntlShape } from \"react-intl\";\n\nconst formatDisplayNames = [\n    <FormattedMessage\n        id=\"ioTypeNumbers\"\n        description=\"Label for the 'number' type, for task input/output in Sandbox Mode\"\n        defaultMessage=\"Numbers\"\n        />,\n    <FormattedMessage\n        id=\"ioTypeCharacters\"\n        description=\"Label for the 'character' type, for task input/output in Sandbox Mode\"\n        defaultMessage=\"Characters\"\n        />,\n    <FormattedMessage\n        id=\"ioTypeStrings\"\n        description=\"Label for the 'string' type, for task input/output in Sandbox Mode\"\n        defaultMessage=\"Strings\"\n        />,\n];\n\nexport function parseValues(intl: IntlShape, text: string): number[] {\n    const tokens = Tokenizer.tokenizeLine(text);\n    const input: number[] = [];\n    for (const token of tokens) {\n        const { tokenType } = token;\n        switch (tokenType) {\n            case TokenType.whiteSpace:\n                break;\n\n            case TokenType.comma:\n                break;\n\n            case TokenType.numberLiteral:\n                // Note: Test inputs are actually signed\n                input.push(Assembler.unsignedToSigned(Assembler.parseValue(token)));\n                break;\n\n            case TokenType.characterLiteral:\n                input.push(Assembler.unsignedToSigned(Assembler.parseCharacter(token)));\n                break;\n\n            case TokenType.stringLiteral:\n                input.push(...Assembler.parseString(token).map(u => Assembler.unsignedToSigned(u)));\n                break;\n\n            default:\n                throw new Error(intl.formatMessage({\n                    id: \"errorInputParsing\",\n                    description: \"Error text shown in Sandbox Mode when there's a parsing error for custom input\",\n                    defaultMessage: `Unexpected token: \"{token}\"!`,\n                }, { token: token.raw }));\n        }\n    }\n\n    return input;\n}\n\ninterface Sic1CustomInputSettings {\n    input: number[];\n    text: string;\n    inputFormat: Format;\n    outputFormat: Format;\n};\n\nexport interface Sic1InputEditorProperties {\n    intl: IntlShape;\n\n    onApply: (settings: Sic1CustomInputSettings) => void;\n    onClose: () => void;\n\n    defaultInputString?: string;\n    defaultInputFormat?: Format;\n    defaultOutputFormat?: Format;\n}\n\ninterface Sic1InputEditorState {\n    error?: string;\n}\n\nexport class Sic1InputEditor extends React.Component<Sic1InputEditorProperties, Sic1InputEditorState> {\n    private form = React.createRef<HTMLFormElement>();\n    private input = React.createRef<HTMLInputElement>();\n    private inputFormat = React.createRef<HTMLSelectElement>();\n    private outputFormat = React.createRef<HTMLSelectElement>();\n\n    constructor(props) {\n        super(props);\n        this.state = {};\n    }\n\n    private apply(): void {\n        if (this.form.current && this.input.current && this.inputFormat.current && this.outputFormat.current) {\n            const text = this.input.current.value;\n            try {\n                const input = parseValues(this.props.intl, this.input.current.value);\n                this.props.onApply({\n                    input,\n                    text,\n                    inputFormat: parseInt(this.inputFormat.current.value),\n                    outputFormat: parseInt(this.outputFormat.current.value),\n                });\n\n                this.props.onClose();\n                this.setState({ error: undefined });\n            } catch (e) {\n                this.setState({ error: e.message });\n            }\n        }\n    }\n\n    public componentDidMount(): void {\n        const input = this.input.current;\n        if (input) {\n            input.focus();\n\n            // Move the cursor to the end, for convenience\n            input.setSelectionRange(input.value.length, input.value.length);\n        }\n    }\n\n    public render() {\n        return  <>\n            <FormattedMessage\n                id=\"contentInputEditor\"\n                description=\"Markup shown at the beginning of the 'input editor' of Sandbox Mode\"\n                defaultMessage={`<h3>Instructions</h3><p>For input, use the same syntax as in a <code>.data</code> directive (examples: <code>-7</code>, <code>''A''</code>, <code>-\"Negated string\"</code>).</p>`}\n                />\n            <h3>\n                <FormattedMessage\n                    id=\"headingInputEditor\"\n                    description=\"Heading for the 'input values' section of Sandbox Mode's input editor\"\n                    defaultMessage=\"Input values\"\n                    />\n            </h3>\n            <form\n                ref={this.form}\n                onSubmit={(event) => {\n                    event.preventDefault();\n                    this.apply();\n                }}\n            >\n                <input\n                    ref={this.input}\n                    className=\"width100\"\n                    defaultValue={this.props.defaultInputString}\n                />\n                {this.state.error\n                    ? <p>\n                        <FormattedMessage\n                            id=\"textInputError\"\n                            description=\"Text shown when an error occurs when parsing custom input in Sandbox Mode\"\n                            defaultMessage=\"Error: {message}\"\n                            values={{ message: this.state.error }}\n                            />\n                        </p>\n                    : null}\n                <br/>\n                <h3>\n                    <FormattedMessage\n                        id=\"headingInputFormats\"\n                        description=\"Heading for the 'display formats' section of Sandbox Mode's editor\"\n                        defaultMessage=\"Display formats\"\n                        />\n                </h3>\n                {([\n                    [\"input\", Shared.resources.headerIOIn, this.inputFormat, this.props.defaultInputFormat],\n                    [\"output\", Shared.resources.headerIOOut, this.outputFormat, this.props.defaultOutputFormat],\n                ] as const).map(([key, title, ref, format]) => <React.Fragment key={key}>\n                    <label>{title}:&nbsp;<select ref={ref} defaultValue={format}>{formatDisplayNames.map((displayName, index) => <option key={index} value={index}>\n                        {displayName}</option>)}\n                    </select></label><br/>\n                </React.Fragment>)}\n            </form>\n            <br/>\n            <Button onClick={() => this.apply()}>{Shared.resources.saveChanges}</Button>\n            <Button onClick={() => this.props.onClose()}>{Shared.resources.cancel}</Button>\n\n        </>;\n    }\n}\n", "sic1/client/ts/mail-viewer.tsx": "import React from \"react\";\nimport { Browser, BrowserIndices, BrowserItem } from \"./browser\";\nimport { Contact, Contacts, formatContact, formatContactWithoutTitle } from \"./contacts\";\nimport { Inbox, Sic1DataManager, UserData } from \"./data-manager\";\nimport { ensureMailRead, mails } from \"./mail\";\nimport { PuzzleListTypes } from \"./puzzle-list\";\nimport { ClientPuzzle } from \"./puzzles\";\nimport { Shared } from \"./shared\";\nimport { Mail } from \"./mail-shared\";\nimport { FormattedMessage } from \"react-intl\";\n\ninterface MailViewerProps {\n    mails: Inbox;\n    initialMailId?: string;\n    currentPuzzleTitle: string;\n    titleToClientPuzzle: { [title: string]: ClientPuzzle };\n    puzzleSandbox: ClientPuzzle;\n    onClearMessageBoxRequested: () => void;\n    onNextPuzzleRequested?: () => void;\n    onPuzzleListRequested: (type: PuzzleListTypes, title?: string) => void;\n    onCreditsRequested: () => void;\n    onManualInGameRequested: () => void;\n    onManualInNewWindowRequested: () => void;\n    onMailRead: (id: string) => void;\n}\n\ninterface MailViewProps {\n    mail: Mail;\n    data: UserData;\n    titleToClientPuzzle: { [title: string]: ClientPuzzle };\n    onMailRead: (id: string) => void;\n}\n\nclass MailView extends React.Component<MailViewProps> {\n    public componentDidMount(): void {\n        ensureMailRead(this.props.mail);\n        this.props.onMailRead(this.props.mail.id);\n    }\n\n    public render(): React.ReactNode {\n        const { to, from } = this.props.mail;\n\n        // A bit of a hack, but try to detect the solved count for this mail and display the corresponding job title\n        const { solvedCount } = this.props.mail;\n        const self: Contact = {\n            name: this.props.data.name,\n            title: Shared.getJobTitleForSolvedCount(solvedCount ?? this.props.data.solvedCount),\n        };\n\n        const toFragment = to\n            ? <>\n                {to.map((c, index) => <React.Fragment key={c}>\n                        {(index === 0) ? null : <><br/><FormattedMessage id=\"mailViewerExtraToLineIndent\" description=\"Optional indent using {nbsp} non-breaking spaces to line up with 'from' line\" defaultMessage=\"{nbsp}{nbsp}{nbsp}{nbsp}{nbsp} \" values={{nbsp: <>&nbsp;</>}}/></>}\n                        {c === \"self\" ? formatContact(self) : formatContact(Contacts[c])}\n                    </React.Fragment>)}\n                {to.length > 1 ? <br/> : null}\n                </>\n            : formatContact(self);\n\n        return <>\n            <header>\n                <FormattedMessage\n                    id=\"mailViewerMailHeading\"\n                    description=\"Heading content markup shown in the mail viewer for a particular mail (optionally use {nbsp} non-breaking spaces to line up 'to' and 'from' lines); use {newline} at the end of each line\"\n                    defaultMessage=\"<cap>To</cap>:{nbsp}{nbsp} {to}{newline}<cap>From</cap>: {from}{newline}{newline}<cap>Subject</cap>: {subject}{newline}\"\n                    values={{\n                        nbsp: <>&nbsp;</>,\n                        newline: <br/>,\n                        to: toFragment,\n                        from: formatContact(from),\n                        subject: formatSubject(this.props.mail, this.props.titleToClientPuzzle),\n                    }}\n                    />\n            </header>\n            {this.props.mail.create({\n                self,\n                from: this.props.mail.from,\n                jobTitles: Shared.jobTitles,\n            })}\n        </>\n    }\n}\n\ntype MailItem = Mail & BrowserItem & { read: boolean };\n\nfunction formatSubject(mail: Mail, titleToClientPuzzle: { [title: string]: ClientPuzzle }): React.ReactNode {\n    return (mail.loadType === \"puzzle\")\n        ? <FormattedMessage\n            id=\"mailViewerTaskSubject\"\n            description=\"Subject line for task completion mails\"\n            defaultMessage=\"RE: {taskName}\"\n            values={{ taskName: titleToClientPuzzle[mail.id].displayTitle }}\n            />\n        : mail.subject;\n}\n\nexport class MailViewer extends React.Component<MailViewerProps, { selection: BrowserIndices }> {\n    private groups: { key:string, title: React.ReactNode, items: MailItem[] }[];\n\n    constructor(props) {\n        super(props);\n\n        const mail: MailItem[] = this.props.mails.map(m => {\n            const mail = mails[m.id];\n            const viewNextTask = {\n                title: <FormattedMessage\n                    id=\"mailViewerButtonNextTask\"\n                    description=\"Button text for the 'view next task' button in the mail viewer\"\n                    defaultMessage=\"View Next Task\"\n                    />,\n                intent: \"View Next Task\",\n                onClick: () => this.props.onNextPuzzleRequested()\n            };\n\n            const actionToButton = {\n                manual: {\n                    title: <FormattedMessage\n                        id=\"mailViewerButtonOpenManual\"\n                        description=\"Button text for the 'open manual in-game' button in the mail viewer\"\n                        defaultMessage=\"Open Manual In-Game\"\n                        />,\n                    intent: \"manualInGame\",\n                    onClick: () => this.props.onManualInGameRequested()\n                },\n                manualInNewWindow: {\n                    title: <FormattedMessage\n                        id=\"mailViewerButtonOpenManualNewWindow\"\n                        description=\"Button text for the 'open manual in new window' button in the mail viewer\"\n                        defaultMessage=\"Open Manual Here\"\n                        />,\n                    intent: \"manualNewWindow\",\n                    onClick: () => this.props.onManualInNewWindowRequested()\n                },\n                credits: {\n                    title: <FormattedMessage\n                        id=\"mailViewerButtonCredits\"\n                        description=\"Button text for the 'view credits' button in the mail viewer\"\n                        defaultMessage=\"View Credits\"\n                        />,\n                    intent: \"credits\",\n                    onClick: () => this.props.onCreditsRequested()\n                },\n                sandbox: {\n                    title: <FormattedMessage\n                        id=\"mailViewerButtonSandbox\"\n                        description=\"Button text for the 'view sandbox mode' button in the mail viewer\"\n                        defaultMessage=\"View Sandbox Mode\"\n                        />,\n                    intent: \"sandbox\",\n                    onClick: () => this.props.onPuzzleListRequested(\"puzzle\", this.props.puzzleSandbox.title)\n                },\n            };\n            \n            return  {\n                ...mail,\n                key: mail.id,\n                title: formatSubject(mail, this.props.titleToClientPuzzle),\n                subtitle: <>&nbsp;{formatContactWithoutTitle(mail.from)}</>,\n                read: m.read,\n                buttons: [\n                    ...((mail.loadType && mail.loadLabel) ? [{ title: mail.loadLabel, intent: \"custom\", onClick: () => this.props.onPuzzleListRequested(mail.loadType) }] : []),\n                    ...((mail.loadType === \"puzzle\")\n                        ? ((mail.id === this.props.currentPuzzleTitle)\n                            ? (this.props.onNextPuzzleRequested ? [viewNextTask] : [])\n                            : [{\n                                title: <FormattedMessage\n                                    id=\"mailViewerButtonViewTask\"\n                                    description=\"Button text for the 'view a specific task' button in the mail viewer\"\n                                    defaultMessage=\"View {taskName}\"\n                                    values={{ taskName: this.props.titleToClientPuzzle[mail.id]?.displayTitle }}\n                                    />,\n                                intent: \"loadPuzzle\",\n                                onClick: () => this.props.onPuzzleListRequested(mail.loadType, mail.id)\n                                }])\n                        : (this.props.onNextPuzzleRequested ? [viewNextTask] : [])),\n                    ...((mail.id === this.props.currentPuzzleTitle)\n                        ? [{\n                                title: <FormattedMessage\n                                    id=\"mailViewerButtonContinueEditing\"\n                                    description=\"Button text for the 'continue editing' button in the mail viewer\"\n                                    defaultMessage=\"Continue Editing Current Program\"\n                                    />,\n                                intent: \"continueEditing\",\n                                onClick: () => this.props.onClearMessageBoxRequested()\n                            }]\n                        : []),\n                    ...((mail.actions?.map(id => actionToButton[id]) ?? [])),\n                ],\n            };\n        });\n\n        const unreadMails = mail.filter(m => !m.read);\n        const readMails = mail.filter(m => m.read);\n\n        // Replace \"view next task\" with \"next unread mail\" button for  all but the last unread mail\n        for (let i = 0; i < unreadMails.length - 1; i++) {\n            const unreadMail = unreadMails[i];\n            if (unreadMail.buttons[0]?.intent === \"View Next Task\") {\n                unreadMail.buttons.splice(0, 1);\n            }\n\n            unreadMail.buttons.unshift({\n                title: <FormattedMessage\n                    id=\"mailViewerViewNextUnread\"\n                    description=\"Button text for the 'view next unread mail' button in the mail viewer\"\n                    defaultMessage=\"View Next Unread Mail\"\n                    />,\n                intent: \"viewNextUnread\",\n                onClick: () => this.setState({ selection: { groupIndex: 0, itemIndex: i + 1 } }),\n            });\n        }\n\n        this.groups = [];\n        if (unreadMails.length > 0) {\n            this.groups.push({\n                key: \"unread\",\n                title: <FormattedMessage\n                    id=\"mailViewerGroupUnread\"\n                    description=\"Group heading for 'unread mail' in the mail viewer\"\n                    defaultMessage=\"Unread Mail\"\n                    />,\n                items: unreadMails,\n            });\n        }\n\n        this.groups.push({\n            key: \"main\",\n            title: this.groups.length === 0\n                ? <FormattedMessage\n                    id=\"mailViewerHeadingUnread\"\n                    description=\"Mail viewer heading for unread mail\"\n                    defaultMessage=\"Inbox\"\n                    />\n                : <FormattedMessage\n                    id=\"mailViewerHeadingRead\"\n                    description=\"Mail viewer heading for mail that has already been read\"\n                    defaultMessage=\"Read Mail\"\n                    />,\n            items: readMails,\n        });\n\n        // Select an item by default, if none was specified (or found)\n        let { groupIndex, itemIndex } = this.findMailById(this.props.initialMailId);\n        if (groupIndex === undefined || itemIndex === undefined) {\n            // If there are unread mails, open the first one; if not open the last mail\n            groupIndex = 0;\n            itemIndex = (unreadMails.length === 0) ? (readMails.length - 1) : 0;\n        }\n\n        this.state = { selection: { groupIndex, itemIndex }};\n    }\n\n    private findMailById(id: string | undefined): Partial<BrowserIndices> {\n        let groupIndex: number;\n        let itemIndex: number;\n        if (id) {\n            for (let g = 0; g < this.groups.length; g++) {\n                const items = this.groups[g].items;\n                const index = items.findIndex(m => m.id === id);\n                if (index >= 0) {\n                    groupIndex = g;\n                    itemIndex = index;\n                    break;\n                }\n            }\n        }\n\n        return { groupIndex, itemIndex };\n    }\n\n    public selectMail(mailId: string): void {\n        if (mailId) {\n            const { groupIndex, itemIndex } = this.findMailById(mailId);\n            if (groupIndex !== undefined && itemIndex !== undefined) {\n                this.setState({ selection: { groupIndex, itemIndex }});\n            }\n        }\n    }\n\n    public render(): React.ReactNode {\n        const { groupIndex, itemIndex } = this.state.selection;\n        const mail = this.groups[groupIndex].items[itemIndex];\n        return <Browser className=\"mailBrowser\" groups={this.groups}  selection={this.state.selection} onSelectionChanged={(selection) => this.setState({ selection })}>\n            <MailView\n                key={mail.id}\n                mail={mail}\n                data={Sic1DataManager.getData()}\n                titleToClientPuzzle={this.props.titleToClientPuzzle}\n                onMailRead={this.props.onMailRead}\n                />\n        </Browser>;\n    }\n}\n", "sic1/client/ts/message-box.tsx": "import React from \"react\";\nimport { Button } from \"./button\";\nimport { Shared } from \"./shared\";\n\nexport const MessageBoxBehavior = {\n    keyboardNavigationForButtons: 0x1,\n    focusFirstButton: 0x2,\n} as const;\n\nexport const menuBehavior = MessageBoxBehavior.keyboardNavigationForButtons | MessageBoxBehavior.focusFirstButton;\n\nexport interface MessageBoxContent {\n    title: string;\n    behavior?: number, // MessageBoxBehavior\n    modal?: boolean;\n    transparent?: boolean;\n    width?: \"none\" | \"wide\" | \"narrowByDefault\";\n    body: React.ReactNode;\n}\n\ninterface MessageBoxProperties extends MessageBoxContent {\n    zIndex: number;\n    onDismissed: () => void;\n}\n\nexport class MessageBox extends React.Component<MessageBoxProperties> {\n    private static readonly menuButtonSelector = \".messageBody button\";\n    private static readonly dimmerZOffset = 5;\n\n    private body = React.createRef<HTMLDivElement>();\n\n    constructor(props: MessageBoxProperties) {\n        super(props);\n    }\n\n    private close = () => {\n        if (this.props.modal !== true) {\n            this.props.onDismissed();\n        }\n    }\n\n    public componentDidMount(): void {\n        if ((this.props.behavior & menuBehavior) === menuBehavior) {\n            document.querySelector<HTMLButtonElement>(MessageBox.menuButtonSelector)?.focus?.();\n        }\n    }\n\n    public render() {\n        const width = this.props.width ?? \"narrow\";\n        return <>\n            <div className=\"centerContainer\">\n                <div className={`messageBox${(this.props.width === \"none\") ? \"\" : ` ${width}`}`} style={{zIndex: this.props.zIndex}}>\n                    <div className=\"messageHeader\">\n                        {this.props.title}\n                        {this.props.modal === true ? null : <Button className=\"messageClose\" onClick={this.close} title=\"Esc\">X</Button>}\n                    </div>\n                    <div ref={this.body} className=\"messageBody\" onKeyDown={(this.props.behavior & MessageBoxBehavior.keyboardNavigationForButtons) ? (event) => {\n                        const offset = Shared.keyToVerticalOffset[event.key];\n                        if (offset) {\n                            Shared.focusFromQuery(this.body.current, MessageBox.menuButtonSelector, offset, true);\n                            event.preventDefault();\n                        }\n                    } : null}>\n                        {this.props.body}\n                    </div>\n                </div>\n                <div className=\"dimmer\" onClick={this.close} style={{zIndex: this.props.zIndex - MessageBox.dimmerZOffset}}></div>\n            </div>\n        </>;\n    }\n}\n", "sic1/client/ts/image-cache.ts": "const imageCache: { [uri: string]: HTMLImageElement } = {};\n\nfunction loadImageInternalAsync(uri: string, width?: number, height?: number): Promise<HTMLImageElement> {\n    return new Promise((resolve, reject) => {\n        const image = new Image(width, height);\n        image.onload = () => resolve(image);\n        image.onerror = (event, source, line, column, error) => reject(error);\n        image.src = uri;\n    });\n}\n\nexport async function loadImageAsync(uri: string, width?: number, height?: number): Promise<HTMLImageElement> {\n    const cachedImage = imageCache[uri];\n    if (cachedImage) {\n        return cachedImage;\n    }\n\n    const image = await loadImageInternalAsync(uri, width, height);\n    imageCache[uri] = image;\n    return image;\n}\n", "sic1/client/ts/stats-cache.ts": "import * as Contract from \"../../server/contract/contract\";\n\nexport type Sic1PuzzleStats = { [puzzleTitle: string]: Contract.PuzzleStatsResponse };\n\nexport interface Sic1StatsCache {\n    userStats: Contract.UserStatsResponse;\n    puzzleStats: Sic1PuzzleStats;\n}\n\nconst steamStatsCache: Sic1StatsCache = {\"userStats\":{\"solutionsByUser\":[{\"bucketMax\":1,\"count\":846},{\"bucketMax\":2,\"count\":814},{\"bucketMax\":3,\"count\":426},{\"bucketMax\":4,\"count\":222},{\"bucketMax\":5,\"count\":266},{\"bucketMax\":6,\"count\":193},{\"bucketMax\":7,\"count\":154},{\"bucketMax\":8,\"count\":40},{\"bucketMax\":9,\"count\":12},{\"bucketMax\":10,\"count\":9},{\"bucketMax\":11,\"count\":9},{\"bucketMax\":12,\"count\":15},{\"bucketMax\":13,\"count\":110},{\"bucketMax\":14,\"count\":58},{\"bucketMax\":15,\"count\":47},{\"bucketMax\":16,\"count\":39},{\"bucketMax\":17,\"count\":9},{\"bucketMax\":18,\"count\":1},{\"bucketMax\":21,\"count\":1},{\"bucketMax\":22,\"count\":2},{\"bucketMax\":23,\"count\":3},{\"bucketMax\":24,\"count\":6},{\"bucketMax\":25,\"count\":4},{\"bucketMax\":27,\"count\":2},{\"bucketMax\":28,\"count\":3},{\"bucketMax\":29,\"count\":6},{\"bucketMax\":30,\"count\":13},{\"bucketMax\":31,\"count\":24}],\"userSolvedCount\":0},\"puzzleStats\":{\"Subleq Instruction and Output\":{\"cyclesExecutedBySolution\":[{\"bucketMax\":1,\"count\":3325},{\"bucketMax\":2,\"count\":1},{\"bucketMax\":4,\"count\":1}],\"memoryBytesAccessedBySolution\":[{\"bucketMax\":4,\"count\":84},{\"bucketMax\":5,\"count\":3243},{\"bucketMax\":8,\"count\":2}]},\"Data Directive and Looping\":{\"cyclesExecutedBySolution\":[{\"bucketMax\":3,\"count\":530},{\"bucketMax\":4,\"count\":5},{\"bucketMax\":5,\"count\":1951},{\"bucketMax\":8,\"count\":1}],\"memoryBytesAccessedBySolution\":[{\"bucketMax\":5,\"count\":418},{\"bucketMax\":8,\"count\":7},{\"bucketMax\":9,\"count\":2056},{\"bucketMax\":11,\"count\":3},{\"bucketMax\":12,\"count\":1},{\"bucketMax\":13,\"count\":1}]},\"First Assessment\":{\"cyclesExecutedBySolution\":[{\"bucketMax\":6,\"count\":112},{\"bucketMax\":8,\"count\":1504},{\"bucketMax\":9,\"count\":1},{\"bucketMax\":10,\"count\":46},{\"bucketMax\":11,\"count\":5},{\"bucketMax\":12,\"count\":1},{\"bucketMax\":14,\"count\":1}],\"memoryBytesAccessedBySolution\":[{\"bucketMax\":9,\"count\":10},{\"bucketMax\":11,\"count\":107},{\"bucketMax\":12,\"count\":1497},{\"bucketMax\":14,\"count\":1},{\"bucketMax\":15,\"count\":7},{\"bucketMax\":16,\"count\":43},{\"bucketMax\":18,\"count\":1},{\"bucketMax\":19,\"count\":1},{\"bucketMax\":23,\"count\":1},{\"bucketMax\":27,\"count\":1},{\"bucketMax\":33,\"count\":1}]},\"Addition\":{\"cyclesExecutedBySolution\":[{\"bucketMax\":15,\"count\":64},{\"bucketMax\":18,\"count\":52},{\"bucketMax\":19,\"count\":1030},{\"bucketMax\":21,\"count\":1},{\"bucketMax\":23,\"count\":7},{\"bucketMax\":24,\"count\":4},{\"bucketMax\":28,\"count\":2},{\"bucketMax\":29,\"count\":1},{\"bucketMax\":37,\"count\":25},{\"bucketMax\":38,\"count\":6},{\"bucketMax\":39,\"count\":1},{\"bucketMax\":41,\"count\":4},{\"bucketMax\":42,\"count\":1},{\"bucketMax\":44,\"count\":1},{\"bucketMax\":46,\"count\":21},{\"bucketMax\":47,\"count\":8},{\"bucketMax\":48,\"count\":5},{\"bucketMax\":49,\"count\":1},{\"bucketMax\":50,\"count\":3},{\"bucketMax\":51,\"count\":1},{\"bucketMax\":56,\"count\":1},{\"bucketMax\":60,\"count\":1},{\"bucketMax\":63,\"count\":1}],\"memoryBytesAccessedBySolution\":[{\"bucketMax\":12,\"count\":10},{\"bucketMax\":14,\"count\":161},{\"bucketMax\":15,\"count\":971},{\"bucketMax\":17,\"count\":1},{\"bucketMax\":18,\"count\":1},{\"bucketMax\":19,\"count\":11},{\"bucketMax\":22,\"count\":3},{\"bucketMax\":28,\"count\":6},{\"bucketMax\":29,\"count\":26},{\"bucketMax\":32,\"count\":3},{\"bucketMax\":33,\"count\":3},{\"bucketMax\":34,\"count\":4},{\"bucketMax\":35,\"count\":9},{\"bucketMax\":36,\"count\":22},{\"bucketMax\":39,\"count\":3},{\"bucketMax\":40,\"count\":1},{\"bucketMax\":42,\"count\":1},{\"bucketMax\":46,\"count\":2}]},\"Subtraction\":{\"cyclesExecutedBySolution\":[{\"bucketMax\":20,\"count\":35},{\"bucketMax\":28,\"count\":795},{\"bucketMax\":29,\"count\":12},{\"bucketMax\":31,\"count\":1},{\"bucketMax\":32,\"count\":16},{\"bucketMax\":33,\"count\":3},{\"bucketMax\":34,\"count\":3},{\"bucketMax\":36,\"count\":1},{\"bucketMax\":37,\"count\":58},{\"bucketMax\":38,\"count\":48},{\"bucketMax\":39,\"count\":1},{\"bucketMax\":41,\"count\":4},{\"bucketMax\":42,\"count\":6},{\"bucketMax\":43,\"count\":1},{\"bucketMax\":44,\"count\":1},{\"bucketMax\":46,\"count\":6},{\"bucketMax\":47,\"count\":5},{\"bucketMax\":48,\"count\":1},{\"bucketMax\":50,\"count\":1},{\"bucketMax\":54,\"count\":3},{\"bucketMax\":55,\"count\":10},{\"bucketMax\":56,\"count\":1},{\"bucketMax\":57,\"count\":6},{\"bucketMax\":59,\"count\":2},{\"bucketMax\":64,\"count\":1},{\"bucketMax\":68,\"count\":1}],\"memoryBytesAccessedBySolution\":[{\"bucketMax\":18,\"count\":10},{\"bucketMax\":20,\"count\":21},{\"bucketMax\":21,\"count\":32},{\"bucketMax\":22,\"count\":782},{\"bucketMax\":25,\"count\":4},{\"bucketMax\":26,\"count\":19},{\"bucketMax\":27,\"count\":1},{\"bucketMax\":28,\"count\":51},{\"bucketMax\":29,\"count\":55},{\"bucketMax\":30,\"count\":1},{\"bucketMax\":31,\"count\":4},{\"bucketMax\":32,\"count\":4},{\"bucketMax\":33,\"count\":4},{\"bucketMax\":35,\"count\":6},{\"bucketMax\":36,\"count\":6},{\"bucketMax\":39,\"count\":2},{\"bucketMax\":40,\"count\":2},{\"bucketMax\":41,\"count\":6},{\"bucketMax\":42,\"count\":1},{\"bucketMax\":43,\"count\":10},{\"bucketMax\":47,\"count\":2},{\"bucketMax\":50,\"count\":1},{\"bucketMax\":54,\"count\":1},{\"bucketMax\":72,\"count\":1}]},\"Sign Function\":{\"cyclesExecutedBySolution\":[{\"bucketMax\":14,\"count\":3},{\"bucketMax\":18,\"count\":8},{\"bucketMax\":22,\"count\":1},{\"bucketMax\":23,\"count\":7},{\"bucketMax\":24,\"count\":218},{\"bucketMax\":25,\"count\":7},{\"bucketMax\":26,\"count\":92},{\"bucketMax\":27,\"count\":76},{\"bucketMax\":28,\"count\":82},{\"bucketMax\":29,\"count\":9},{\"bucketMax\":30,\"count\":31},{\"bucketMax\":31,\"count\":36},{\"bucketMax\":32,\"count\":7},{\"bucketMax\":33,\"count\":19},{\"bucketMax\":34,\"count\":12},{\"bucketMax\":35,\"count\":21},{\"bucketMax\":36,\"count\":4},{\"bucketMax\":37,\"count\":10},{\"bucketMax\":38,\"count\":13},{\"bucketMax\":39,\"count\":5},{\"bucketMax\":40,\"count\":9},{\"bucketMax\":41,\"count\":4},{\"bucketMax\":42,\"count\":3},{\"bucketMax\":43,\"count\":2},{\"bucketMax\":44,\"count\":4},{\"bucketMax\":45,\"count\":12},{\"bucketMax\":46,\"count\":3},{\"bucketMax\":47,\"count\":6},{\"bucketMax\":48,\"count\":2},{\"bucketMax\":49,\"count\":8},{\"bucketMax\":50,\"count\":1},{\"bucketMax\":51,\"count\":2},{\"bucketMax\":52,\"count\":4},{\"bucketMax\":53,\"count\":3},{\"bucketMax\":54,\"count\":1},{\"bucketMax\":55,\"count\":3},{\"bucketMax\":56,\"count\":2},{\"bucketMax\":58,\"count\":1},{\"bucketMax\":60,\"count\":1},{\"bucketMax\":62,\"count\":1},{\"bucketMax\":67,\"count\":1},{\"bucketMax\":72,\"count\":1},{\"bucketMax\":89,\"count\":1},{\"bucketMax\":92,\"count\":1}],\"memoryBytesAccessedBySolution\":[{\"bucketMax\":17,\"count\":4},{\"bucketMax\":19,\"count\":4},{\"bucketMax\":20,\"count\":3},{\"bucketMax\":21,\"count\":11},{\"bucketMax\":22,\"count\":8},{\"bucketMax\":23,\"count\":27},{\"bucketMax\":24,\"count\":46},{\"bucketMax\":25,\"count\":8},{\"bucketMax\":26,\"count\":13},{\"bucketMax\":27,\"count\":84},{\"bucketMax\":28,\"count\":28},{\"bucketMax\":29,\"count\":42},{\"bucketMax\":30,\"count\":147},{\"bucketMax\":31,\"count\":49},{\"bucketMax\":32,\"count\":8},{\"bucketMax\":33,\"count\":57},{\"bucketMax\":34,\"count\":30},{\"bucketMax\":35,\"count\":3},{\"bucketMax\":36,\"count\":31},{\"bucketMax\":37,\"count\":49},{\"bucketMax\":38,\"count\":6},{\"bucketMax\":39,\"count\":9},{\"bucketMax\":40,\"count\":19},{\"bucketMax\":41,\"count\":3},{\"bucketMax\":42,\"count\":6},{\"bucketMax\":43,\"count\":9},{\"bucketMax\":44,\"count\":3},{\"bucketMax\":45,\"count\":1},{\"bucketMax\":46,\"count\":9},{\"bucketMax\":48,\"count\":2},{\"bucketMax\":49,\"count\":7},{\"bucketMax\":50,\"count\":4},{\"bucketMax\":52,\"count\":1},{\"bucketMax\":53,\"count\":1},{\"bucketMax\":54,\"count\":1},{\"bucketMax\":55,\"count\":1},{\"bucketMax\":56,\"count\":1},{\"bucketMax\":59,\"count\":1},{\"bucketMax\":61,\"count\":1},{\"bucketMax\":67,\"count\":2},{\"bucketMax\":69,\"count\":1}]},\"Multiplication\":{\"cyclesExecutedBySolution\":[{\"bucketMax\":20,\"count\":1},{\"bucketMax\":45,\"count\":2},{\"bucketMax\":47,\"count\":1},{\"bucketMax\":49,\"count\":2},{\"bucketMax\":50,\"count\":2},{\"bucketMax\":51,\"count\":2},{\"bucketMax\":52,\"count\":1},{\"bucketMax\":53,\"count\":1},{\"bucketMax\":54,\"count\":1},{\"bucketMax\":56,\"count\":2},{\"bucketMax\":57,\"count\":3},{\"bucketMax\":58,\"count\":3},{\"bucketMax\":59,\"count\":2},{\"bucketMax\":60,\"count\":4},{\"bucketMax\":61,\"count\":4},{\"bucketMax\":62,\"count\":2},{\"bucketMax\":63,\"count\":13},{\"bucketMax\":64,\"count\":13},{\"bucketMax\":65,\"count\":12},{\"bucketMax\":66,\"count\":6},{\"bucketMax\":67,\"count\":12},{\"bucketMax\":68,\"count\":6},{\"bucketMax\":69,\"count\":4},{\"bucketMax\":70,\"count\":6},{\"bucketMax\":71,\"count\":15},{\"bucketMax\":72,\"count\":4},{\"bucketMax\":73,\"count\":11},{\"bucketMax\":74,\"count\":16},{\"bucketMax\":75,\"count\":15},{\"bucketMax\":76,\"count\":7},{\"bucketMax\":77,\"count\":13},{\"bucketMax\":78,\"count\":15},{\"bucketMax\":79,\"count\":11},{\"bucketMax\":80,\"count\":10},{\"bucketMax\":81,\"count\":15},{\"bucketMax\":82,\"count\":5},{\"bucketMax\":83,\"count\":9},{\"bucketMax\":84,\"count\":5},{\"bucketMax\":85,\"count\":10},{\"bucketMax\":86,\"count\":7},{\"bucketMax\":87,\"count\":15},{\"bucketMax\":88,\"count\":14},{\"bucketMax\":89,\"count\":10},{\"bucketMax\":90,\"count\":11},{\"bucketMax\":91,\"count\":17},{\"bucketMax\":92,\"count\":15},{\"bucketMax\":93,\"count\":13},{\"bucketMax\":94,\"count\":7},{\"bucketMax\":95,\"count\":22},{\"bucketMax\":96,\"count\":26},{\"bucketMax\":97,\"count\":5},{\"bucketMax\":98,\"count\":7},{\"bucketMax\":99,\"count\":3},{\"bucketMax\":100,\"count\":5},{\"bucketMax\":101,\"count\":6},{\"bucketMax\":103,\"count\":6},{\"bucketMax\":104,\"count\":3},{\"bucketMax\":105,\"count\":32},{\"bucketMax\":106,\"count\":3},{\"bucketMax\":107,\"count\":1},{\"bucketMax\":108,\"count\":5},{\"bucketMax\":109,\"count\":10},{\"bucketMax\":110,\"count\":10},{\"bucketMax\":111,\"count\":5},{\"bucketMax\":112,\"count\":5},{\"bucketMax\":113,\"count\":5},{\"bucketMax\":114,\"count\":2},{\"bucketMax\":115,\"count\":6},{\"bucketMax\":116,\"count\":2},{\"bucketMax\":117,\"count\":2},{\"bucketMax\":118,\"count\":5},{\"bucketMax\":119,\"count\":3},{\"bucketMax\":121,\"count\":1},{\"bucketMax\":122,\"count\":1},{\"bucketMax\":123,\"count\":2},{\"bucketMax\":130,\"count\":1},{\"bucketMax\":134,\"count\":1},{\"bucketMax\":136,\"count\":2},{\"bucketMax\":138,\"count\":1},{\"bucketMax\":150,\"count\":1},{\"bucketMax\":156,\"count\":1},{\"bucketMax\":194,\"count\":1}],\"memoryBytesAccessedBySolution\":[{\"bucketMax\":30,\"count\":1},{\"bucketMax\":31,\"count\":3},{\"bucketMax\":32,\"count\":1},{\"bucketMax\":33,\"count\":7},{\"bucketMax\":34,\"count\":1},{\"bucketMax\":35,\"count\":3},{\"bucketMax\":36,\"count\":26},{\"bucketMax\":37,\"count\":19},{\"bucketMax\":39,\"count\":8},{\"bucketMax\":40,\"count\":52},{\"bucketMax\":41,\"count\":14},{\"bucketMax\":42,\"count\":16},{\"bucketMax\":43,\"count\":33},{\"bucketMax\":44,\"count\":28},{\"bucketMax\":45,\"count\":15},{\"bucketMax\":46,\"count\":36},{\"bucketMax\":47,\"count\":67},{\"bucketMax\":48,\"count\":31},{\"bucketMax\":49,\"count\":25},{\"bucketMax\":50,\"count\":33},{\"bucketMax\":51,\"count\":21},{\"bucketMax\":52,\"count\":16},{\"bucketMax\":53,\"count\":14},{\"bucketMax\":54,\"count\":11},{\"bucketMax\":55,\"count\":9},{\"bucketMax\":56,\"count\":9},{\"bucketMax\":57,\"count\":10},{\"bucketMax\":58,\"count\":7},{\"bucketMax\":59,\"count\":7},{\"bucketMax\":60,\"count\":5},{\"bucketMax\":61,\"count\":2},{\"bucketMax\":62,\"count\":5},{\"bucketMax\":63,\"count\":2},{\"bucketMax\":64,\"count\":2},{\"bucketMax\":65,\"count\":4},{\"bucketMax\":67,\"count\":2},{\"bucketMax\":68,\"count\":1},{\"bucketMax\":69,\"count\":2},{\"bucketMax\":70,\"count\":1},{\"bucketMax\":71,\"count\":1},{\"bucketMax\":72,\"count\":3},{\"bucketMax\":73,\"count\":2},{\"bucketMax\":74,\"count\":2},{\"bucketMax\":75,\"count\":1},{\"bucketMax\":76,\"count\":1},{\"bucketMax\":78,\"count\":2},{\"bucketMax\":80,\"count\":2},{\"bucketMax\":81,\"count\":1},{\"bucketMax\":82,\"count\":1},{\"bucketMax\":85,\"count\":1},{\"bucketMax\":87,\"count\":1},{\"bucketMax\":88,\"count\":1},{\"bucketMax\":92,\"count\":1},{\"bucketMax\":117,\"count\":1},{\"bucketMax\":139,\"count\":1}]},\"Division\":{\"cyclesExecutedBySolution\":[{\"bucketMax\":68,\"count\":1},{\"bucketMax\":76,\"count\":3},{\"bucketMax\":77,\"count\":1},{\"bucketMax\":78,\"count\":33},{\"bucketMax\":79,\"count\":27},{\"bucketMax\":80,\"count\":3},{\"bucketMax\":81,\"count\":4},{\"bucketMax\":82,\"count\":5},{\"bucketMax\":83,\"count\":3},{\"bucketMax\":84,\"count\":1},{\"bucketMax\":85,\"count\":8},{\"bucketMax\":86,\"count\":45},{\"bucketMax\":87,\"count\":15},{\"bucketMax\":88,\"count\":1},{\"bucketMax\":89,\"count\":8},{\"bucketMax\":90,\"count\":10},{\"bucketMax\":91,\"count\":3},{\"bucketMax\":92,\"count\":8},{\"bucketMax\":93,\"count\":10},{\"bucketMax\":94,\"count\":4},{\"bucketMax\":96,\"count\":2},{\"bucketMax\":97,\"count\":15},{\"bucketMax\":98,\"count\":5},{\"bucketMax\":100,\"count\":7},{\"bucketMax\":101,\"count\":5},{\"bucketMax\":102,\"count\":6},{\"bucketMax\":103,\"count\":1},{\"bucketMax\":104,\"count\":5},{\"bucketMax\":105,\"count\":2},{\"bucketMax\":106,\"count\":2},{\"bucketMax\":107,\"count\":2},{\"bucketMax\":108,\"count\":4},{\"bucketMax\":109,\"count\":4},{\"bucketMax\":110,\"count\":5},{\"bucketMax\":111,\"count\":2},{\"bucketMax\":112,\"count\":4},{\"bucketMax\":113,\"count\":2},{\"bucketMax\":114,\"count\":7},{\"bucketMax\":115,\"count\":5},{\"bucketMax\":116,\"count\":5},{\"bucketMax\":117,\"count\":4},{\"bucketMax\":118,\"count\":5},{\"bucketMax\":119,\"count\":2},{\"bucketMax\":120,\"count\":1},{\"bucketMax\":121,\"count\":6},{\"bucketMax\":122,\"count\":6},{\"bucketMax\":123,\"count\":4},{\"bucketMax\":124,\"count\":2},{\"bucketMax\":125,\"count\":3},{\"bucketMax\":126,\"count\":4},{\"bucketMax\":127,\"count\":24},{\"bucketMax\":129,\"count\":3},{\"bucketMax\":130,\"count\":3},{\"bucketMax\":131,\"count\":2},{\"bucketMax\":132,\"count\":1},{\"bucketMax\":133,\"count\":3},{\"bucketMax\":134,\"count\":3},{\"bucketMax\":136,\"count\":1},{\"bucketMax\":137,\"count\":1},{\"bucketMax\":139,\"count\":3},{\"bucketMax\":140,\"count\":2},{\"bucketMax\":141,\"count\":1},{\"bucketMax\":142,\"count\":1},{\"bucketMax\":144,\"count\":1},{\"bucketMax\":145,\"count\":2},{\"bucketMax\":146,\"count\":2},{\"bucketMax\":148,\"count\":2},{\"bucketMax\":149,\"count\":1},{\"bucketMax\":150,\"count\":1},{\"bucketMax\":151,\"count\":1},{\"bucketMax\":152,\"count\":1},{\"bucketMax\":153,\"count\":1},{\"bucketMax\":160,\"count\":2},{\"bucketMax\":163,\"count\":1},{\"bucketMax\":164,\"count\":1},{\"bucketMax\":165,\"count\":1},{\"bucketMax\":169,\"count\":1},{\"bucketMax\":171,\"count\":1},{\"bucketMax\":177,\"count\":1},{\"bucketMax\":182,\"count\":1},{\"bucketMax\":186,\"count\":1},{\"bucketMax\":189,\"count\":1},{\"bucketMax\":190,\"count\":1},{\"bucketMax\":198,\"count\":1},{\"bucketMax\":199,\"count\":1},{\"bucketMax\":201,\"count\":1},{\"bucketMax\":203,\"count\":1},{\"bucketMax\":215,\"count\":1},{\"bucketMax\":219,\"count\":1},{\"bucketMax\":220,\"count\":1},{\"bucketMax\":223,\"count\":1},{\"bucketMax\":233,\"count\":1},{\"bucketMax\":252,\"count\":1},{\"bucketMax\":281,\"count\":1},{\"bucketMax\":283,\"count\":1},{\"bucketMax\":289,\"count\":1},{\"bucketMax\":317,\"count\":1},{\"bucketMax\":440,\"count\":1},{\"bucketMax\":473,\"count\":1}],\"memoryBytesAccessedBySolution\":[{\"bucketMax\":34,\"count\":2},{\"bucketMax\":36,\"count\":2},{\"bucketMax\":38,\"count\":2},{\"bucketMax\":39,\"count\":1},{\"bucketMax\":40,\"count\":1},{\"bucketMax\":41,\"count\":2},{\"bucketMax\":42,\"count\":21},{\"bucketMax\":43,\"count\":33},{\"bucketMax\":44,\"count\":1},{\"bucketMax\":45,\"count\":6},{\"bucketMax\":46,\"count\":29},{\"bucketMax\":47,\"count\":58},{\"bucketMax\":49,\"count\":6},{\"bucketMax\":50,\"count\":8},{\"bucketMax\":51,\"count\":10},{\"bucketMax\":52,\"count\":7},{\"bucketMax\":53,\"count\":11},{\"bucketMax\":54,\"count\":13},{\"bucketMax\":56,\"count\":6},{\"bucketMax\":57,\"count\":3},{\"bucketMax\":58,\"count\":2},{\"bucketMax\":59,\"count\":3},{\"bucketMax\":60,\"count\":4},{\"bucketMax\":61,\"count\":2},{\"bucketMax\":62,\"count\":6},{\"bucketMax\":63,\"count\":7},{\"bucketMax\":64,\"count\":4},{\"bucketMax\":65,\"count\":3},{\"bucketMax\":66,\"count\":3},{\"bucketMax\":67,\"count\":2},{\"bucketMax\":68,\"count\":6},{\"bucketMax\":69,\"count\":10},{\"bucketMax\":70,\"count\":3},{\"bucketMax\":71,\"count\":7},{\"bucketMax\":72,\"count\":11},{\"bucketMax\":73,\"count\":6},{\"bucketMax\":74,\"count\":4},{\"bucketMax\":75,\"count\":3},{\"bucketMax\":76,\"count\":5},{\"bucketMax\":77,\"count\":5},{\"bucketMax\":78,\"count\":6},{\"bucketMax\":79,\"count\":4},{\"bucketMax\":80,\"count\":23},{\"bucketMax\":81,\"count\":6},{\"bucketMax\":82,\"count\":3},{\"bucketMax\":83,\"count\":2},{\"bucketMax\":84,\"count\":2},{\"bucketMax\":85,\"count\":6},{\"bucketMax\":86,\"count\":3},{\"bucketMax\":87,\"count\":2},{\"bucketMax\":88,\"count\":1},{\"bucketMax\":89,\"count\":3},{\"bucketMax\":91,\"count\":3},{\"bucketMax\":92,\"count\":1},{\"bucketMax\":93,\"count\":3},{\"bucketMax\":95,\"count\":1},{\"bucketMax\":96,\"count\":1},{\"bucketMax\":97,\"count\":1},{\"bucketMax\":98,\"count\":2},{\"bucketMax\":99,\"count\":1},{\"bucketMax\":102,\"count\":1},{\"bucketMax\":103,\"count\":2},{\"bucketMax\":107,\"count\":1},{\"bucketMax\":108,\"count\":2},{\"bucketMax\":109,\"count\":1},{\"bucketMax\":114,\"count\":1},{\"bucketMax\":117,\"count\":1},{\"bucketMax\":121,\"count\":1},{\"bucketMax\":129,\"count\":1},{\"bucketMax\":130,\"count\":2},{\"bucketMax\":163,\"count\":1}]},\"Sequence Sum\":{\"cyclesExecutedBySolution\":[{\"bucketMax\":37,\"count\":1},{\"bucketMax\":43,\"count\":1},{\"bucketMax\":54,\"count\":1},{\"bucketMax\":76,\"count\":1},{\"bucketMax\":78,\"count\":3},{\"bucketMax\":79,\"count\":1},{\"bucketMax\":81,\"count\":1},{\"bucketMax\":82,\"count\":2},{\"bucketMax\":85,\"count\":101},{\"bucketMax\":86,\"count\":10},{\"bucketMax\":87,\"count\":6},{\"bucketMax\":88,\"count\":12},{\"bucketMax\":89,\"count\":9},{\"bucketMax\":90,\"count\":4},{\"bucketMax\":91,\"count\":50},{\"bucketMax\":92,\"count\":19},{\"bucketMax\":93,\"count\":27},{\"bucketMax\":95,\"count\":15},{\"bucketMax\":96,\"count\":8},{\"bucketMax\":97,\"count\":2},{\"bucketMax\":98,\"count\":6},{\"bucketMax\":99,\"count\":15},{\"bucketMax\":100,\"count\":8},{\"bucketMax\":101,\"count\":5},{\"bucketMax\":102,\"count\":2},{\"bucketMax\":103,\"count\":4},{\"bucketMax\":104,\"count\":2},{\"bucketMax\":105,\"count\":2},{\"bucketMax\":106,\"count\":2},{\"bucketMax\":107,\"count\":4},{\"bucketMax\":108,\"count\":1},{\"bucketMax\":109,\"count\":1},{\"bucketMax\":110,\"count\":1},{\"bucketMax\":111,\"count\":4},{\"bucketMax\":113,\"count\":5},{\"bucketMax\":114,\"count\":2},{\"bucketMax\":115,\"count\":3},{\"bucketMax\":116,\"count\":2},{\"bucketMax\":117,\"count\":6},{\"bucketMax\":121,\"count\":1},{\"bucketMax\":123,\"count\":1},{\"bucketMax\":124,\"count\":1},{\"bucketMax\":125,\"count\":2},{\"bucketMax\":127,\"count\":1},{\"bucketMax\":128,\"count\":5},{\"bucketMax\":129,\"count\":2},{\"bucketMax\":130,\"count\":1},{\"bucketMax\":132,\"count\":1},{\"bucketMax\":140,\"count\":1},{\"bucketMax\":150,\"count\":1},{\"bucketMax\":151,\"count\":1},{\"bucketMax\":162,\"count\":1},{\"bucketMax\":202,\"count\":1}],\"memoryBytesAccessedBySolution\":[{\"bucketMax\":19,\"count\":2},{\"bucketMax\":20,\"count\":1},{\"bucketMax\":21,\"count\":1},{\"bucketMax\":22,\"count\":2},{\"bucketMax\":23,\"count\":4},{\"bucketMax\":24,\"count\":11},{\"bucketMax\":25,\"count\":9},{\"bucketMax\":26,\"count\":124},{\"bucketMax\":27,\"count\":1},{\"bucketMax\":28,\"count\":2},{\"bucketMax\":29,\"count\":35},{\"bucketMax\":30,\"count\":21},{\"bucketMax\":32,\"count\":63},{\"bucketMax\":33,\"count\":18},{\"bucketMax\":34,\"count\":2},{\"bucketMax\":35,\"count\":21},{\"bucketMax\":36,\"count\":19},{\"bucketMax\":37,\"count\":4},{\"bucketMax\":38,\"count\":8},{\"bucketMax\":39,\"count\":8},{\"bucketMax\":41,\"count\":4},{\"bucketMax\":42,\"count\":6},{\"bucketMax\":43,\"count\":3},{\"bucketMax\":50,\"count\":1},{\"bucketMax\":56,\"count\":1}]},\"Sequence Cardinality\":{\"cyclesExecutedBySolution\":[{\"bucketMax\":15,\"count\":1},{\"bucketMax\":16,\"count\":1},{\"bucketMax\":24,\"count\":1},{\"bucketMax\":26,\"count\":10},{\"bucketMax\":27,\"count\":14},{\"bucketMax\":35,\"count\":3},{\"bucketMax\":42,\"count\":3},{\"bucketMax\":43,\"count\":1},{\"bucketMax\":47,\"count\":3},{\"bucketMax\":49,\"count\":3},{\"bucketMax\":50,\"count\":28},{\"bucketMax\":51,\"count\":10},{\"bucketMax\":54,\"count\":7},{\"bucketMax\":55,\"count\":91},{\"bucketMax\":56,\"count\":2},{\"bucketMax\":57,\"count\":1},{\"bucketMax\":58,\"count\":25},{\"bucketMax\":59,\"count\":21},{\"bucketMax\":61,\"count\":59},{\"bucketMax\":62,\"count\":7},{\"bucketMax\":63,\"count\":26},{\"bucketMax\":64,\"count\":1},{\"bucketMax\":65,\"count\":3},{\"bucketMax\":66,\"count\":3},{\"bucketMax\":67,\"count\":2},{\"bucketMax\":68,\"count\":1},{\"bucketMax\":69,\"count\":5},{\"bucketMax\":70,\"count\":5},{\"bucketMax\":71,\"count\":1},{\"bucketMax\":73,\"count\":2},{\"bucketMax\":74,\"count\":1},{\"bucketMax\":75,\"count\":1},{\"bucketMax\":79,\"count\":1},{\"bucketMax\":81,\"count\":4},{\"bucketMax\":83,\"count\":3},{\"bucketMax\":85,\"count\":1},{\"bucketMax\":86,\"count\":2},{\"bucketMax\":94,\"count\":1},{\"bucketMax\":98,\"count\":1},{\"bucketMax\":108,\"count\":1}],\"memoryBytesAccessedBySolution\":[{\"bucketMax\":14,\"count\":5},{\"bucketMax\":15,\"count\":5},{\"bucketMax\":16,\"count\":6},{\"bucketMax\":17,\"count\":10},{\"bucketMax\":19,\"count\":1},{\"bucketMax\":20,\"count\":2},{\"bucketMax\":21,\"count\":1},{\"bucketMax\":23,\"count\":6},{\"bucketMax\":24,\"count\":21},{\"bucketMax\":25,\"count\":5},{\"bucketMax\":26,\"count\":7},{\"bucketMax\":27,\"count\":173},{\"bucketMax\":28,\"count\":1},{\"bucketMax\":29,\"count\":1},{\"bucketMax\":30,\"count\":33},{\"bucketMax\":31,\"count\":6},{\"bucketMax\":32,\"count\":1},{\"bucketMax\":33,\"count\":45},{\"bucketMax\":34,\"count\":10},{\"bucketMax\":35,\"count\":1},{\"bucketMax\":36,\"count\":2},{\"bucketMax\":37,\"count\":5},{\"bucketMax\":39,\"count\":4},{\"bucketMax\":40,\"count\":2},{\"bucketMax\":41,\"count\":3},{\"bucketMax\":42,\"count\":1},{\"bucketMax\":43,\"count\":2},{\"bucketMax\":44,\"count\":1},{\"bucketMax\":50,\"count\":1}]},\"Number to Sequence\":{\"cyclesExecutedBySolution\":[{\"bucketMax\":36,\"count\":1},{\"bucketMax\":47,\"count\":1},{\"bucketMax\":48,\"count\":15},{\"bucketMax\":50,\"count\":1},{\"bucketMax\":51,\"count\":1},{\"bucketMax\":53,\"count\":2},{\"bucketMax\":54,\"count\":3},{\"bucketMax\":59,\"count\":30},{\"bucketMax\":60,\"count\":18},{\"bucketMax\":61,\"count\":2},{\"bucketMax\":64,\"count\":1},{\"bucketMax\":65,\"count\":5},{\"bucketMax\":66,\"count\":5},{\"bucketMax\":68,\"count\":2},{\"bucketMax\":69,\"count\":12},{\"bucketMax\":70,\"count\":3},{\"bucketMax\":71,\"count\":1},{\"bucketMax\":72,\"count\":21},{\"bucketMax\":73,\"count\":4},{\"bucketMax\":74,\"count\":2},{\"bucketMax\":76,\"count\":1},{\"bucketMax\":77,\"count\":62},{\"bucketMax\":78,\"count\":26},{\"bucketMax\":79,\"count\":13},{\"bucketMax\":80,\"count\":1},{\"bucketMax\":82,\"count\":5},{\"bucketMax\":83,\"count\":6},{\"bucketMax\":84,\"count\":8},{\"bucketMax\":85,\"count\":2},{\"bucketMax\":87,\"count\":3},{\"bucketMax\":88,\"count\":3},{\"bucketMax\":89,\"count\":7},{\"bucketMax\":90,\"count\":19},{\"bucketMax\":92,\"count\":1},{\"bucketMax\":94,\"count\":6},{\"bucketMax\":95,\"count\":11},{\"bucketMax\":96,\"count\":6},{\"bucketMax\":97,\"count\":1},{\"bucketMax\":99,\"count\":1},{\"bucketMax\":100,\"count\":6},{\"bucketMax\":101,\"count\":6},{\"bucketMax\":102,\"count\":4},{\"bucketMax\":104,\"count\":1},{\"bucketMax\":105,\"count\":1},{\"bucketMax\":106,\"count\":5},{\"bucketMax\":107,\"count\":2},{\"bucketMax\":108,\"count\":2},{\"bucketMax\":113,\"count\":1},{\"bucketMax\":117,\"count\":1},{\"bucketMax\":119,\"count\":3},{\"bucketMax\":120,\"count\":1},{\"bucketMax\":121,\"count\":1},{\"bucketMax\":124,\"count\":1},{\"bucketMax\":126,\"count\":1},{\"bucketMax\":130,\"count\":1}],\"memoryBytesAccessedBySolution\":[{\"bucketMax\":15,\"count\":4},{\"bucketMax\":16,\"count\":1},{\"bucketMax\":17,\"count\":6},{\"bucketMax\":18,\"count\":10},{\"bucketMax\":19,\"count\":18},{\"bucketMax\":20,\"count\":16},{\"bucketMax\":21,\"count\":3},{\"bucketMax\":22,\"count\":9},{\"bucketMax\":23,\"count\":70},{\"bucketMax\":24,\"count\":8},{\"bucketMax\":25,\"count\":8},{\"bucketMax\":26,\"count\":22},{\"bucketMax\":27,\"count\":14},{\"bucketMax\":28,\"count\":13},{\"bucketMax\":29,\"count\":18},{\"bucketMax\":30,\"count\":38},{\"bucketMax\":31,\"count\":38},{\"bucketMax\":32,\"count\":5},{\"bucketMax\":33,\"count\":11},{\"bucketMax\":34,\"count\":20},{\"bucketMax\":35,\"count\":5},{\"bucketMax\":37,\"count\":9},{\"bucketMax\":38,\"count\":1},{\"bucketMax\":39,\"count\":1},{\"bucketMax\":40,\"count\":2},{\"bucketMax\":41,\"count\":2},{\"bucketMax\":42,\"count\":1}]},\"Self-Modifying Code\":{\"cyclesExecutedBySolution\":[{\"bucketMax\":12,\"count\":33},{\"bucketMax\":46,\"count\":312}],\"memoryBytesAccessedBySolution\":[{\"bucketMax\":15,\"count\":345}]},\"Stack Memory\":{\"cyclesExecutedBySolution\":[{\"bucketMax\":3,\"count\":38},{\"bucketMax\":6,\"count\":9},{\"bucketMax\":19,\"count\":281}],\"memoryBytesAccessedBySolution\":[{\"bucketMax\":7,\"count\":12},{\"bucketMax\":8,\"count\":5},{\"bucketMax\":9,\"count\":3},{\"bucketMax\":10,\"count\":2},{\"bucketMax\":13,\"count\":16},{\"bucketMax\":20,\"count\":1},{\"bucketMax\":22,\"count\":3},{\"bucketMax\":23,\"count\":5},{\"bucketMax\":36,\"count\":279}]},\"Reverse Sequence\":{\"cyclesExecutedBySolution\":[{\"bucketMax\":46,\"count\":1},{\"bucketMax\":51,\"count\":1},{\"bucketMax\":57,\"count\":1},{\"bucketMax\":73,\"count\":1},{\"bucketMax\":96,\"count\":1},{\"bucketMax\":104,\"count\":2},{\"bucketMax\":115,\"count\":1},{\"bucketMax\":122,\"count\":1},{\"bucketMax\":128,\"count\":1},{\"bucketMax\":129,\"count\":3},{\"bucketMax\":131,\"count\":3},{\"bucketMax\":132,\"count\":2},{\"bucketMax\":134,\"count\":1},{\"bucketMax\":135,\"count\":1},{\"bucketMax\":137,\"count\":1},{\"bucketMax\":139,\"count\":1},{\"bucketMax\":140,\"count\":1},{\"bucketMax\":141,\"count\":1},{\"bucketMax\":145,\"count\":2},{\"bucketMax\":146,\"count\":1},{\"bucketMax\":147,\"count\":3},{\"bucketMax\":148,\"count\":4},{\"bucketMax\":151,\"count\":1},{\"bucketMax\":154,\"count\":2},{\"bucketMax\":156,\"count\":1},{\"bucketMax\":158,\"count\":1},{\"bucketMax\":159,\"count\":2},{\"bucketMax\":160,\"count\":1},{\"bucketMax\":164,\"count\":4},{\"bucketMax\":166,\"count\":1},{\"bucketMax\":167,\"count\":1},{\"bucketMax\":168,\"count\":1},{\"bucketMax\":171,\"count\":1},{\"bucketMax\":172,\"count\":1},{\"bucketMax\":173,\"count\":3},{\"bucketMax\":174,\"count\":1},{\"bucketMax\":175,\"count\":1},{\"bucketMax\":176,\"count\":1},{\"bucketMax\":177,\"count\":1},{\"bucketMax\":178,\"count\":2},{\"bucketMax\":179,\"count\":1},{\"bucketMax\":180,\"count\":3},{\"bucketMax\":183,\"count\":1},{\"bucketMax\":184,\"count\":1},{\"bucketMax\":185,\"count\":1},{\"bucketMax\":186,\"count\":1},{\"bucketMax\":187,\"count\":3},{\"bucketMax\":188,\"count\":2},{\"bucketMax\":189,\"count\":2},{\"bucketMax\":191,\"count\":3},{\"bucketMax\":192,\"count\":1},{\"bucketMax\":193,\"count\":3},{\"bucketMax\":194,\"count\":1},{\"bucketMax\":195,\"count\":2},{\"bucketMax\":198,\"count\":2},{\"bucketMax\":199,\"count\":4},{\"bucketMax\":201,\"count\":5},{\"bucketMax\":202,\"count\":1},{\"bucketMax\":203,\"count\":1},{\"bucketMax\":205,\"count\":2},{\"bucketMax\":206,\"count\":2},{\"bucketMax\":207,\"count\":2},{\"bucketMax\":208,\"count\":2},{\"bucketMax\":209,\"count\":1},{\"bucketMax\":210,\"count\":3},{\"bucketMax\":211,\"count\":1},{\"bucketMax\":212,\"count\":2},{\"bucketMax\":213,\"count\":2},{\"bucketMax\":215,\"count\":1},{\"bucketMax\":217,\"count\":1},{\"bucketMax\":218,\"count\":3},{\"bucketMax\":219,\"count\":2},{\"bucketMax\":220,\"count\":2},{\"bucketMax\":221,\"count\":1},{\"bucketMax\":223,\"count\":3},{\"bucketMax\":224,\"count\":1},{\"bucketMax\":225,\"count\":4},{\"bucketMax\":226,\"count\":2},{\"bucketMax\":229,\"count\":1},{\"bucketMax\":230,\"count\":2},{\"bucketMax\":231,\"count\":2},{\"bucketMax\":232,\"count\":4},{\"bucketMax\":233,\"count\":1},{\"bucketMax\":234,\"count\":4},{\"bucketMax\":235,\"count\":2},{\"bucketMax\":236,\"count\":1},{\"bucketMax\":237,\"count\":3},{\"bucketMax\":240,\"count\":1},{\"bucketMax\":241,\"count\":1},{\"bucketMax\":242,\"count\":1},{\"bucketMax\":244,\"count\":2},{\"bucketMax\":246,\"count\":1},{\"bucketMax\":247,\"count\":1},{\"bucketMax\":248,\"count\":1},{\"bucketMax\":253,\"count\":3},{\"bucketMax\":255,\"count\":3},{\"bucketMax\":256,\"count\":1},{\"bucketMax\":257,\"count\":1},{\"bucketMax\":258,\"count\":1},{\"bucketMax\":260,\"count\":1},{\"bucketMax\":262,\"count\":1},{\"bucketMax\":263,\"count\":1},{\"bucketMax\":264,\"count\":2},{\"bucketMax\":265,\"count\":1},{\"bucketMax\":266,\"count\":1},{\"bucketMax\":269,\"count\":2},{\"bucketMax\":271,\"count\":2},{\"bucketMax\":272,\"count\":1},{\"bucketMax\":273,\"count\":1},{\"bucketMax\":274,\"count\":2},{\"bucketMax\":275,\"count\":1},{\"bucketMax\":279,\"count\":3},{\"bucketMax\":283,\"count\":1},{\"bucketMax\":284,\"count\":1},{\"bucketMax\":286,\"count\":1},{\"bucketMax\":288,\"count\":1},{\"bucketMax\":289,\"count\":2},{\"bucketMax\":290,\"count\":1},{\"bucketMax\":294,\"count\":1},{\"bucketMax\":298,\"count\":1},{\"bucketMax\":299,\"count\":1},{\"bucketMax\":300,\"count\":1},{\"bucketMax\":301,\"count\":2},{\"bucketMax\":302,\"count\":1},{\"bucketMax\":304,\"count\":1},{\"bucketMax\":307,\"count\":2},{\"bucketMax\":311,\"count\":1},{\"bucketMax\":314,\"count\":1},{\"bucketMax\":336,\"count\":1},{\"bucketMax\":345,\"count\":1},{\"bucketMax\":349,\"count\":1},{\"bucketMax\":361,\"count\":1},{\"bucketMax\":365,\"count\":1},{\"bucketMax\":381,\"count\":1},{\"bucketMax\":401,\"count\":1},{\"bucketMax\":448,\"count\":1}],\"memoryBytesAccessedBySolution\":[{\"bucketMax\":47,\"count\":2},{\"bucketMax\":49,\"count\":2},{\"bucketMax\":51,\"count\":1},{\"bucketMax\":54,\"count\":1},{\"bucketMax\":57,\"count\":2},{\"bucketMax\":58,\"count\":6},{\"bucketMax\":59,\"count\":3},{\"bucketMax\":60,\"count\":1},{\"bucketMax\":61,\"count\":2},{\"bucketMax\":62,\"count\":4},{\"bucketMax\":63,\"count\":1},{\"bucketMax\":64,\"count\":3},{\"bucketMax\":65,\"count\":4},{\"bucketMax\":66,\"count\":1},{\"bucketMax\":68,\"count\":6},{\"bucketMax\":69,\"count\":1},{\"bucketMax\":70,\"count\":2},{\"bucketMax\":71,\"count\":3},{\"bucketMax\":72,\"count\":10},{\"bucketMax\":73,\"count\":5},{\"bucketMax\":74,\"count\":8},{\"bucketMax\":75,\"count\":5},{\"bucketMax\":76,\"count\":1},{\"bucketMax\":77,\"count\":10},{\"bucketMax\":78,\"count\":4},{\"bucketMax\":79,\"count\":2},{\"bucketMax\":80,\"count\":2},{\"bucketMax\":81,\"count\":4},{\"bucketMax\":82,\"count\":3},{\"bucketMax\":83,\"count\":5},{\"bucketMax\":84,\"count\":7},{\"bucketMax\":85,\"count\":1},{\"bucketMax\":86,\"count\":4},{\"bucketMax\":87,\"count\":6},{\"bucketMax\":88,\"count\":7},{\"bucketMax\":89,\"count\":5},{\"bucketMax\":90,\"count\":5},{\"bucketMax\":92,\"count\":3},{\"bucketMax\":93,\"count\":5},{\"bucketMax\":94,\"count\":4},{\"bucketMax\":95,\"count\":2},{\"bucketMax\":96,\"count\":5},{\"bucketMax\":97,\"count\":3},{\"bucketMax\":98,\"count\":2},{\"bucketMax\":99,\"count\":7},{\"bucketMax\":100,\"count\":1},{\"bucketMax\":101,\"count\":3},{\"bucketMax\":102,\"count\":3},{\"bucketMax\":103,\"count\":4},{\"bucketMax\":105,\"count\":5},{\"bucketMax\":106,\"count\":3},{\"bucketMax\":108,\"count\":1},{\"bucketMax\":109,\"count\":4},{\"bucketMax\":110,\"count\":1},{\"bucketMax\":111,\"count\":3},{\"bucketMax\":113,\"count\":3},{\"bucketMax\":114,\"count\":1},{\"bucketMax\":115,\"count\":1},{\"bucketMax\":116,\"count\":3},{\"bucketMax\":117,\"count\":2},{\"bucketMax\":118,\"count\":1},{\"bucketMax\":119,\"count\":1},{\"bucketMax\":121,\"count\":3},{\"bucketMax\":133,\"count\":1},{\"bucketMax\":134,\"count\":1},{\"bucketMax\":135,\"count\":1},{\"bucketMax\":137,\"count\":1},{\"bucketMax\":143,\"count\":1}]},\"Interleave\":{\"cyclesExecutedBySolution\":[{\"bucketMax\":47,\"count\":3},{\"bucketMax\":80,\"count\":1},{\"bucketMax\":101,\"count\":2},{\"bucketMax\":109,\"count\":1},{\"bucketMax\":111,\"count\":1},{\"bucketMax\":112,\"count\":1},{\"bucketMax\":114,\"count\":2},{\"bucketMax\":124,\"count\":4},{\"bucketMax\":126,\"count\":1},{\"bucketMax\":127,\"count\":1},{\"bucketMax\":129,\"count\":3},{\"bucketMax\":132,\"count\":1},{\"bucketMax\":137,\"count\":1},{\"bucketMax\":138,\"count\":1},{\"bucketMax\":139,\"count\":2},{\"bucketMax\":142,\"count\":1},{\"bucketMax\":145,\"count\":1},{\"bucketMax\":147,\"count\":1},{\"bucketMax\":149,\"count\":8},{\"bucketMax\":161,\"count\":1},{\"bucketMax\":163,\"count\":2},{\"bucketMax\":165,\"count\":1},{\"bucketMax\":166,\"count\":1},{\"bucketMax\":167,\"count\":1},{\"bucketMax\":170,\"count\":2},{\"bucketMax\":171,\"count\":1},{\"bucketMax\":173,\"count\":1},{\"bucketMax\":175,\"count\":1},{\"bucketMax\":177,\"count\":1},{\"bucketMax\":184,\"count\":1},{\"bucketMax\":185,\"count\":1},{\"bucketMax\":186,\"count\":1},{\"bucketMax\":191,\"count\":1},{\"bucketMax\":194,\"count\":1},{\"bucketMax\":195,\"count\":2},{\"bucketMax\":196,\"count\":1},{\"bucketMax\":197,\"count\":1},{\"bucketMax\":198,\"count\":2},{\"bucketMax\":203,\"count\":1},{\"bucketMax\":209,\"count\":1},{\"bucketMax\":212,\"count\":1},{\"bucketMax\":214,\"count\":1},{\"bucketMax\":216,\"count\":1},{\"bucketMax\":219,\"count\":1},{\"bucketMax\":222,\"count\":1},{\"bucketMax\":224,\"count\":1},{\"bucketMax\":228,\"count\":1},{\"bucketMax\":230,\"count\":1},{\"bucketMax\":231,\"count\":1},{\"bucketMax\":232,\"count\":2},{\"bucketMax\":233,\"count\":1},{\"bucketMax\":240,\"count\":2},{\"bucketMax\":247,\"count\":1},{\"bucketMax\":250,\"count\":1},{\"bucketMax\":251,\"count\":1},{\"bucketMax\":257,\"count\":1},{\"bucketMax\":260,\"count\":1},{\"bucketMax\":261,\"count\":1},{\"bucketMax\":264,\"count\":1},{\"bucketMax\":269,\"count\":1},{\"bucketMax\":271,\"count\":2},{\"bucketMax\":273,\"count\":1},{\"bucketMax\":274,\"count\":1},{\"bucketMax\":276,\"count\":1},{\"bucketMax\":282,\"count\":1},{\"bucketMax\":290,\"count\":1},{\"bucketMax\":292,\"count\":2},{\"bucketMax\":295,\"count\":1},{\"bucketMax\":297,\"count\":3},{\"bucketMax\":299,\"count\":1},{\"bucketMax\":300,\"count\":2},{\"bucketMax\":301,\"count\":1},{\"bucketMax\":305,\"count\":3},{\"bucketMax\":307,\"count\":1},{\"bucketMax\":309,\"count\":1},{\"bucketMax\":310,\"count\":1},{\"bucketMax\":311,\"count\":1},{\"bucketMax\":314,\"count\":1},{\"bucketMax\":315,\"count\":1},{\"bucketMax\":316,\"count\":2},{\"bucketMax\":319,\"count\":2},{\"bucketMax\":323,\"count\":2},{\"bucketMax\":324,\"count\":2},{\"bucketMax\":329,\"count\":3},{\"bucketMax\":330,\"count\":1},{\"bucketMax\":332,\"count\":1},{\"bucketMax\":335,\"count\":1},{\"bucketMax\":336,\"count\":2},{\"bucketMax\":337,\"count\":2},{\"bucketMax\":339,\"count\":1},{\"bucketMax\":344,\"count\":1},{\"bucketMax\":346,\"count\":2},{\"bucketMax\":347,\"count\":1},{\"bucketMax\":352,\"count\":1},{\"bucketMax\":356,\"count\":1},{\"bucketMax\":357,\"count\":1},{\"bucketMax\":360,\"count\":2},{\"bucketMax\":361,\"count\":1},{\"bucketMax\":367,\"count\":2},{\"bucketMax\":383,\"count\":1},{\"bucketMax\":391,\"count\":1},{\"bucketMax\":396,\"count\":1},{\"bucketMax\":398,\"count\":1},{\"bucketMax\":403,\"count\":1},{\"bucketMax\":407,\"count\":1},{\"bucketMax\":409,\"count\":1},{\"bucketMax\":411,\"count\":1},{\"bucketMax\":416,\"count\":1},{\"bucketMax\":419,\"count\":1},{\"bucketMax\":420,\"count\":1},{\"bucketMax\":433,\"count\":2},{\"bucketMax\":438,\"count\":1},{\"bucketMax\":440,\"count\":1},{\"bucketMax\":463,\"count\":1},{\"bucketMax\":466,\"count\":1},{\"bucketMax\":470,\"count\":1},{\"bucketMax\":532,\"count\":1},{\"bucketMax\":951,\"count\":1}],\"memoryBytesAccessedBySolution\":[{\"bucketMax\":41,\"count\":1},{\"bucketMax\":43,\"count\":3},{\"bucketMax\":44,\"count\":1},{\"bucketMax\":48,\"count\":1},{\"bucketMax\":49,\"count\":3},{\"bucketMax\":51,\"count\":3},{\"bucketMax\":55,\"count\":1},{\"bucketMax\":56,\"count\":2},{\"bucketMax\":57,\"count\":5},{\"bucketMax\":61,\"count\":2},{\"bucketMax\":62,\"count\":10},{\"bucketMax\":63,\"count\":1},{\"bucketMax\":67,\"count\":2},{\"bucketMax\":69,\"count\":1},{\"bucketMax\":73,\"count\":2},{\"bucketMax\":74,\"count\":1},{\"bucketMax\":75,\"count\":2},{\"bucketMax\":76,\"count\":1},{\"bucketMax\":77,\"count\":1},{\"bucketMax\":78,\"count\":1},{\"bucketMax\":80,\"count\":2},{\"bucketMax\":81,\"count\":1},{\"bucketMax\":82,\"count\":1},{\"bucketMax\":84,\"count\":1},{\"bucketMax\":86,\"count\":2},{\"bucketMax\":87,\"count\":2},{\"bucketMax\":89,\"count\":3},{\"bucketMax\":90,\"count\":1},{\"bucketMax\":91,\"count\":2},{\"bucketMax\":92,\"count\":3},{\"bucketMax\":93,\"count\":6},{\"bucketMax\":94,\"count\":1},{\"bucketMax\":95,\"count\":1},{\"bucketMax\":96,\"count\":3},{\"bucketMax\":97,\"count\":2},{\"bucketMax\":98,\"count\":4},{\"bucketMax\":100,\"count\":4},{\"bucketMax\":101,\"count\":4},{\"bucketMax\":102,\"count\":3},{\"bucketMax\":104,\"count\":1},{\"bucketMax\":105,\"count\":2},{\"bucketMax\":108,\"count\":1},{\"bucketMax\":110,\"count\":1},{\"bucketMax\":111,\"count\":1},{\"bucketMax\":112,\"count\":1},{\"bucketMax\":114,\"count\":2},{\"bucketMax\":115,\"count\":2},{\"bucketMax\":116,\"count\":1},{\"bucketMax\":119,\"count\":4},{\"bucketMax\":120,\"count\":1},{\"bucketMax\":121,\"count\":1},{\"bucketMax\":122,\"count\":1},{\"bucketMax\":123,\"count\":2},{\"bucketMax\":124,\"count\":4},{\"bucketMax\":125,\"count\":2},{\"bucketMax\":126,\"count\":3},{\"bucketMax\":127,\"count\":1},{\"bucketMax\":128,\"count\":2},{\"bucketMax\":129,\"count\":1},{\"bucketMax\":130,\"count\":1},{\"bucketMax\":134,\"count\":4},{\"bucketMax\":136,\"count\":4},{\"bucketMax\":138,\"count\":1},{\"bucketMax\":140,\"count\":1},{\"bucketMax\":142,\"count\":1},{\"bucketMax\":147,\"count\":1},{\"bucketMax\":148,\"count\":1},{\"bucketMax\":150,\"count\":1},{\"bucketMax\":151,\"count\":2},{\"bucketMax\":152,\"count\":2},{\"bucketMax\":153,\"count\":2},{\"bucketMax\":156,\"count\":1},{\"bucketMax\":161,\"count\":1},{\"bucketMax\":163,\"count\":1},{\"bucketMax\":164,\"count\":1},{\"bucketMax\":166,\"count\":1},{\"bucketMax\":175,\"count\":1},{\"bucketMax\":179,\"count\":1},{\"bucketMax\":182,\"count\":1},{\"bucketMax\":184,\"count\":1},{\"bucketMax\":189,\"count\":1},{\"bucketMax\":190,\"count\":1},{\"bucketMax\":197,\"count\":1},{\"bucketMax\":204,\"count\":1},{\"bucketMax\":205,\"count\":1},{\"bucketMax\":231,\"count\":1}]},\"Indicator Function\":{\"cyclesExecutedBySolution\":[{\"bucketMax\":85,\"count\":1},{\"bucketMax\":91,\"count\":1},{\"bucketMax\":101,\"count\":1},{\"bucketMax\":114,\"count\":1},{\"bucketMax\":129,\"count\":1},{\"bucketMax\":143,\"count\":1},{\"bucketMax\":144,\"count\":1},{\"bucketMax\":145,\"count\":2},{\"bucketMax\":147,\"count\":1},{\"bucketMax\":150,\"count\":1},{\"bucketMax\":153,\"count\":1},{\"bucketMax\":160,\"count\":1},{\"bucketMax\":163,\"count\":1},{\"bucketMax\":169,\"count\":1},{\"bucketMax\":176,\"count\":2},{\"bucketMax\":177,\"count\":1},{\"bucketMax\":179,\"count\":2},{\"bucketMax\":180,\"count\":1},{\"bucketMax\":182,\"count\":2},{\"bucketMax\":183,\"count\":1},{\"bucketMax\":189,\"count\":1},{\"bucketMax\":192,\"count\":1},{\"bucketMax\":196,\"count\":1},{\"bucketMax\":197,\"count\":3},{\"bucketMax\":200,\"count\":2},{\"bucketMax\":203,\"count\":1},{\"bucketMax\":208,\"count\":2},{\"bucketMax\":209,\"count\":1},{\"bucketMax\":210,\"count\":2},{\"bucketMax\":211,\"count\":1},{\"bucketMax\":212,\"count\":1},{\"bucketMax\":214,\"count\":1},{\"bucketMax\":217,\"count\":1},{\"bucketMax\":218,\"count\":1},{\"bucketMax\":219,\"count\":1},{\"bucketMax\":222,\"count\":1},{\"bucketMax\":223,\"count\":3},{\"bucketMax\":227,\"count\":2},{\"bucketMax\":230,\"count\":1},{\"bucketMax\":239,\"count\":2},{\"bucketMax\":240,\"count\":1},{\"bucketMax\":241,\"count\":1},{\"bucketMax\":247,\"count\":1},{\"bucketMax\":248,\"count\":2},{\"bucketMax\":257,\"count\":1},{\"bucketMax\":258,\"count\":1},{\"bucketMax\":261,\"count\":1},{\"bucketMax\":266,\"count\":1},{\"bucketMax\":267,\"count\":1},{\"bucketMax\":272,\"count\":1},{\"bucketMax\":275,\"count\":1},{\"bucketMax\":276,\"count\":1},{\"bucketMax\":279,\"count\":1},{\"bucketMax\":280,\"count\":2},{\"bucketMax\":286,\"count\":1},{\"bucketMax\":289,\"count\":1},{\"bucketMax\":293,\"count\":1},{\"bucketMax\":305,\"count\":1},{\"bucketMax\":316,\"count\":1},{\"bucketMax\":322,\"count\":2},{\"bucketMax\":327,\"count\":1},{\"bucketMax\":338,\"count\":1},{\"bucketMax\":344,\"count\":1},{\"bucketMax\":346,\"count\":1},{\"bucketMax\":347,\"count\":2},{\"bucketMax\":349,\"count\":1},{\"bucketMax\":351,\"count\":2},{\"bucketMax\":378,\"count\":1},{\"bucketMax\":381,\"count\":1},{\"bucketMax\":391,\"count\":1},{\"bucketMax\":400,\"count\":1},{\"bucketMax\":406,\"count\":1},{\"bucketMax\":408,\"count\":1},{\"bucketMax\":409,\"count\":1},{\"bucketMax\":415,\"count\":1},{\"bucketMax\":466,\"count\":1},{\"bucketMax\":486,\"count\":1},{\"bucketMax\":490,\"count\":1},{\"bucketMax\":512,\"count\":1},{\"bucketMax\":514,\"count\":1},{\"bucketMax\":533,\"count\":1},{\"bucketMax\":587,\"count\":1},{\"bucketMax\":613,\"count\":1},{\"bucketMax\":699,\"count\":1},{\"bucketMax\":805,\"count\":1},{\"bucketMax\":829,\"count\":1},{\"bucketMax\":1079,\"count\":1},{\"bucketMax\":1220,\"count\":1}],\"memoryBytesAccessedBySolution\":[{\"bucketMax\":47,\"count\":1},{\"bucketMax\":65,\"count\":1},{\"bucketMax\":67,\"count\":1},{\"bucketMax\":69,\"count\":1},{\"bucketMax\":70,\"count\":2},{\"bucketMax\":75,\"count\":1},{\"bucketMax\":84,\"count\":1},{\"bucketMax\":85,\"count\":1},{\"bucketMax\":88,\"count\":2},{\"bucketMax\":93,\"count\":1},{\"bucketMax\":95,\"count\":1},{\"bucketMax\":96,\"count\":1},{\"bucketMax\":97,\"count\":1},{\"bucketMax\":98,\"count\":1},{\"bucketMax\":99,\"count\":1},{\"bucketMax\":106,\"count\":2},{\"bucketMax\":110,\"count\":1},{\"bucketMax\":111,\"count\":1},{\"bucketMax\":112,\"count\":1},{\"bucketMax\":113,\"count\":2},{\"bucketMax\":114,\"count\":2},{\"bucketMax\":115,\"count\":3},{\"bucketMax\":117,\"count\":2},{\"bucketMax\":119,\"count\":3},{\"bucketMax\":120,\"count\":3},{\"bucketMax\":121,\"count\":1},{\"bucketMax\":123,\"count\":1},{\"bucketMax\":124,\"count\":1},{\"bucketMax\":125,\"count\":1},{\"bucketMax\":126,\"count\":2},{\"bucketMax\":128,\"count\":2},{\"bucketMax\":129,\"count\":3},{\"bucketMax\":131,\"count\":1},{\"bucketMax\":132,\"count\":4},{\"bucketMax\":133,\"count\":1},{\"bucketMax\":134,\"count\":1},{\"bucketMax\":136,\"count\":3},{\"bucketMax\":137,\"count\":1},{\"bucketMax\":140,\"count\":1},{\"bucketMax\":141,\"count\":1},{\"bucketMax\":143,\"count\":1},{\"bucketMax\":144,\"count\":1},{\"bucketMax\":145,\"count\":1},{\"bucketMax\":146,\"count\":1},{\"bucketMax\":148,\"count\":1},{\"bucketMax\":150,\"count\":1},{\"bucketMax\":151,\"count\":1},{\"bucketMax\":153,\"count\":1},{\"bucketMax\":154,\"count\":1},{\"bucketMax\":158,\"count\":1},{\"bucketMax\":159,\"count\":1},{\"bucketMax\":160,\"count\":1},{\"bucketMax\":162,\"count\":3},{\"bucketMax\":163,\"count\":1},{\"bucketMax\":166,\"count\":2},{\"bucketMax\":169,\"count\":1},{\"bucketMax\":174,\"count\":1},{\"bucketMax\":175,\"count\":1},{\"bucketMax\":176,\"count\":1},{\"bucketMax\":177,\"count\":2},{\"bucketMax\":181,\"count\":1},{\"bucketMax\":183,\"count\":2},{\"bucketMax\":185,\"count\":1},{\"bucketMax\":190,\"count\":1},{\"bucketMax\":191,\"count\":2},{\"bucketMax\":192,\"count\":1},{\"bucketMax\":194,\"count\":1},{\"bucketMax\":195,\"count\":1},{\"bucketMax\":196,\"count\":1},{\"bucketMax\":206,\"count\":1},{\"bucketMax\":207,\"count\":1},{\"bucketMax\":208,\"count\":1},{\"bucketMax\":209,\"count\":1},{\"bucketMax\":213,\"count\":1},{\"bucketMax\":214,\"count\":1},{\"bucketMax\":225,\"count\":2},{\"bucketMax\":236,\"count\":1},{\"bucketMax\":251,\"count\":1}]},\"Sort\":{\"cyclesExecutedBySolution\":[{\"bucketMax\":254,\"count\":1},{\"bucketMax\":293,\"count\":1},{\"bucketMax\":294,\"count\":1},{\"bucketMax\":305,\"count\":1},{\"bucketMax\":344,\"count\":1},{\"bucketMax\":358,\"count\":1},{\"bucketMax\":412,\"count\":1},{\"bucketMax\":418,\"count\":2},{\"bucketMax\":421,\"count\":1},{\"bucketMax\":436,\"count\":1},{\"bucketMax\":457,\"count\":1},{\"bucketMax\":458,\"count\":1},{\"bucketMax\":477,\"count\":1},{\"bucketMax\":481,\"count\":1},{\"bucketMax\":494,\"count\":1},{\"bucketMax\":496,\"count\":1},{\"bucketMax\":509,\"count\":1},{\"bucketMax\":513,\"count\":1},{\"bucketMax\":534,\"count\":1},{\"bucketMax\":535,\"count\":1},{\"bucketMax\":538,\"count\":1},{\"bucketMax\":556,\"count\":1},{\"bucketMax\":626,\"count\":1},{\"bucketMax\":632,\"count\":1},{\"bucketMax\":652,\"count\":1},{\"bucketMax\":656,\"count\":1},{\"bucketMax\":673,\"count\":1},{\"bucketMax\":679,\"count\":1},{\"bucketMax\":686,\"count\":1},{\"bucketMax\":687,\"count\":1},{\"bucketMax\":722,\"count\":1},{\"bucketMax\":748,\"count\":1},{\"bucketMax\":757,\"count\":1},{\"bucketMax\":777,\"count\":1},{\"bucketMax\":778,\"count\":1},{\"bucketMax\":809,\"count\":1},{\"bucketMax\":826,\"count\":1},{\"bucketMax\":829,\"count\":2},{\"bucketMax\":852,\"count\":1},{\"bucketMax\":855,\"count\":1},{\"bucketMax\":886,\"count\":1},{\"bucketMax\":960,\"count\":1},{\"bucketMax\":1027,\"count\":1},{\"bucketMax\":1113,\"count\":1},{\"bucketMax\":1121,\"count\":1},{\"bucketMax\":1144,\"count\":1},{\"bucketMax\":1146,\"count\":1},{\"bucketMax\":1159,\"count\":1},{\"bucketMax\":1174,\"count\":1},{\"bucketMax\":1175,\"count\":1},{\"bucketMax\":1202,\"count\":1},{\"bucketMax\":1237,\"count\":1},{\"bucketMax\":1425,\"count\":1},{\"bucketMax\":1503,\"count\":1},{\"bucketMax\":1639,\"count\":1},{\"bucketMax\":1822,\"count\":1},{\"bucketMax\":1951,\"count\":1},{\"bucketMax\":2005,\"count\":1},{\"bucketMax\":2197,\"count\":1},{\"bucketMax\":2250,\"count\":1},{\"bucketMax\":2333,\"count\":1},{\"bucketMax\":2357,\"count\":1},{\"bucketMax\":2518,\"count\":1},{\"bucketMax\":2587,\"count\":1},{\"bucketMax\":2828,\"count\":1},{\"bucketMax\":3025,\"count\":1},{\"bucketMax\":3205,\"count\":1}],\"memoryBytesAccessedBySolution\":[{\"bucketMax\":78,\"count\":1},{\"bucketMax\":79,\"count\":1},{\"bucketMax\":94,\"count\":1},{\"bucketMax\":95,\"count\":1},{\"bucketMax\":98,\"count\":2},{\"bucketMax\":104,\"count\":1},{\"bucketMax\":105,\"count\":1},{\"bucketMax\":106,\"count\":1},{\"bucketMax\":111,\"count\":1},{\"bucketMax\":112,\"count\":1},{\"bucketMax\":117,\"count\":1},{\"bucketMax\":119,\"count\":1},{\"bucketMax\":123,\"count\":1},{\"bucketMax\":130,\"count\":1},{\"bucketMax\":132,\"count\":1},{\"bucketMax\":134,\"count\":1},{\"bucketMax\":135,\"count\":1},{\"bucketMax\":138,\"count\":1},{\"bucketMax\":142,\"count\":1},{\"bucketMax\":143,\"count\":1},{\"bucketMax\":144,\"count\":1},{\"bucketMax\":150,\"count\":1},{\"bucketMax\":155,\"count\":1},{\"bucketMax\":157,\"count\":1},{\"bucketMax\":162,\"count\":1},{\"bucketMax\":164,\"count\":1},{\"bucketMax\":165,\"count\":1},{\"bucketMax\":167,\"count\":1},{\"bucketMax\":169,\"count\":1},{\"bucketMax\":171,\"count\":2},{\"bucketMax\":173,\"count\":1},{\"bucketMax\":176,\"count\":2},{\"bucketMax\":178,\"count\":1},{\"bucketMax\":179,\"count\":1},{\"bucketMax\":180,\"count\":1},{\"bucketMax\":181,\"count\":1},{\"bucketMax\":182,\"count\":1},{\"bucketMax\":186,\"count\":2},{\"bucketMax\":191,\"count\":1},{\"bucketMax\":192,\"count\":1},{\"bucketMax\":196,\"count\":1},{\"bucketMax\":197,\"count\":1},{\"bucketMax\":200,\"count\":3},{\"bucketMax\":211,\"count\":1},{\"bucketMax\":212,\"count\":2},{\"bucketMax\":213,\"count\":2},{\"bucketMax\":215,\"count\":1},{\"bucketMax\":223,\"count\":1},{\"bucketMax\":225,\"count\":1},{\"bucketMax\":226,\"count\":1},{\"bucketMax\":227,\"count\":1},{\"bucketMax\":229,\"count\":1},{\"bucketMax\":232,\"count\":1},{\"bucketMax\":233,\"count\":1},{\"bucketMax\":236,\"count\":1},{\"bucketMax\":240,\"count\":1},{\"bucketMax\":241,\"count\":1},{\"bucketMax\":242,\"count\":1},{\"bucketMax\":246,\"count\":1},{\"bucketMax\":250,\"count\":2}]},\"Mode\":{\"cyclesExecutedBySolution\":[{\"bucketMax\":267,\"count\":1},{\"bucketMax\":285,\"count\":1},{\"bucketMax\":324,\"count\":1},{\"bucketMax\":336,\"count\":1},{\"bucketMax\":348,\"count\":1},{\"bucketMax\":357,\"count\":1},{\"bucketMax\":372,\"count\":1},{\"bucketMax\":389,\"count\":1},{\"bucketMax\":405,\"count\":1},{\"bucketMax\":429,\"count\":1},{\"bucketMax\":457,\"count\":1},{\"bucketMax\":459,\"count\":1},{\"bucketMax\":661,\"count\":1},{\"bucketMax\":694,\"count\":1},{\"bucketMax\":726,\"count\":1},{\"bucketMax\":730,\"count\":1},{\"bucketMax\":771,\"count\":1},{\"bucketMax\":782,\"count\":1},{\"bucketMax\":789,\"count\":1},{\"bucketMax\":814,\"count\":1},{\"bucketMax\":850,\"count\":1},{\"bucketMax\":868,\"count\":1},{\"bucketMax\":891,\"count\":1},{\"bucketMax\":930,\"count\":1},{\"bucketMax\":948,\"count\":1},{\"bucketMax\":1101,\"count\":1},{\"bucketMax\":1127,\"count\":1},{\"bucketMax\":1166,\"count\":1},{\"bucketMax\":1192,\"count\":1},{\"bucketMax\":1315,\"count\":1},{\"bucketMax\":1457,\"count\":1},{\"bucketMax\":1821,\"count\":1},{\"bucketMax\":2020,\"count\":1},{\"bucketMax\":2058,\"count\":1},{\"bucketMax\":2615,\"count\":1},{\"bucketMax\":2672,\"count\":1},{\"bucketMax\":2713,\"count\":1},{\"bucketMax\":2867,\"count\":1},{\"bucketMax\":2893,\"count\":1},{\"bucketMax\":2900,\"count\":1},{\"bucketMax\":2916,\"count\":1},{\"bucketMax\":2989,\"count\":1},{\"bucketMax\":3203,\"count\":1},{\"bucketMax\":3540,\"count\":1},{\"bucketMax\":3680,\"count\":1},{\"bucketMax\":3714,\"count\":1},{\"bucketMax\":3791,\"count\":1},{\"bucketMax\":4051,\"count\":1},{\"bucketMax\":4211,\"count\":1},{\"bucketMax\":5798,\"count\":1}],\"memoryBytesAccessedBySolution\":[{\"bucketMax\":78,\"count\":1},{\"bucketMax\":100,\"count\":2},{\"bucketMax\":107,\"count\":1},{\"bucketMax\":115,\"count\":1},{\"bucketMax\":123,\"count\":1},{\"bucketMax\":128,\"count\":1},{\"bucketMax\":133,\"count\":1},{\"bucketMax\":136,\"count\":1},{\"bucketMax\":139,\"count\":1},{\"bucketMax\":140,\"count\":1},{\"bucketMax\":143,\"count\":1},{\"bucketMax\":147,\"count\":1},{\"bucketMax\":153,\"count\":1},{\"bucketMax\":155,\"count\":1},{\"bucketMax\":173,\"count\":1},{\"bucketMax\":186,\"count\":1},{\"bucketMax\":192,\"count\":1},{\"bucketMax\":193,\"count\":1},{\"bucketMax\":194,\"count\":2},{\"bucketMax\":195,\"count\":1},{\"bucketMax\":197,\"count\":2},{\"bucketMax\":205,\"count\":1},{\"bucketMax\":208,\"count\":1},{\"bucketMax\":209,\"count\":1},{\"bucketMax\":211,\"count\":1},{\"bucketMax\":216,\"count\":1},{\"bucketMax\":217,\"count\":1},{\"bucketMax\":218,\"count\":1},{\"bucketMax\":220,\"count\":1},{\"bucketMax\":222,\"count\":1},{\"bucketMax\":223,\"count\":1},{\"bucketMax\":232,\"count\":2},{\"bucketMax\":234,\"count\":1},{\"bucketMax\":235,\"count\":1},{\"bucketMax\":238,\"count\":1},{\"bucketMax\":240,\"count\":2},{\"bucketMax\":243,\"count\":1},{\"bucketMax\":244,\"count\":3},{\"bucketMax\":247,\"count\":1},{\"bucketMax\":250,\"count\":1},{\"bucketMax\":251,\"count\":2},{\"bucketMax\":253,\"count\":1}]},\"Characters\":{\"cyclesExecutedBySolution\":[{\"bucketMax\":2,\"count\":63}],\"memoryBytesAccessedBySolution\":[{\"bucketMax\":7,\"count\":17},{\"bucketMax\":8,\"count\":1},{\"bucketMax\":9,\"count\":45}]},\"Decimal Digits\":{\"cyclesExecutedBySolution\":[{\"bucketMax\":6,\"count\":8},{\"bucketMax\":11,\"count\":54},{\"bucketMax\":17,\"count\":1}],\"memoryBytesAccessedBySolution\":[{\"bucketMax\":12,\"count\":6},{\"bucketMax\":13,\"count\":1},{\"bucketMax\":14,\"count\":9},{\"bucketMax\":15,\"count\":5},{\"bucketMax\":16,\"count\":41},{\"bucketMax\":23,\"count\":1}]},\"Uppercase\":{\"cyclesExecutedBySolution\":[{\"bucketMax\":14,\"count\":1},{\"bucketMax\":20,\"count\":3},{\"bucketMax\":39,\"count\":5},{\"bucketMax\":41,\"count\":1},{\"bucketMax\":44,\"count\":1},{\"bucketMax\":49,\"count\":3},{\"bucketMax\":50,\"count\":10},{\"bucketMax\":51,\"count\":3},{\"bucketMax\":52,\"count\":1},{\"bucketMax\":53,\"count\":2},{\"bucketMax\":54,\"count\":2},{\"bucketMax\":55,\"count\":4},{\"bucketMax\":56,\"count\":2},{\"bucketMax\":60,\"count\":6},{\"bucketMax\":61,\"count\":4},{\"bucketMax\":64,\"count\":1},{\"bucketMax\":65,\"count\":1},{\"bucketMax\":66,\"count\":4},{\"bucketMax\":67,\"count\":2},{\"bucketMax\":68,\"count\":1},{\"bucketMax\":71,\"count\":1},{\"bucketMax\":73,\"count\":1},{\"bucketMax\":74,\"count\":2},{\"bucketMax\":75,\"count\":1},{\"bucketMax\":81,\"count\":1}],\"memoryBytesAccessedBySolution\":[{\"bucketMax\":17,\"count\":1},{\"bucketMax\":18,\"count\":3},{\"bucketMax\":21,\"count\":1},{\"bucketMax\":27,\"count\":1},{\"bucketMax\":28,\"count\":4},{\"bucketMax\":30,\"count\":1},{\"bucketMax\":31,\"count\":13},{\"bucketMax\":32,\"count\":1},{\"bucketMax\":33,\"count\":1},{\"bucketMax\":34,\"count\":7},{\"bucketMax\":35,\"count\":2},{\"bucketMax\":36,\"count\":2},{\"bucketMax\":37,\"count\":7},{\"bucketMax\":38,\"count\":2},{\"bucketMax\":40,\"count\":1},{\"bucketMax\":41,\"count\":4},{\"bucketMax\":42,\"count\":3},{\"bucketMax\":43,\"count\":1},{\"bucketMax\":44,\"count\":3},{\"bucketMax\":45,\"count\":1},{\"bucketMax\":46,\"count\":1},{\"bucketMax\":47,\"count\":2},{\"bucketMax\":50,\"count\":1},{\"bucketMax\":51,\"count\":1}]},\"Strings\":{\"cyclesExecutedBySolution\":[{\"bucketMax\":14,\"count\":13},{\"bucketMax\":27,\"count\":4},{\"bucketMax\":40,\"count\":47}],\"memoryBytesAccessedBySolution\":[{\"bucketMax\":20,\"count\":2},{\"bucketMax\":21,\"count\":8},{\"bucketMax\":23,\"count\":1},{\"bucketMax\":24,\"count\":2},{\"bucketMax\":25,\"count\":4},{\"bucketMax\":26,\"count\":47}]},\"Tokenizer\":{\"cyclesExecutedBySolution\":[{\"bucketMax\":90,\"count\":1},{\"bucketMax\":113,\"count\":1},{\"bucketMax\":114,\"count\":1},{\"bucketMax\":181,\"count\":1},{\"bucketMax\":182,\"count\":10},{\"bucketMax\":183,\"count\":4},{\"bucketMax\":189,\"count\":2},{\"bucketMax\":190,\"count\":1},{\"bucketMax\":219,\"count\":4},{\"bucketMax\":220,\"count\":1},{\"bucketMax\":225,\"count\":3},{\"bucketMax\":226,\"count\":6},{\"bucketMax\":227,\"count\":6},{\"bucketMax\":228,\"count\":2},{\"bucketMax\":234,\"count\":1},{\"bucketMax\":235,\"count\":1},{\"bucketMax\":241,\"count\":2},{\"bucketMax\":245,\"count\":1},{\"bucketMax\":252,\"count\":1},{\"bucketMax\":256,\"count\":1},{\"bucketMax\":265,\"count\":1},{\"bucketMax\":269,\"count\":1},{\"bucketMax\":270,\"count\":1},{\"bucketMax\":271,\"count\":2},{\"bucketMax\":273,\"count\":1},{\"bucketMax\":294,\"count\":1},{\"bucketMax\":404,\"count\":1},{\"bucketMax\":528,\"count\":1},{\"bucketMax\":580,\"count\":1},{\"bucketMax\":586,\"count\":1},{\"bucketMax\":831,\"count\":1}],\"memoryBytesAccessedBySolution\":[{\"bucketMax\":18,\"count\":4},{\"bucketMax\":21,\"count\":1},{\"bucketMax\":22,\"count\":2},{\"bucketMax\":23,\"count\":5},{\"bucketMax\":24,\"count\":2},{\"bucketMax\":26,\"count\":6},{\"bucketMax\":27,\"count\":7},{\"bucketMax\":28,\"count\":2},{\"bucketMax\":29,\"count\":5},{\"bucketMax\":30,\"count\":4},{\"bucketMax\":31,\"count\":2},{\"bucketMax\":32,\"count\":3},{\"bucketMax\":33,\"count\":2},{\"bucketMax\":35,\"count\":1},{\"bucketMax\":36,\"count\":5},{\"bucketMax\":37,\"count\":1},{\"bucketMax\":39,\"count\":2},{\"bucketMax\":40,\"count\":2},{\"bucketMax\":43,\"count\":2},{\"bucketMax\":92,\"count\":1},{\"bucketMax\":94,\"count\":1},{\"bucketMax\":101,\"count\":1},{\"bucketMax\":123,\"count\":1}]},\"Parse Decimal\":{\"cyclesExecutedBySolution\":[{\"bucketMax\":13,\"count\":1},{\"bucketMax\":29,\"count\":2},{\"bucketMax\":33,\"count\":1},{\"bucketMax\":43,\"count\":1},{\"bucketMax\":48,\"count\":1},{\"bucketMax\":49,\"count\":1},{\"bucketMax\":53,\"count\":1},{\"bucketMax\":56,\"count\":1},{\"bucketMax\":57,\"count\":1},{\"bucketMax\":59,\"count\":1},{\"bucketMax\":64,\"count\":1},{\"bucketMax\":65,\"count\":3},{\"bucketMax\":67,\"count\":1},{\"bucketMax\":68,\"count\":1},{\"bucketMax\":73,\"count\":2},{\"bucketMax\":76,\"count\":1},{\"bucketMax\":79,\"count\":1},{\"bucketMax\":80,\"count\":1},{\"bucketMax\":81,\"count\":1},{\"bucketMax\":84,\"count\":3},{\"bucketMax\":87,\"count\":1},{\"bucketMax\":88,\"count\":1},{\"bucketMax\":90,\"count\":1},{\"bucketMax\":91,\"count\":1},{\"bucketMax\":92,\"count\":1},{\"bucketMax\":94,\"count\":2},{\"bucketMax\":96,\"count\":1},{\"bucketMax\":97,\"count\":1},{\"bucketMax\":98,\"count\":1},{\"bucketMax\":101,\"count\":2},{\"bucketMax\":106,\"count\":2},{\"bucketMax\":128,\"count\":1},{\"bucketMax\":129,\"count\":1},{\"bucketMax\":133,\"count\":1},{\"bucketMax\":134,\"count\":1},{\"bucketMax\":138,\"count\":1},{\"bucketMax\":146,\"count\":1},{\"bucketMax\":174,\"count\":1},{\"bucketMax\":204,\"count\":1},{\"bucketMax\":223,\"count\":1},{\"bucketMax\":279,\"count\":1}],\"memoryBytesAccessedBySolution\":[{\"bucketMax\":32,\"count\":1},{\"bucketMax\":33,\"count\":1},{\"bucketMax\":34,\"count\":1},{\"bucketMax\":39,\"count\":1},{\"bucketMax\":41,\"count\":1},{\"bucketMax\":45,\"count\":3},{\"bucketMax\":47,\"count\":1},{\"bucketMax\":48,\"count\":3},{\"bucketMax\":50,\"count\":1},{\"bucketMax\":51,\"count\":4},{\"bucketMax\":52,\"count\":4},{\"bucketMax\":53,\"count\":1},{\"bucketMax\":54,\"count\":1},{\"bucketMax\":55,\"count\":2},{\"bucketMax\":56,\"count\":1},{\"bucketMax\":59,\"count\":1},{\"bucketMax\":60,\"count\":1},{\"bucketMax\":61,\"count\":1},{\"bucketMax\":63,\"count\":3},{\"bucketMax\":65,\"count\":1},{\"bucketMax\":66,\"count\":2},{\"bucketMax\":67,\"count\":4},{\"bucketMax\":68,\"count\":1},{\"bucketMax\":69,\"count\":3},{\"bucketMax\":72,\"count\":1},{\"bucketMax\":73,\"count\":1},{\"bucketMax\":77,\"count\":1},{\"bucketMax\":80,\"count\":1},{\"bucketMax\":88,\"count\":1},{\"bucketMax\":90,\"count\":1},{\"bucketMax\":111,\"count\":1},{\"bucketMax\":129,\"count\":1},{\"bucketMax\":143,\"count\":1}]},\"Print Decimal\":{\"cyclesExecutedBySolution\":[{\"bucketMax\":24,\"count\":1},{\"bucketMax\":43,\"count\":1},{\"bucketMax\":44,\"count\":1},{\"bucketMax\":46,\"count\":1},{\"bucketMax\":47,\"count\":3},{\"bucketMax\":51,\"count\":1},{\"bucketMax\":52,\"count\":1},{\"bucketMax\":55,\"count\":1},{\"bucketMax\":60,\"count\":4},{\"bucketMax\":64,\"count\":1},{\"bucketMax\":65,\"count\":1},{\"bucketMax\":67,\"count\":1},{\"bucketMax\":68,\"count\":1},{\"bucketMax\":70,\"count\":1},{\"bucketMax\":73,\"count\":1},{\"bucketMax\":78,\"count\":1},{\"bucketMax\":80,\"count\":1},{\"bucketMax\":82,\"count\":1},{\"bucketMax\":83,\"count\":2},{\"bucketMax\":86,\"count\":1},{\"bucketMax\":91,\"count\":1},{\"bucketMax\":96,\"count\":1},{\"bucketMax\":97,\"count\":1},{\"bucketMax\":98,\"count\":1},{\"bucketMax\":99,\"count\":1},{\"bucketMax\":100,\"count\":1},{\"bucketMax\":104,\"count\":1},{\"bucketMax\":108,\"count\":1},{\"bucketMax\":110,\"count\":1},{\"bucketMax\":112,\"count\":1},{\"bucketMax\":113,\"count\":1},{\"bucketMax\":121,\"count\":1},{\"bucketMax\":122,\"count\":1},{\"bucketMax\":123,\"count\":1},{\"bucketMax\":124,\"count\":1},{\"bucketMax\":129,\"count\":1},{\"bucketMax\":148,\"count\":1},{\"bucketMax\":149,\"count\":1},{\"bucketMax\":166,\"count\":1},{\"bucketMax\":172,\"count\":1},{\"bucketMax\":185,\"count\":1},{\"bucketMax\":253,\"count\":1},{\"bucketMax\":260,\"count\":1},{\"bucketMax\":264,\"count\":1},{\"bucketMax\":314,\"count\":1}],\"memoryBytesAccessedBySolution\":[{\"bucketMax\":34,\"count\":1},{\"bucketMax\":37,\"count\":1},{\"bucketMax\":43,\"count\":1},{\"bucketMax\":44,\"count\":2},{\"bucketMax\":47,\"count\":1},{\"bucketMax\":49,\"count\":1},{\"bucketMax\":52,\"count\":1},{\"bucketMax\":54,\"count\":2},{\"bucketMax\":56,\"count\":1},{\"bucketMax\":59,\"count\":1},{\"bucketMax\":65,\"count\":4},{\"bucketMax\":66,\"count\":3},{\"bucketMax\":70,\"count\":1},{\"bucketMax\":72,\"count\":1},{\"bucketMax\":73,\"count\":1},{\"bucketMax\":77,\"count\":1},{\"bucketMax\":79,\"count\":1},{\"bucketMax\":80,\"count\":2},{\"bucketMax\":83,\"count\":2},{\"bucketMax\":85,\"count\":2},{\"bucketMax\":87,\"count\":1},{\"bucketMax\":90,\"count\":1},{\"bucketMax\":100,\"count\":2},{\"bucketMax\":103,\"count\":1},{\"bucketMax\":105,\"count\":1},{\"bucketMax\":107,\"count\":1},{\"bucketMax\":113,\"count\":1},{\"bucketMax\":117,\"count\":2},{\"bucketMax\":119,\"count\":1},{\"bucketMax\":120,\"count\":1},{\"bucketMax\":123,\"count\":1},{\"bucketMax\":124,\"count\":1},{\"bucketMax\":132,\"count\":1},{\"bucketMax\":133,\"count\":1},{\"bucketMax\":135,\"count\":1},{\"bucketMax\":141,\"count\":1},{\"bucketMax\":154,\"count\":1},{\"bucketMax\":186,\"count\":1},{\"bucketMax\":221,\"count\":1}]},\"Calculator\":{\"cyclesExecutedBySolution\":[{\"bucketMax\":98,\"count\":1},{\"bucketMax\":123,\"count\":1},{\"bucketMax\":141,\"count\":1},{\"bucketMax\":142,\"count\":2},{\"bucketMax\":147,\"count\":1},{\"bucketMax\":153,\"count\":1},{\"bucketMax\":160,\"count\":1},{\"bucketMax\":168,\"count\":1},{\"bucketMax\":169,\"count\":1},{\"bucketMax\":179,\"count\":1},{\"bucketMax\":183,\"count\":1},{\"bucketMax\":194,\"count\":1},{\"bucketMax\":196,\"count\":1},{\"bucketMax\":199,\"count\":1},{\"bucketMax\":205,\"count\":1},{\"bucketMax\":206,\"count\":1},{\"bucketMax\":211,\"count\":1},{\"bucketMax\":212,\"count\":1},{\"bucketMax\":216,\"count\":1},{\"bucketMax\":217,\"count\":1},{\"bucketMax\":229,\"count\":1},{\"bucketMax\":231,\"count\":1},{\"bucketMax\":232,\"count\":1},{\"bucketMax\":236,\"count\":1},{\"bucketMax\":244,\"count\":1},{\"bucketMax\":250,\"count\":1},{\"bucketMax\":255,\"count\":1},{\"bucketMax\":266,\"count\":1},{\"bucketMax\":272,\"count\":1},{\"bucketMax\":276,\"count\":1},{\"bucketMax\":282,\"count\":1},{\"bucketMax\":292,\"count\":1},{\"bucketMax\":295,\"count\":1},{\"bucketMax\":310,\"count\":1},{\"bucketMax\":311,\"count\":1},{\"bucketMax\":344,\"count\":1},{\"bucketMax\":354,\"count\":1},{\"bucketMax\":355,\"count\":1},{\"bucketMax\":365,\"count\":1},{\"bucketMax\":378,\"count\":1},{\"bucketMax\":414,\"count\":1},{\"bucketMax\":418,\"count\":1},{\"bucketMax\":437,\"count\":1},{\"bucketMax\":503,\"count\":1},{\"bucketMax\":554,\"count\":1},{\"bucketMax\":606,\"count\":1},{\"bucketMax\":682,\"count\":1}],\"memoryBytesAccessedBySolution\":[{\"bucketMax\":78,\"count\":2},{\"bucketMax\":106,\"count\":2},{\"bucketMax\":108,\"count\":1},{\"bucketMax\":112,\"count\":2},{\"bucketMax\":113,\"count\":1},{\"bucketMax\":114,\"count\":1},{\"bucketMax\":125,\"count\":1},{\"bucketMax\":126,\"count\":1},{\"bucketMax\":132,\"count\":1},{\"bucketMax\":136,\"count\":1},{\"bucketMax\":138,\"count\":1},{\"bucketMax\":145,\"count\":1},{\"bucketMax\":146,\"count\":1},{\"bucketMax\":147,\"count\":1},{\"bucketMax\":149,\"count\":1},{\"bucketMax\":152,\"count\":1},{\"bucketMax\":157,\"count\":1},{\"bucketMax\":159,\"count\":1},{\"bucketMax\":161,\"count\":2},{\"bucketMax\":163,\"count\":1},{\"bucketMax\":166,\"count\":1},{\"bucketMax\":168,\"count\":1},{\"bucketMax\":169,\"count\":1},{\"bucketMax\":175,\"count\":1},{\"bucketMax\":180,\"count\":2},{\"bucketMax\":184,\"count\":2},{\"bucketMax\":187,\"count\":1},{\"bucketMax\":189,\"count\":1},{\"bucketMax\":192,\"count\":1},{\"bucketMax\":195,\"count\":1},{\"bucketMax\":196,\"count\":1},{\"bucketMax\":203,\"count\":1},{\"bucketMax\":214,\"count\":1},{\"bucketMax\":217,\"count\":2},{\"bucketMax\":220,\"count\":1},{\"bucketMax\":221,\"count\":1},{\"bucketMax\":222,\"count\":1},{\"bucketMax\":225,\"count\":1},{\"bucketMax\":227,\"count\":1},{\"bucketMax\":243,\"count\":1}]},\"Multi-Line Strings\":{\"cyclesExecutedBySolution\":[{\"bucketMax\":24,\"count\":5},{\"bucketMax\":71,\"count\":1},{\"bucketMax\":116,\"count\":7},{\"bucketMax\":117,\"count\":5},{\"bucketMax\":121,\"count\":1},{\"bucketMax\":140,\"count\":4},{\"bucketMax\":142,\"count\":3},{\"bucketMax\":143,\"count\":5},{\"bucketMax\":145,\"count\":1},{\"bucketMax\":146,\"count\":1},{\"bucketMax\":150,\"count\":1},{\"bucketMax\":159,\"count\":1},{\"bucketMax\":161,\"count\":1},{\"bucketMax\":162,\"count\":1},{\"bucketMax\":167,\"count\":2},{\"bucketMax\":169,\"count\":1},{\"bucketMax\":171,\"count\":1},{\"bucketMax\":182,\"count\":1},{\"bucketMax\":188,\"count\":1},{\"bucketMax\":234,\"count\":1},{\"bucketMax\":250,\"count\":1},{\"bucketMax\":354,\"count\":1},{\"bucketMax\":359,\"count\":1},{\"bucketMax\":387,\"count\":1}],\"memoryBytesAccessedBySolution\":[{\"bucketMax\":18,\"count\":3},{\"bucketMax\":20,\"count\":1},{\"bucketMax\":21,\"count\":2},{\"bucketMax\":22,\"count\":3},{\"bucketMax\":23,\"count\":3},{\"bucketMax\":24,\"count\":2},{\"bucketMax\":26,\"count\":6},{\"bucketMax\":27,\"count\":6},{\"bucketMax\":28,\"count\":1},{\"bucketMax\":29,\"count\":4},{\"bucketMax\":30,\"count\":2},{\"bucketMax\":32,\"count\":1},{\"bucketMax\":33,\"count\":3},{\"bucketMax\":34,\"count\":2},{\"bucketMax\":35,\"count\":1},{\"bucketMax\":36,\"count\":1},{\"bucketMax\":38,\"count\":1},{\"bucketMax\":40,\"count\":2},{\"bucketMax\":48,\"count\":1},{\"bucketMax\":94,\"count\":2},{\"bucketMax\":98,\"count\":1}]},\"Parse Data Directives\":{\"cyclesExecutedBySolution\":[{\"bucketMax\":55,\"count\":1},{\"bucketMax\":65,\"count\":1},{\"bucketMax\":69,\"count\":1},{\"bucketMax\":73,\"count\":1},{\"bucketMax\":76,\"count\":1},{\"bucketMax\":81,\"count\":1},{\"bucketMax\":82,\"count\":1},{\"bucketMax\":83,\"count\":1},{\"bucketMax\":87,\"count\":1},{\"bucketMax\":93,\"count\":1},{\"bucketMax\":99,\"count\":1},{\"bucketMax\":101,\"count\":1},{\"bucketMax\":104,\"count\":2},{\"bucketMax\":113,\"count\":1},{\"bucketMax\":116,\"count\":1},{\"bucketMax\":117,\"count\":1},{\"bucketMax\":118,\"count\":1},{\"bucketMax\":119,\"count\":2},{\"bucketMax\":121,\"count\":1},{\"bucketMax\":124,\"count\":2},{\"bucketMax\":126,\"count\":2},{\"bucketMax\":132,\"count\":1},{\"bucketMax\":143,\"count\":1},{\"bucketMax\":147,\"count\":1},{\"bucketMax\":163,\"count\":1},{\"bucketMax\":165,\"count\":1},{\"bucketMax\":170,\"count\":1},{\"bucketMax\":171,\"count\":1},{\"bucketMax\":179,\"count\":1},{\"bucketMax\":190,\"count\":1},{\"bucketMax\":193,\"count\":1},{\"bucketMax\":194,\"count\":1},{\"bucketMax\":209,\"count\":1},{\"bucketMax\":216,\"count\":1},{\"bucketMax\":242,\"count\":1},{\"bucketMax\":256,\"count\":1},{\"bucketMax\":293,\"count\":1},{\"bucketMax\":343,\"count\":1},{\"bucketMax\":363,\"count\":1},{\"bucketMax\":555,\"count\":1}],\"memoryBytesAccessedBySolution\":[{\"bucketMax\":50,\"count\":1},{\"bucketMax\":55,\"count\":1},{\"bucketMax\":63,\"count\":1},{\"bucketMax\":89,\"count\":1},{\"bucketMax\":95,\"count\":1},{\"bucketMax\":96,\"count\":2},{\"bucketMax\":104,\"count\":2},{\"bucketMax\":105,\"count\":2},{\"bucketMax\":107,\"count\":1},{\"bucketMax\":110,\"count\":1},{\"bucketMax\":111,\"count\":1},{\"bucketMax\":112,\"count\":3},{\"bucketMax\":113,\"count\":3},{\"bucketMax\":115,\"count\":1},{\"bucketMax\":116,\"count\":1},{\"bucketMax\":120,\"count\":1},{\"bucketMax\":121,\"count\":2},{\"bucketMax\":122,\"count\":1},{\"bucketMax\":129,\"count\":1},{\"bucketMax\":131,\"count\":1},{\"bucketMax\":136,\"count\":2},{\"bucketMax\":139,\"count\":1},{\"bucketMax\":148,\"count\":1},{\"bucketMax\":149,\"count\":1},{\"bucketMax\":150,\"count\":1},{\"bucketMax\":152,\"count\":1},{\"bucketMax\":155,\"count\":2},{\"bucketMax\":163,\"count\":1},{\"bucketMax\":164,\"count\":1},{\"bucketMax\":167,\"count\":1},{\"bucketMax\":168,\"count\":1},{\"bucketMax\":172,\"count\":2},{\"bucketMax\":183,\"count\":1}]},\"Parse Subleq Instructions\":{\"cyclesExecutedBySolution\":[{\"bucketMax\":168,\"count\":1},{\"bucketMax\":170,\"count\":1},{\"bucketMax\":175,\"count\":1},{\"bucketMax\":193,\"count\":1},{\"bucketMax\":213,\"count\":1},{\"bucketMax\":223,\"count\":1},{\"bucketMax\":240,\"count\":1},{\"bucketMax\":251,\"count\":1},{\"bucketMax\":253,\"count\":1},{\"bucketMax\":255,\"count\":1},{\"bucketMax\":262,\"count\":1},{\"bucketMax\":263,\"count\":1},{\"bucketMax\":272,\"count\":1},{\"bucketMax\":279,\"count\":1},{\"bucketMax\":287,\"count\":1},{\"bucketMax\":297,\"count\":1},{\"bucketMax\":300,\"count\":1},{\"bucketMax\":304,\"count\":1},{\"bucketMax\":311,\"count\":1},{\"bucketMax\":332,\"count\":1},{\"bucketMax\":342,\"count\":1},{\"bucketMax\":360,\"count\":1},{\"bucketMax\":362,\"count\":1},{\"bucketMax\":380,\"count\":1},{\"bucketMax\":397,\"count\":1},{\"bucketMax\":438,\"count\":1},{\"bucketMax\":440,\"count\":1},{\"bucketMax\":451,\"count\":1},{\"bucketMax\":488,\"count\":1},{\"bucketMax\":490,\"count\":1},{\"bucketMax\":499,\"count\":1},{\"bucketMax\":527,\"count\":1},{\"bucketMax\":572,\"count\":1},{\"bucketMax\":730,\"count\":1},{\"bucketMax\":778,\"count\":1},{\"bucketMax\":951,\"count\":1},{\"bucketMax\":965,\"count\":1},{\"bucketMax\":1014,\"count\":1},{\"bucketMax\":1272,\"count\":1}],\"memoryBytesAccessedBySolution\":[{\"bucketMax\":44,\"count\":1},{\"bucketMax\":59,\"count\":1},{\"bucketMax\":68,\"count\":1},{\"bucketMax\":69,\"count\":1},{\"bucketMax\":71,\"count\":1},{\"bucketMax\":72,\"count\":1},{\"bucketMax\":79,\"count\":1},{\"bucketMax\":85,\"count\":1},{\"bucketMax\":87,\"count\":1},{\"bucketMax\":93,\"count\":1},{\"bucketMax\":94,\"count\":1},{\"bucketMax\":95,\"count\":2},{\"bucketMax\":98,\"count\":2},{\"bucketMax\":100,\"count\":1},{\"bucketMax\":101,\"count\":1},{\"bucketMax\":102,\"count\":1},{\"bucketMax\":104,\"count\":1},{\"bucketMax\":106,\"count\":2},{\"bucketMax\":108,\"count\":1},{\"bucketMax\":116,\"count\":1},{\"bucketMax\":117,\"count\":1},{\"bucketMax\":119,\"count\":1},{\"bucketMax\":120,\"count\":1},{\"bucketMax\":125,\"count\":1},{\"bucketMax\":126,\"count\":1},{\"bucketMax\":127,\"count\":1},{\"bucketMax\":131,\"count\":1},{\"bucketMax\":132,\"count\":1},{\"bucketMax\":133,\"count\":1},{\"bucketMax\":138,\"count\":1},{\"bucketMax\":140,\"count\":1},{\"bucketMax\":152,\"count\":1},{\"bucketMax\":158,\"count\":1},{\"bucketMax\":168,\"count\":1},{\"bucketMax\":178,\"count\":1},{\"bucketMax\":198,\"count\":1}]},\"Self-Hosting\":{\"cyclesExecutedBySolution\":[{\"bucketMax\":200,\"count\":1},{\"bucketMax\":283,\"count\":1},{\"bucketMax\":332,\"count\":1},{\"bucketMax\":387,\"count\":2},{\"bucketMax\":400,\"count\":1},{\"bucketMax\":492,\"count\":1},{\"bucketMax\":523,\"count\":1},{\"bucketMax\":545,\"count\":1},{\"bucketMax\":546,\"count\":1},{\"bucketMax\":560,\"count\":1},{\"bucketMax\":587,\"count\":1},{\"bucketMax\":618,\"count\":1},{\"bucketMax\":629,\"count\":1},{\"bucketMax\":675,\"count\":1},{\"bucketMax\":678,\"count\":1},{\"bucketMax\":682,\"count\":1},{\"bucketMax\":721,\"count\":1},{\"bucketMax\":758,\"count\":1},{\"bucketMax\":760,\"count\":1},{\"bucketMax\":802,\"count\":1},{\"bucketMax\":819,\"count\":1},{\"bucketMax\":827,\"count\":1},{\"bucketMax\":831,\"count\":1},{\"bucketMax\":848,\"count\":2},{\"bucketMax\":893,\"count\":1},{\"bucketMax\":918,\"count\":1},{\"bucketMax\":942,\"count\":1},{\"bucketMax\":948,\"count\":1},{\"bucketMax\":1033,\"count\":1},{\"bucketMax\":1325,\"count\":1},{\"bucketMax\":1561,\"count\":1},{\"bucketMax\":1625,\"count\":1},{\"bucketMax\":1635,\"count\":1},{\"bucketMax\":1897,\"count\":1}],\"memoryBytesAccessedBySolution\":[{\"bucketMax\":99,\"count\":1},{\"bucketMax\":126,\"count\":1},{\"bucketMax\":137,\"count\":1},{\"bucketMax\":138,\"count\":1},{\"bucketMax\":163,\"count\":1},{\"bucketMax\":172,\"count\":1},{\"bucketMax\":173,\"count\":1},{\"bucketMax\":174,\"count\":1},{\"bucketMax\":175,\"count\":1},{\"bucketMax\":178,\"count\":1},{\"bucketMax\":180,\"count\":1},{\"bucketMax\":188,\"count\":1},{\"bucketMax\":190,\"count\":1},{\"bucketMax\":193,\"count\":2},{\"bucketMax\":199,\"count\":1},{\"bucketMax\":202,\"count\":2},{\"bucketMax\":203,\"count\":1},{\"bucketMax\":204,\"count\":1},{\"bucketMax\":206,\"count\":2},{\"bucketMax\":207,\"count\":1},{\"bucketMax\":209,\"count\":1},{\"bucketMax\":213,\"count\":1},{\"bucketMax\":220,\"count\":1},{\"bucketMax\":223,\"count\":1},{\"bucketMax\":224,\"count\":2},{\"bucketMax\":227,\"count\":1},{\"bucketMax\":234,\"count\":1},{\"bucketMax\":239,\"count\":1},{\"bucketMax\":246,\"count\":1},{\"bucketMax\":253,\"count\":1},{\"bucketMax\":256,\"count\":1}]},\"Self-Hosting Part 2\":{\"cyclesExecutedBySolution\":[{\"bucketMax\":989,\"count\":3},{\"bucketMax\":1048,\"count\":1},{\"bucketMax\":1054,\"count\":1},{\"bucketMax\":1243,\"count\":1},{\"bucketMax\":1276,\"count\":1},{\"bucketMax\":1454,\"count\":1},{\"bucketMax\":1475,\"count\":1},{\"bucketMax\":1534,\"count\":1},{\"bucketMax\":1535,\"count\":1},{\"bucketMax\":1547,\"count\":1},{\"bucketMax\":1678,\"count\":1},{\"bucketMax\":1747,\"count\":1},{\"bucketMax\":1757,\"count\":1},{\"bucketMax\":1845,\"count\":1},{\"bucketMax\":1877,\"count\":1},{\"bucketMax\":2141,\"count\":1},{\"bucketMax\":2167,\"count\":1},{\"bucketMax\":2232,\"count\":1},{\"bucketMax\":2433,\"count\":1},{\"bucketMax\":2775,\"count\":1}],\"memoryBytesAccessedBySolution\":[{\"bucketMax\":154,\"count\":1},{\"bucketMax\":179,\"count\":1},{\"bucketMax\":182,\"count\":1},{\"bucketMax\":186,\"count\":1},{\"bucketMax\":206,\"count\":1},{\"bucketMax\":211,\"count\":1},{\"bucketMax\":216,\"count\":1},{\"bucketMax\":218,\"count\":1},{\"bucketMax\":220,\"count\":2},{\"bucketMax\":225,\"count\":1},{\"bucketMax\":226,\"count\":1},{\"bucketMax\":228,\"count\":3},{\"bucketMax\":232,\"count\":1},{\"bucketMax\":234,\"count\":1},{\"bucketMax\":239,\"count\":1},{\"bucketMax\":244,\"count\":1},{\"bucketMax\":245,\"count\":1},{\"bucketMax\":252,\"count\":2}]}}};\n\nconst webStatsCache: Sic1StatsCache = {\"userStats\":{\"solutionsByUser\":[{\"bucketMax\":1,\"count\":1227},{\"bucketMax\":2,\"count\":813},{\"bucketMax\":3,\"count\":382},{\"bucketMax\":4,\"count\":247},{\"bucketMax\":5,\"count\":261},{\"bucketMax\":6,\"count\":207},{\"bucketMax\":7,\"count\":163},{\"bucketMax\":8,\"count\":21},{\"bucketMax\":9,\"count\":12},{\"bucketMax\":10,\"count\":9},{\"bucketMax\":11,\"count\":8},{\"bucketMax\":12,\"count\":23},{\"bucketMax\":13,\"count\":107},{\"bucketMax\":14,\"count\":44},{\"bucketMax\":15,\"count\":59},{\"bucketMax\":16,\"count\":32},{\"bucketMax\":17,\"count\":10},{\"bucketMax\":18,\"count\":1},{\"bucketMax\":20,\"count\":1},{\"bucketMax\":22,\"count\":3},{\"bucketMax\":23,\"count\":3},{\"bucketMax\":24,\"count\":5},{\"bucketMax\":25,\"count\":2},{\"bucketMax\":26,\"count\":1},{\"bucketMax\":27,\"count\":1},{\"bucketMax\":28,\"count\":1},{\"bucketMax\":29,\"count\":10},{\"bucketMax\":30,\"count\":6},{\"bucketMax\":31,\"count\":6}],\"userSolvedCount\":0},\"puzzleStats\":{\"Subleq Instruction and Output\":{\"cyclesExecutedBySolution\":[{\"bucketMax\":1,\"count\":3629},{\"bucketMax\":2,\"count\":4},{\"bucketMax\":3,\"count\":1},{\"bucketMax\":4,\"count\":1},{\"bucketMax\":5,\"count\":1}],\"memoryBytesAccessedBySolution\":[{\"bucketMax\":4,\"count\":54},{\"bucketMax\":5,\"count\":3575},{\"bucketMax\":8,\"count\":3},{\"bucketMax\":10,\"count\":2},{\"bucketMax\":13,\"count\":1},{\"bucketMax\":19,\"count\":1}]},\"Data Directive and Looping\":{\"cyclesExecutedBySolution\":[{\"bucketMax\":3,\"count\":481},{\"bucketMax\":4,\"count\":2},{\"bucketMax\":5,\"count\":1945},{\"bucketMax\":6,\"count\":1},{\"bucketMax\":17,\"count\":1}],\"memoryBytesAccessedBySolution\":[{\"bucketMax\":5,\"count\":359},{\"bucketMax\":8,\"count\":8},{\"bucketMax\":9,\"count\":2060},{\"bucketMax\":11,\"count\":3},{\"bucketMax\":23,\"count\":1}]},\"First Assessment\":{\"cyclesExecutedBySolution\":[{\"bucketMax\":6,\"count\":62},{\"bucketMax\":8,\"count\":1342},{\"bucketMax\":10,\"count\":159},{\"bucketMax\":11,\"count\":48},{\"bucketMax\":12,\"count\":2},{\"bucketMax\":13,\"count\":3},{\"bucketMax\":18,\"count\":1}],\"memoryBytesAccessedBySolution\":[{\"bucketMax\":9,\"count\":5},{\"bucketMax\":11,\"count\":97},{\"bucketMax\":12,\"count\":1296},{\"bucketMax\":14,\"count\":2},{\"bucketMax\":15,\"count\":24},{\"bucketMax\":16,\"count\":183},{\"bucketMax\":17,\"count\":2},{\"bucketMax\":19,\"count\":5},{\"bucketMax\":23,\"count\":2},{\"bucketMax\":26,\"count\":1}]},\"Addition\":{\"cyclesExecutedBySolution\":[{\"bucketMax\":14,\"count\":2},{\"bucketMax\":15,\"count\":23},{\"bucketMax\":18,\"count\":11},{\"bucketMax\":19,\"count\":1015},{\"bucketMax\":20,\"count\":1},{\"bucketMax\":23,\"count\":40},{\"bucketMax\":24,\"count\":9},{\"bucketMax\":27,\"count\":1},{\"bucketMax\":28,\"count\":5},{\"bucketMax\":34,\"count\":1},{\"bucketMax\":37,\"count\":33},{\"bucketMax\":39,\"count\":1},{\"bucketMax\":41,\"count\":16},{\"bucketMax\":42,\"count\":3},{\"bucketMax\":44,\"count\":4},{\"bucketMax\":46,\"count\":17},{\"bucketMax\":47,\"count\":16},{\"bucketMax\":48,\"count\":2},{\"bucketMax\":49,\"count\":3},{\"bucketMax\":50,\"count\":10},{\"bucketMax\":51,\"count\":5},{\"bucketMax\":54,\"count\":4},{\"bucketMax\":59,\"count\":1},{\"bucketMax\":73,\"count\":1}],\"memoryBytesAccessedBySolution\":[{\"bucketMax\":12,\"count\":4},{\"bucketMax\":14,\"count\":74},{\"bucketMax\":15,\"count\":971},{\"bucketMax\":17,\"count\":2},{\"bucketMax\":18,\"count\":6},{\"bucketMax\":19,\"count\":43},{\"bucketMax\":21,\"count\":1},{\"bucketMax\":22,\"count\":5},{\"bucketMax\":26,\"count\":1},{\"bucketMax\":29,\"count\":34},{\"bucketMax\":32,\"count\":4},{\"bucketMax\":33,\"count\":20},{\"bucketMax\":34,\"count\":1},{\"bucketMax\":35,\"count\":19},{\"bucketMax\":36,\"count\":16},{\"bucketMax\":37,\"count\":1},{\"bucketMax\":39,\"count\":7},{\"bucketMax\":40,\"count\":12},{\"bucketMax\":46,\"count\":1},{\"bucketMax\":50,\"count\":1},{\"bucketMax\":52,\"count\":1},{\"bucketMax\":54,\"count\":1}]},\"Subtraction\":{\"cyclesExecutedBySolution\":[{\"bucketMax\":14,\"count\":1},{\"bucketMax\":20,\"count\":14},{\"bucketMax\":21,\"count\":1},{\"bucketMax\":28,\"count\":737},{\"bucketMax\":29,\"count\":20},{\"bucketMax\":30,\"count\":1},{\"bucketMax\":32,\"count\":36},{\"bucketMax\":33,\"count\":1},{\"bucketMax\":34,\"count\":7},{\"bucketMax\":36,\"count\":1},{\"bucketMax\":37,\"count\":60},{\"bucketMax\":38,\"count\":55},{\"bucketMax\":39,\"count\":2},{\"bucketMax\":41,\"count\":5},{\"bucketMax\":42,\"count\":10},{\"bucketMax\":46,\"count\":7},{\"bucketMax\":48,\"count\":1},{\"bucketMax\":50,\"count\":1},{\"bucketMax\":54,\"count\":1},{\"bucketMax\":55,\"count\":6},{\"bucketMax\":56,\"count\":4},{\"bucketMax\":57,\"count\":7},{\"bucketMax\":59,\"count\":3},{\"bucketMax\":61,\"count\":2},{\"bucketMax\":63,\"count\":1},{\"bucketMax\":64,\"count\":5},{\"bucketMax\":68,\"count\":1},{\"bucketMax\":71,\"count\":1}],\"memoryBytesAccessedBySolution\":[{\"bucketMax\":18,\"count\":3},{\"bucketMax\":20,\"count\":28},{\"bucketMax\":21,\"count\":35},{\"bucketMax\":22,\"count\":707},{\"bucketMax\":24,\"count\":2},{\"bucketMax\":25,\"count\":7},{\"bucketMax\":26,\"count\":36},{\"bucketMax\":28,\"count\":65},{\"bucketMax\":29,\"count\":53},{\"bucketMax\":30,\"count\":1},{\"bucketMax\":31,\"count\":2},{\"bucketMax\":32,\"count\":9},{\"bucketMax\":33,\"count\":4},{\"bucketMax\":35,\"count\":1},{\"bucketMax\":36,\"count\":7},{\"bucketMax\":39,\"count\":1},{\"bucketMax\":40,\"count\":1},{\"bucketMax\":41,\"count\":7},{\"bucketMax\":42,\"count\":4},{\"bucketMax\":43,\"count\":7},{\"bucketMax\":44,\"count\":1},{\"bucketMax\":45,\"count\":2},{\"bucketMax\":46,\"count\":2},{\"bucketMax\":47,\"count\":5},{\"bucketMax\":48,\"count\":1},{\"bucketMax\":51,\"count\":1},{\"bucketMax\":58,\"count\":1}]},\"Sign Function\":{\"cyclesExecutedBySolution\":[{\"bucketMax\":14,\"count\":1},{\"bucketMax\":18,\"count\":2},{\"bucketMax\":23,\"count\":6},{\"bucketMax\":24,\"count\":193},{\"bucketMax\":25,\"count\":14},{\"bucketMax\":26,\"count\":140},{\"bucketMax\":27,\"count\":62},{\"bucketMax\":28,\"count\":114},{\"bucketMax\":29,\"count\":7},{\"bucketMax\":30,\"count\":15},{\"bucketMax\":31,\"count\":30},{\"bucketMax\":32,\"count\":10},{\"bucketMax\":33,\"count\":23},{\"bucketMax\":34,\"count\":4},{\"bucketMax\":35,\"count\":18},{\"bucketMax\":36,\"count\":7},{\"bucketMax\":37,\"count\":6},{\"bucketMax\":38,\"count\":12},{\"bucketMax\":39,\"count\":8},{\"bucketMax\":40,\"count\":2},{\"bucketMax\":41,\"count\":5},{\"bucketMax\":42,\"count\":5},{\"bucketMax\":43,\"count\":5},{\"bucketMax\":44,\"count\":8},{\"bucketMax\":45,\"count\":4},{\"bucketMax\":46,\"count\":2},{\"bucketMax\":47,\"count\":1},{\"bucketMax\":48,\"count\":3},{\"bucketMax\":49,\"count\":5},{\"bucketMax\":50,\"count\":1},{\"bucketMax\":51,\"count\":2},{\"bucketMax\":52,\"count\":2},{\"bucketMax\":53,\"count\":2},{\"bucketMax\":55,\"count\":1},{\"bucketMax\":56,\"count\":1},{\"bucketMax\":57,\"count\":1},{\"bucketMax\":59,\"count\":1},{\"bucketMax\":60,\"count\":3},{\"bucketMax\":61,\"count\":1},{\"bucketMax\":64,\"count\":2},{\"bucketMax\":65,\"count\":1},{\"bucketMax\":66,\"count\":1},{\"bucketMax\":70,\"count\":1},{\"bucketMax\":82,\"count\":2},{\"bucketMax\":87,\"count\":2},{\"bucketMax\":89,\"count\":1},{\"bucketMax\":91,\"count\":1}],\"memoryBytesAccessedBySolution\":[{\"bucketMax\":19,\"count\":3},{\"bucketMax\":20,\"count\":1},{\"bucketMax\":21,\"count\":6},{\"bucketMax\":22,\"count\":15},{\"bucketMax\":23,\"count\":18},{\"bucketMax\":24,\"count\":38},{\"bucketMax\":25,\"count\":7},{\"bucketMax\":26,\"count\":16},{\"bucketMax\":27,\"count\":93},{\"bucketMax\":28,\"count\":33},{\"bucketMax\":29,\"count\":46},{\"bucketMax\":30,\"count\":157},{\"bucketMax\":31,\"count\":51},{\"bucketMax\":32,\"count\":8},{\"bucketMax\":33,\"count\":54},{\"bucketMax\":34,\"count\":33},{\"bucketMax\":35,\"count\":3},{\"bucketMax\":36,\"count\":28},{\"bucketMax\":37,\"count\":33},{\"bucketMax\":38,\"count\":9},{\"bucketMax\":39,\"count\":17},{\"bucketMax\":40,\"count\":16},{\"bucketMax\":41,\"count\":3},{\"bucketMax\":42,\"count\":8},{\"bucketMax\":43,\"count\":9},{\"bucketMax\":44,\"count\":3},{\"bucketMax\":45,\"count\":1},{\"bucketMax\":46,\"count\":7},{\"bucketMax\":47,\"count\":1},{\"bucketMax\":49,\"count\":4},{\"bucketMax\":50,\"count\":1},{\"bucketMax\":51,\"count\":2},{\"bucketMax\":52,\"count\":2},{\"bucketMax\":53,\"count\":1},{\"bucketMax\":55,\"count\":1},{\"bucketMax\":57,\"count\":1},{\"bucketMax\":58,\"count\":1},{\"bucketMax\":59,\"count\":1},{\"bucketMax\":63,\"count\":1},{\"bucketMax\":64,\"count\":1},{\"bucketMax\":65,\"count\":1},{\"bucketMax\":72,\"count\":2},{\"bucketMax\":80,\"count\":1}]},\"Multiplication\":{\"cyclesExecutedBySolution\":[{\"bucketMax\":33,\"count\":1},{\"bucketMax\":36,\"count\":1},{\"bucketMax\":47,\"count\":1},{\"bucketMax\":49,\"count\":2},{\"bucketMax\":50,\"count\":1},{\"bucketMax\":51,\"count\":1},{\"bucketMax\":52,\"count\":1},{\"bucketMax\":53,\"count\":1},{\"bucketMax\":54,\"count\":1},{\"bucketMax\":55,\"count\":1},{\"bucketMax\":57,\"count\":2},{\"bucketMax\":58,\"count\":3},{\"bucketMax\":59,\"count\":2},{\"bucketMax\":60,\"count\":12},{\"bucketMax\":61,\"count\":7},{\"bucketMax\":62,\"count\":1},{\"bucketMax\":63,\"count\":11},{\"bucketMax\":64,\"count\":20},{\"bucketMax\":65,\"count\":10},{\"bucketMax\":66,\"count\":8},{\"bucketMax\":67,\"count\":4},{\"bucketMax\":68,\"count\":10},{\"bucketMax\":69,\"count\":6},{\"bucketMax\":70,\"count\":8},{\"bucketMax\":71,\"count\":7},{\"bucketMax\":72,\"count\":4},{\"bucketMax\":73,\"count\":11},{\"bucketMax\":74,\"count\":33},{\"bucketMax\":75,\"count\":7},{\"bucketMax\":76,\"count\":12},{\"bucketMax\":77,\"count\":12},{\"bucketMax\":78,\"count\":21},{\"bucketMax\":79,\"count\":14},{\"bucketMax\":80,\"count\":12},{\"bucketMax\":81,\"count\":19},{\"bucketMax\":82,\"count\":9},{\"bucketMax\":83,\"count\":7},{\"bucketMax\":84,\"count\":3},{\"bucketMax\":85,\"count\":18},{\"bucketMax\":86,\"count\":9},{\"bucketMax\":87,\"count\":14},{\"bucketMax\":88,\"count\":12},{\"bucketMax\":89,\"count\":7},{\"bucketMax\":90,\"count\":8},{\"bucketMax\":91,\"count\":11},{\"bucketMax\":92,\"count\":8},{\"bucketMax\":93,\"count\":7},{\"bucketMax\":94,\"count\":5},{\"bucketMax\":95,\"count\":19},{\"bucketMax\":96,\"count\":16},{\"bucketMax\":97,\"count\":7},{\"bucketMax\":98,\"count\":6},{\"bucketMax\":99,\"count\":4},{\"bucketMax\":100,\"count\":5},{\"bucketMax\":101,\"count\":11},{\"bucketMax\":102,\"count\":5},{\"bucketMax\":103,\"count\":1},{\"bucketMax\":104,\"count\":6},{\"bucketMax\":105,\"count\":17},{\"bucketMax\":106,\"count\":1},{\"bucketMax\":107,\"count\":2},{\"bucketMax\":108,\"count\":3},{\"bucketMax\":109,\"count\":3},{\"bucketMax\":110,\"count\":3},{\"bucketMax\":111,\"count\":5},{\"bucketMax\":113,\"count\":2},{\"bucketMax\":114,\"count\":6},{\"bucketMax\":116,\"count\":3},{\"bucketMax\":119,\"count\":2},{\"bucketMax\":120,\"count\":2},{\"bucketMax\":122,\"count\":2},{\"bucketMax\":123,\"count\":2},{\"bucketMax\":125,\"count\":2},{\"bucketMax\":126,\"count\":2},{\"bucketMax\":128,\"count\":1},{\"bucketMax\":131,\"count\":1},{\"bucketMax\":132,\"count\":1},{\"bucketMax\":144,\"count\":1},{\"bucketMax\":146,\"count\":1},{\"bucketMax\":190,\"count\":1},{\"bucketMax\":205,\"count\":1},{\"bucketMax\":223,\"count\":1},{\"bucketMax\":285,\"count\":1}],\"memoryBytesAccessedBySolution\":[{\"bucketMax\":32,\"count\":1},{\"bucketMax\":33,\"count\":6},{\"bucketMax\":35,\"count\":4},{\"bucketMax\":36,\"count\":28},{\"bucketMax\":37,\"count\":28},{\"bucketMax\":39,\"count\":27},{\"bucketMax\":40,\"count\":45},{\"bucketMax\":41,\"count\":15},{\"bucketMax\":42,\"count\":19},{\"bucketMax\":43,\"count\":31},{\"bucketMax\":44,\"count\":30},{\"bucketMax\":45,\"count\":16},{\"bucketMax\":46,\"count\":49},{\"bucketMax\":47,\"count\":53},{\"bucketMax\":48,\"count\":13},{\"bucketMax\":49,\"count\":19},{\"bucketMax\":50,\"count\":35},{\"bucketMax\":51,\"count\":24},{\"bucketMax\":52,\"count\":7},{\"bucketMax\":53,\"count\":11},{\"bucketMax\":54,\"count\":9},{\"bucketMax\":55,\"count\":9},{\"bucketMax\":56,\"count\":6},{\"bucketMax\":57,\"count\":2},{\"bucketMax\":58,\"count\":1},{\"bucketMax\":59,\"count\":6},{\"bucketMax\":60,\"count\":4},{\"bucketMax\":61,\"count\":3},{\"bucketMax\":62,\"count\":7},{\"bucketMax\":63,\"count\":3},{\"bucketMax\":64,\"count\":2},{\"bucketMax\":65,\"count\":5},{\"bucketMax\":66,\"count\":1},{\"bucketMax\":67,\"count\":1},{\"bucketMax\":68,\"count\":1},{\"bucketMax\":70,\"count\":1},{\"bucketMax\":72,\"count\":1},{\"bucketMax\":73,\"count\":1},{\"bucketMax\":75,\"count\":1},{\"bucketMax\":76,\"count\":1},{\"bucketMax\":77,\"count\":1},{\"bucketMax\":83,\"count\":2},{\"bucketMax\":99,\"count\":1},{\"bucketMax\":115,\"count\":1},{\"bucketMax\":164,\"count\":1}]},\"Division\":{\"cyclesExecutedBySolution\":[{\"bucketMax\":76,\"count\":1},{\"bucketMax\":78,\"count\":36},{\"bucketMax\":79,\"count\":27},{\"bucketMax\":80,\"count\":1},{\"bucketMax\":81,\"count\":5},{\"bucketMax\":82,\"count\":6},{\"bucketMax\":83,\"count\":3},{\"bucketMax\":84,\"count\":1},{\"bucketMax\":85,\"count\":15},{\"bucketMax\":86,\"count\":40},{\"bucketMax\":87,\"count\":26},{\"bucketMax\":88,\"count\":6},{\"bucketMax\":89,\"count\":10},{\"bucketMax\":90,\"count\":8},{\"bucketMax\":92,\"count\":1},{\"bucketMax\":93,\"count\":2},{\"bucketMax\":94,\"count\":3},{\"bucketMax\":95,\"count\":1},{\"bucketMax\":96,\"count\":1},{\"bucketMax\":97,\"count\":10},{\"bucketMax\":98,\"count\":2},{\"bucketMax\":99,\"count\":1},{\"bucketMax\":100,\"count\":3},{\"bucketMax\":101,\"count\":8},{\"bucketMax\":102,\"count\":13},{\"bucketMax\":103,\"count\":4},{\"bucketMax\":104,\"count\":1},{\"bucketMax\":105,\"count\":1},{\"bucketMax\":107,\"count\":6},{\"bucketMax\":109,\"count\":7},{\"bucketMax\":110,\"count\":1},{\"bucketMax\":111,\"count\":1},{\"bucketMax\":112,\"count\":1},{\"bucketMax\":113,\"count\":3},{\"bucketMax\":114,\"count\":3},{\"bucketMax\":115,\"count\":3},{\"bucketMax\":116,\"count\":3},{\"bucketMax\":117,\"count\":3},{\"bucketMax\":118,\"count\":4},{\"bucketMax\":119,\"count\":3},{\"bucketMax\":120,\"count\":6},{\"bucketMax\":121,\"count\":1},{\"bucketMax\":122,\"count\":6},{\"bucketMax\":123,\"count\":7},{\"bucketMax\":124,\"count\":1},{\"bucketMax\":126,\"count\":2},{\"bucketMax\":127,\"count\":14},{\"bucketMax\":129,\"count\":3},{\"bucketMax\":130,\"count\":2},{\"bucketMax\":132,\"count\":3},{\"bucketMax\":133,\"count\":2},{\"bucketMax\":137,\"count\":2},{\"bucketMax\":139,\"count\":2},{\"bucketMax\":140,\"count\":2},{\"bucketMax\":141,\"count\":1},{\"bucketMax\":142,\"count\":1},{\"bucketMax\":143,\"count\":1},{\"bucketMax\":144,\"count\":1},{\"bucketMax\":146,\"count\":1},{\"bucketMax\":150,\"count\":1},{\"bucketMax\":154,\"count\":1},{\"bucketMax\":156,\"count\":1},{\"bucketMax\":159,\"count\":1},{\"bucketMax\":161,\"count\":1},{\"bucketMax\":164,\"count\":1},{\"bucketMax\":166,\"count\":1},{\"bucketMax\":169,\"count\":1},{\"bucketMax\":170,\"count\":1},{\"bucketMax\":175,\"count\":1},{\"bucketMax\":177,\"count\":1},{\"bucketMax\":178,\"count\":2},{\"bucketMax\":181,\"count\":1},{\"bucketMax\":183,\"count\":1},{\"bucketMax\":188,\"count\":1},{\"bucketMax\":189,\"count\":1},{\"bucketMax\":193,\"count\":1},{\"bucketMax\":197,\"count\":1},{\"bucketMax\":201,\"count\":1},{\"bucketMax\":217,\"count\":1},{\"bucketMax\":221,\"count\":1},{\"bucketMax\":231,\"count\":1},{\"bucketMax\":246,\"count\":1},{\"bucketMax\":250,\"count\":1},{\"bucketMax\":253,\"count\":2},{\"bucketMax\":255,\"count\":1},{\"bucketMax\":258,\"count\":1},{\"bucketMax\":266,\"count\":1},{\"bucketMax\":278,\"count\":1},{\"bucketMax\":312,\"count\":2},{\"bucketMax\":346,\"count\":1},{\"bucketMax\":780,\"count\":1},{\"bucketMax\":970,\"count\":1}],\"memoryBytesAccessedBySolution\":[{\"bucketMax\":38,\"count\":1},{\"bucketMax\":39,\"count\":2},{\"bucketMax\":40,\"count\":1},{\"bucketMax\":41,\"count\":3},{\"bucketMax\":42,\"count\":18},{\"bucketMax\":43,\"count\":36},{\"bucketMax\":45,\"count\":7},{\"bucketMax\":46,\"count\":39},{\"bucketMax\":47,\"count\":55},{\"bucketMax\":48,\"count\":1},{\"bucketMax\":49,\"count\":10},{\"bucketMax\":50,\"count\":12},{\"bucketMax\":51,\"count\":6},{\"bucketMax\":52,\"count\":3},{\"bucketMax\":53,\"count\":4},{\"bucketMax\":54,\"count\":3},{\"bucketMax\":55,\"count\":1},{\"bucketMax\":56,\"count\":5},{\"bucketMax\":57,\"count\":4},{\"bucketMax\":58,\"count\":2},{\"bucketMax\":59,\"count\":3},{\"bucketMax\":60,\"count\":2},{\"bucketMax\":61,\"count\":2},{\"bucketMax\":62,\"count\":7},{\"bucketMax\":63,\"count\":5},{\"bucketMax\":64,\"count\":6},{\"bucketMax\":65,\"count\":6},{\"bucketMax\":66,\"count\":2},{\"bucketMax\":67,\"count\":5},{\"bucketMax\":68,\"count\":3},{\"bucketMax\":69,\"count\":3},{\"bucketMax\":70,\"count\":13},{\"bucketMax\":71,\"count\":8},{\"bucketMax\":72,\"count\":2},{\"bucketMax\":73,\"count\":3},{\"bucketMax\":74,\"count\":6},{\"bucketMax\":75,\"count\":2},{\"bucketMax\":76,\"count\":3},{\"bucketMax\":77,\"count\":5},{\"bucketMax\":78,\"count\":3},{\"bucketMax\":79,\"count\":2},{\"bucketMax\":80,\"count\":18},{\"bucketMax\":81,\"count\":3},{\"bucketMax\":82,\"count\":2},{\"bucketMax\":83,\"count\":3},{\"bucketMax\":84,\"count\":6},{\"bucketMax\":85,\"count\":2},{\"bucketMax\":86,\"count\":3},{\"bucketMax\":88,\"count\":1},{\"bucketMax\":89,\"count\":1},{\"bucketMax\":90,\"count\":4},{\"bucketMax\":91,\"count\":4},{\"bucketMax\":95,\"count\":1},{\"bucketMax\":96,\"count\":1},{\"bucketMax\":98,\"count\":2},{\"bucketMax\":99,\"count\":1},{\"bucketMax\":103,\"count\":1},{\"bucketMax\":104,\"count\":1},{\"bucketMax\":108,\"count\":1},{\"bucketMax\":111,\"count\":1},{\"bucketMax\":114,\"count\":3},{\"bucketMax\":117,\"count\":1},{\"bucketMax\":127,\"count\":1},{\"bucketMax\":150,\"count\":1},{\"bucketMax\":203,\"count\":1},{\"bucketMax\":204,\"count\":1}]},\"Sequence Sum\":{\"cyclesExecutedBySolution\":[{\"bucketMax\":57,\"count\":1},{\"bucketMax\":74,\"count\":1},{\"bucketMax\":78,\"count\":2},{\"bucketMax\":83,\"count\":1},{\"bucketMax\":85,\"count\":120},{\"bucketMax\":86,\"count\":9},{\"bucketMax\":87,\"count\":6},{\"bucketMax\":88,\"count\":12},{\"bucketMax\":89,\"count\":16},{\"bucketMax\":90,\"count\":4},{\"bucketMax\":91,\"count\":58},{\"bucketMax\":92,\"count\":16},{\"bucketMax\":93,\"count\":12},{\"bucketMax\":94,\"count\":1},{\"bucketMax\":95,\"count\":8},{\"bucketMax\":96,\"count\":8},{\"bucketMax\":97,\"count\":4},{\"bucketMax\":98,\"count\":1},{\"bucketMax\":99,\"count\":6},{\"bucketMax\":100,\"count\":5},{\"bucketMax\":101,\"count\":2},{\"bucketMax\":102,\"count\":4},{\"bucketMax\":103,\"count\":3},{\"bucketMax\":105,\"count\":3},{\"bucketMax\":106,\"count\":1},{\"bucketMax\":107,\"count\":3},{\"bucketMax\":108,\"count\":1},{\"bucketMax\":109,\"count\":4},{\"bucketMax\":110,\"count\":5},{\"bucketMax\":111,\"count\":4},{\"bucketMax\":113,\"count\":2},{\"bucketMax\":114,\"count\":2},{\"bucketMax\":115,\"count\":1},{\"bucketMax\":116,\"count\":2},{\"bucketMax\":117,\"count\":1},{\"bucketMax\":118,\"count\":1},{\"bucketMax\":119,\"count\":1},{\"bucketMax\":120,\"count\":1},{\"bucketMax\":121,\"count\":1},{\"bucketMax\":123,\"count\":2},{\"bucketMax\":128,\"count\":1},{\"bucketMax\":129,\"count\":1},{\"bucketMax\":131,\"count\":1},{\"bucketMax\":133,\"count\":3},{\"bucketMax\":135,\"count\":1},{\"bucketMax\":142,\"count\":1}],\"memoryBytesAccessedBySolution\":[{\"bucketMax\":22,\"count\":2},{\"bucketMax\":23,\"count\":1},{\"bucketMax\":24,\"count\":10},{\"bucketMax\":25,\"count\":10},{\"bucketMax\":26,\"count\":147},{\"bucketMax\":29,\"count\":38},{\"bucketMax\":30,\"count\":19},{\"bucketMax\":31,\"count\":1},{\"bucketMax\":32,\"count\":54},{\"bucketMax\":33,\"count\":14},{\"bucketMax\":34,\"count\":1},{\"bucketMax\":35,\"count\":9},{\"bucketMax\":36,\"count\":12},{\"bucketMax\":37,\"count\":2},{\"bucketMax\":38,\"count\":7},{\"bucketMax\":39,\"count\":7},{\"bucketMax\":40,\"count\":1},{\"bucketMax\":42,\"count\":3},{\"bucketMax\":44,\"count\":1},{\"bucketMax\":47,\"count\":1},{\"bucketMax\":50,\"count\":3}]},\"Sequence Cardinality\":{\"cyclesExecutedBySolution\":[{\"bucketMax\":26,\"count\":4},{\"bucketMax\":27,\"count\":7},{\"bucketMax\":32,\"count\":1},{\"bucketMax\":35,\"count\":1},{\"bucketMax\":43,\"count\":6},{\"bucketMax\":49,\"count\":5},{\"bucketMax\":50,\"count\":17},{\"bucketMax\":51,\"count\":8},{\"bucketMax\":54,\"count\":6},{\"bucketMax\":55,\"count\":112},{\"bucketMax\":56,\"count\":1},{\"bucketMax\":57,\"count\":2},{\"bucketMax\":58,\"count\":15},{\"bucketMax\":59,\"count\":17},{\"bucketMax\":60,\"count\":2},{\"bucketMax\":61,\"count\":69},{\"bucketMax\":62,\"count\":6},{\"bucketMax\":63,\"count\":15},{\"bucketMax\":65,\"count\":2},{\"bucketMax\":66,\"count\":3},{\"bucketMax\":67,\"count\":4},{\"bucketMax\":68,\"count\":1},{\"bucketMax\":69,\"count\":1},{\"bucketMax\":71,\"count\":6},{\"bucketMax\":73,\"count\":2},{\"bucketMax\":74,\"count\":7},{\"bucketMax\":75,\"count\":3},{\"bucketMax\":77,\"count\":1},{\"bucketMax\":78,\"count\":2},{\"bucketMax\":79,\"count\":1},{\"bucketMax\":83,\"count\":1},{\"bucketMax\":86,\"count\":1},{\"bucketMax\":89,\"count\":2},{\"bucketMax\":96,\"count\":1},{\"bucketMax\":97,\"count\":1},{\"bucketMax\":107,\"count\":1}],\"memoryBytesAccessedBySolution\":[{\"bucketMax\":15,\"count\":2},{\"bucketMax\":16,\"count\":3},{\"bucketMax\":17,\"count\":6},{\"bucketMax\":20,\"count\":1},{\"bucketMax\":22,\"count\":1},{\"bucketMax\":23,\"count\":2},{\"bucketMax\":24,\"count\":15},{\"bucketMax\":25,\"count\":9},{\"bucketMax\":26,\"count\":9},{\"bucketMax\":27,\"count\":178},{\"bucketMax\":28,\"count\":1},{\"bucketMax\":30,\"count\":28},{\"bucketMax\":31,\"count\":9},{\"bucketMax\":32,\"count\":1},{\"bucketMax\":33,\"count\":43},{\"bucketMax\":34,\"count\":8},{\"bucketMax\":36,\"count\":4},{\"bucketMax\":37,\"count\":4},{\"bucketMax\":38,\"count\":1},{\"bucketMax\":39,\"count\":1},{\"bucketMax\":40,\"count\":4},{\"bucketMax\":43,\"count\":2},{\"bucketMax\":48,\"count\":1},{\"bucketMax\":50,\"count\":1}]},\"Number to Sequence\":{\"cyclesExecutedBySolution\":[{\"bucketMax\":48,\"count\":10},{\"bucketMax\":49,\"count\":2},{\"bucketMax\":59,\"count\":30},{\"bucketMax\":60,\"count\":36},{\"bucketMax\":61,\"count\":2},{\"bucketMax\":62,\"count\":1},{\"bucketMax\":63,\"count\":1},{\"bucketMax\":64,\"count\":2},{\"bucketMax\":65,\"count\":6},{\"bucketMax\":66,\"count\":1},{\"bucketMax\":69,\"count\":9},{\"bucketMax\":70,\"count\":7},{\"bucketMax\":71,\"count\":4},{\"bucketMax\":72,\"count\":22},{\"bucketMax\":73,\"count\":6},{\"bucketMax\":75,\"count\":2},{\"bucketMax\":76,\"count\":1},{\"bucketMax\":77,\"count\":60},{\"bucketMax\":78,\"count\":22},{\"bucketMax\":79,\"count\":7},{\"bucketMax\":81,\"count\":1},{\"bucketMax\":82,\"count\":3},{\"bucketMax\":83,\"count\":6},{\"bucketMax\":84,\"count\":3},{\"bucketMax\":86,\"count\":2},{\"bucketMax\":87,\"count\":1},{\"bucketMax\":88,\"count\":2},{\"bucketMax\":89,\"count\":4},{\"bucketMax\":90,\"count\":14},{\"bucketMax\":94,\"count\":4},{\"bucketMax\":95,\"count\":6},{\"bucketMax\":96,\"count\":10},{\"bucketMax\":98,\"count\":1},{\"bucketMax\":100,\"count\":4},{\"bucketMax\":101,\"count\":9},{\"bucketMax\":102,\"count\":2},{\"bucketMax\":106,\"count\":3},{\"bucketMax\":107,\"count\":1},{\"bucketMax\":108,\"count\":3},{\"bucketMax\":111,\"count\":1},{\"bucketMax\":112,\"count\":3},{\"bucketMax\":113,\"count\":3},{\"bucketMax\":117,\"count\":1},{\"bucketMax\":119,\"count\":1},{\"bucketMax\":136,\"count\":1}],\"memoryBytesAccessedBySolution\":[{\"bucketMax\":17,\"count\":2},{\"bucketMax\":18,\"count\":4},{\"bucketMax\":19,\"count\":28},{\"bucketMax\":20,\"count\":14},{\"bucketMax\":21,\"count\":5},{\"bucketMax\":22,\"count\":7},{\"bucketMax\":23,\"count\":71},{\"bucketMax\":24,\"count\":9},{\"bucketMax\":25,\"count\":12},{\"bucketMax\":26,\"count\":24},{\"bucketMax\":27,\"count\":24},{\"bucketMax\":28,\"count\":14},{\"bucketMax\":29,\"count\":22},{\"bucketMax\":30,\"count\":27},{\"bucketMax\":31,\"count\":17},{\"bucketMax\":32,\"count\":1},{\"bucketMax\":33,\"count\":6},{\"bucketMax\":34,\"count\":14},{\"bucketMax\":35,\"count\":5},{\"bucketMax\":36,\"count\":2},{\"bucketMax\":37,\"count\":5},{\"bucketMax\":38,\"count\":1},{\"bucketMax\":40,\"count\":2},{\"bucketMax\":41,\"count\":1},{\"bucketMax\":45,\"count\":1},{\"bucketMax\":47,\"count\":1},{\"bucketMax\":49,\"count\":1}]},\"Self-Modifying Code\":{\"cyclesExecutedBySolution\":[{\"bucketMax\":12,\"count\":18},{\"bucketMax\":34,\"count\":1},{\"bucketMax\":46,\"count\":301}],\"memoryBytesAccessedBySolution\":[{\"bucketMax\":15,\"count\":320}]},\"Stack Memory\":{\"cyclesExecutedBySolution\":[{\"bucketMax\":3,\"count\":30},{\"bucketMax\":6,\"count\":5},{\"bucketMax\":16,\"count\":1},{\"bucketMax\":19,\"count\":268}],\"memoryBytesAccessedBySolution\":[{\"bucketMax\":7,\"count\":3},{\"bucketMax\":8,\"count\":2},{\"bucketMax\":9,\"count\":4},{\"bucketMax\":10,\"count\":4},{\"bucketMax\":12,\"count\":2},{\"bucketMax\":13,\"count\":15},{\"bucketMax\":20,\"count\":1},{\"bucketMax\":23,\"count\":3},{\"bucketMax\":24,\"count\":1},{\"bucketMax\":26,\"count\":1},{\"bucketMax\":36,\"count\":268}]},\"Reverse Sequence\":{\"cyclesExecutedBySolution\":[{\"bucketMax\":115,\"count\":1},{\"bucketMax\":122,\"count\":1},{\"bucketMax\":123,\"count\":1},{\"bucketMax\":125,\"count\":1},{\"bucketMax\":128,\"count\":2},{\"bucketMax\":131,\"count\":1},{\"bucketMax\":132,\"count\":1},{\"bucketMax\":133,\"count\":1},{\"bucketMax\":134,\"count\":3},{\"bucketMax\":136,\"count\":1},{\"bucketMax\":139,\"count\":1},{\"bucketMax\":142,\"count\":1},{\"bucketMax\":145,\"count\":2},{\"bucketMax\":148,\"count\":1},{\"bucketMax\":152,\"count\":1},{\"bucketMax\":153,\"count\":2},{\"bucketMax\":156,\"count\":2},{\"bucketMax\":159,\"count\":3},{\"bucketMax\":160,\"count\":2},{\"bucketMax\":161,\"count\":1},{\"bucketMax\":164,\"count\":1},{\"bucketMax\":166,\"count\":1},{\"bucketMax\":171,\"count\":1},{\"bucketMax\":175,\"count\":2},{\"bucketMax\":176,\"count\":3},{\"bucketMax\":179,\"count\":2},{\"bucketMax\":184,\"count\":1},{\"bucketMax\":185,\"count\":4},{\"bucketMax\":186,\"count\":3},{\"bucketMax\":188,\"count\":2},{\"bucketMax\":189,\"count\":1},{\"bucketMax\":190,\"count\":3},{\"bucketMax\":191,\"count\":2},{\"bucketMax\":192,\"count\":1},{\"bucketMax\":194,\"count\":1},{\"bucketMax\":195,\"count\":2},{\"bucketMax\":196,\"count\":1},{\"bucketMax\":197,\"count\":2},{\"bucketMax\":199,\"count\":2},{\"bucketMax\":201,\"count\":8},{\"bucketMax\":202,\"count\":2},{\"bucketMax\":204,\"count\":1},{\"bucketMax\":205,\"count\":1},{\"bucketMax\":206,\"count\":1},{\"bucketMax\":207,\"count\":1},{\"bucketMax\":208,\"count\":2},{\"bucketMax\":209,\"count\":2},{\"bucketMax\":213,\"count\":3},{\"bucketMax\":214,\"count\":3},{\"bucketMax\":215,\"count\":1},{\"bucketMax\":217,\"count\":1},{\"bucketMax\":218,\"count\":1},{\"bucketMax\":219,\"count\":1},{\"bucketMax\":220,\"count\":1},{\"bucketMax\":221,\"count\":2},{\"bucketMax\":222,\"count\":1},{\"bucketMax\":223,\"count\":1},{\"bucketMax\":224,\"count\":1},{\"bucketMax\":225,\"count\":3},{\"bucketMax\":226,\"count\":2},{\"bucketMax\":227,\"count\":1},{\"bucketMax\":228,\"count\":2},{\"bucketMax\":230,\"count\":2},{\"bucketMax\":231,\"count\":1},{\"bucketMax\":232,\"count\":2},{\"bucketMax\":234,\"count\":1},{\"bucketMax\":235,\"count\":1},{\"bucketMax\":236,\"count\":1},{\"bucketMax\":237,\"count\":2},{\"bucketMax\":238,\"count\":1},{\"bucketMax\":239,\"count\":2},{\"bucketMax\":240,\"count\":1},{\"bucketMax\":241,\"count\":4},{\"bucketMax\":242,\"count\":2},{\"bucketMax\":244,\"count\":1},{\"bucketMax\":245,\"count\":1},{\"bucketMax\":246,\"count\":4},{\"bucketMax\":247,\"count\":2},{\"bucketMax\":251,\"count\":8},{\"bucketMax\":255,\"count\":4},{\"bucketMax\":259,\"count\":2},{\"bucketMax\":260,\"count\":1},{\"bucketMax\":262,\"count\":3},{\"bucketMax\":263,\"count\":1},{\"bucketMax\":264,\"count\":1},{\"bucketMax\":265,\"count\":2},{\"bucketMax\":266,\"count\":3},{\"bucketMax\":267,\"count\":1},{\"bucketMax\":269,\"count\":2},{\"bucketMax\":271,\"count\":1},{\"bucketMax\":272,\"count\":2},{\"bucketMax\":278,\"count\":1},{\"bucketMax\":279,\"count\":1},{\"bucketMax\":285,\"count\":1},{\"bucketMax\":292,\"count\":2},{\"bucketMax\":294,\"count\":3},{\"bucketMax\":306,\"count\":1},{\"bucketMax\":314,\"count\":1},{\"bucketMax\":320,\"count\":1},{\"bucketMax\":324,\"count\":1},{\"bucketMax\":329,\"count\":1},{\"bucketMax\":335,\"count\":1},{\"bucketMax\":341,\"count\":1},{\"bucketMax\":348,\"count\":1},{\"bucketMax\":357,\"count\":1},{\"bucketMax\":386,\"count\":1},{\"bucketMax\":390,\"count\":1},{\"bucketMax\":394,\"count\":1},{\"bucketMax\":398,\"count\":1},{\"bucketMax\":441,\"count\":1},{\"bucketMax\":1063,\"count\":1}],\"memoryBytesAccessedBySolution\":[{\"bucketMax\":51,\"count\":2},{\"bucketMax\":53,\"count\":1},{\"bucketMax\":57,\"count\":2},{\"bucketMax\":58,\"count\":2},{\"bucketMax\":59,\"count\":5},{\"bucketMax\":60,\"count\":1},{\"bucketMax\":61,\"count\":2},{\"bucketMax\":62,\"count\":4},{\"bucketMax\":63,\"count\":1},{\"bucketMax\":64,\"count\":2},{\"bucketMax\":65,\"count\":2},{\"bucketMax\":66,\"count\":1},{\"bucketMax\":67,\"count\":1},{\"bucketMax\":68,\"count\":5},{\"bucketMax\":69,\"count\":3},{\"bucketMax\":71,\"count\":4},{\"bucketMax\":72,\"count\":4},{\"bucketMax\":73,\"count\":2},{\"bucketMax\":74,\"count\":2},{\"bucketMax\":75,\"count\":2},{\"bucketMax\":76,\"count\":2},{\"bucketMax\":77,\"count\":6},{\"bucketMax\":78,\"count\":2},{\"bucketMax\":79,\"count\":1},{\"bucketMax\":80,\"count\":7},{\"bucketMax\":81,\"count\":9},{\"bucketMax\":82,\"count\":1},{\"bucketMax\":83,\"count\":2},{\"bucketMax\":84,\"count\":3},{\"bucketMax\":86,\"count\":4},{\"bucketMax\":87,\"count\":12},{\"bucketMax\":88,\"count\":11},{\"bucketMax\":89,\"count\":4},{\"bucketMax\":90,\"count\":2},{\"bucketMax\":91,\"count\":1},{\"bucketMax\":92,\"count\":2},{\"bucketMax\":93,\"count\":5},{\"bucketMax\":94,\"count\":3},{\"bucketMax\":95,\"count\":2},{\"bucketMax\":96,\"count\":3},{\"bucketMax\":98,\"count\":1},{\"bucketMax\":99,\"count\":3},{\"bucketMax\":100,\"count\":10},{\"bucketMax\":101,\"count\":2},{\"bucketMax\":102,\"count\":3},{\"bucketMax\":103,\"count\":6},{\"bucketMax\":104,\"count\":3},{\"bucketMax\":105,\"count\":3},{\"bucketMax\":106,\"count\":5},{\"bucketMax\":108,\"count\":1},{\"bucketMax\":109,\"count\":2},{\"bucketMax\":110,\"count\":1},{\"bucketMax\":111,\"count\":2},{\"bucketMax\":112,\"count\":1},{\"bucketMax\":114,\"count\":4},{\"bucketMax\":115,\"count\":3},{\"bucketMax\":117,\"count\":2},{\"bucketMax\":119,\"count\":1},{\"bucketMax\":120,\"count\":1},{\"bucketMax\":121,\"count\":2},{\"bucketMax\":132,\"count\":1},{\"bucketMax\":153,\"count\":1}]},\"Interleave\":{\"cyclesExecutedBySolution\":[{\"bucketMax\":98,\"count\":2},{\"bucketMax\":119,\"count\":1},{\"bucketMax\":122,\"count\":1},{\"bucketMax\":124,\"count\":1},{\"bucketMax\":129,\"count\":2},{\"bucketMax\":131,\"count\":1},{\"bucketMax\":144,\"count\":3},{\"bucketMax\":145,\"count\":1},{\"bucketMax\":149,\"count\":7},{\"bucketMax\":160,\"count\":1},{\"bucketMax\":164,\"count\":1},{\"bucketMax\":165,\"count\":2},{\"bucketMax\":170,\"count\":1},{\"bucketMax\":173,\"count\":1},{\"bucketMax\":174,\"count\":1},{\"bucketMax\":175,\"count\":2},{\"bucketMax\":176,\"count\":1},{\"bucketMax\":178,\"count\":2},{\"bucketMax\":179,\"count\":2},{\"bucketMax\":183,\"count\":1},{\"bucketMax\":184,\"count\":1},{\"bucketMax\":185,\"count\":1},{\"bucketMax\":187,\"count\":2},{\"bucketMax\":188,\"count\":2},{\"bucketMax\":189,\"count\":1},{\"bucketMax\":195,\"count\":1},{\"bucketMax\":196,\"count\":1},{\"bucketMax\":204,\"count\":1},{\"bucketMax\":205,\"count\":3},{\"bucketMax\":213,\"count\":1},{\"bucketMax\":215,\"count\":1},{\"bucketMax\":218,\"count\":1},{\"bucketMax\":219,\"count\":1},{\"bucketMax\":222,\"count\":1},{\"bucketMax\":233,\"count\":1},{\"bucketMax\":238,\"count\":1},{\"bucketMax\":242,\"count\":2},{\"bucketMax\":244,\"count\":1},{\"bucketMax\":245,\"count\":1},{\"bucketMax\":247,\"count\":1},{\"bucketMax\":252,\"count\":1},{\"bucketMax\":254,\"count\":1},{\"bucketMax\":255,\"count\":1},{\"bucketMax\":257,\"count\":3},{\"bucketMax\":258,\"count\":1},{\"bucketMax\":263,\"count\":2},{\"bucketMax\":270,\"count\":1},{\"bucketMax\":272,\"count\":1},{\"bucketMax\":274,\"count\":1},{\"bucketMax\":276,\"count\":2},{\"bucketMax\":279,\"count\":1},{\"bucketMax\":280,\"count\":1},{\"bucketMax\":282,\"count\":2},{\"bucketMax\":284,\"count\":1},{\"bucketMax\":289,\"count\":2},{\"bucketMax\":292,\"count\":2},{\"bucketMax\":297,\"count\":1},{\"bucketMax\":302,\"count\":1},{\"bucketMax\":303,\"count\":1},{\"bucketMax\":304,\"count\":1},{\"bucketMax\":305,\"count\":1},{\"bucketMax\":306,\"count\":1},{\"bucketMax\":310,\"count\":2},{\"bucketMax\":312,\"count\":1},{\"bucketMax\":313,\"count\":1},{\"bucketMax\":317,\"count\":1},{\"bucketMax\":320,\"count\":1},{\"bucketMax\":323,\"count\":2},{\"bucketMax\":324,\"count\":2},{\"bucketMax\":325,\"count\":1},{\"bucketMax\":326,\"count\":2},{\"bucketMax\":327,\"count\":1},{\"bucketMax\":328,\"count\":1},{\"bucketMax\":333,\"count\":1},{\"bucketMax\":334,\"count\":1},{\"bucketMax\":336,\"count\":1},{\"bucketMax\":337,\"count\":1},{\"bucketMax\":340,\"count\":1},{\"bucketMax\":341,\"count\":3},{\"bucketMax\":352,\"count\":2},{\"bucketMax\":354,\"count\":1},{\"bucketMax\":356,\"count\":4},{\"bucketMax\":359,\"count\":1},{\"bucketMax\":364,\"count\":1},{\"bucketMax\":366,\"count\":1},{\"bucketMax\":368,\"count\":1},{\"bucketMax\":371,\"count\":2},{\"bucketMax\":374,\"count\":1},{\"bucketMax\":375,\"count\":1},{\"bucketMax\":383,\"count\":1},{\"bucketMax\":385,\"count\":1},{\"bucketMax\":393,\"count\":2},{\"bucketMax\":410,\"count\":1},{\"bucketMax\":415,\"count\":2},{\"bucketMax\":419,\"count\":1},{\"bucketMax\":420,\"count\":1},{\"bucketMax\":462,\"count\":1},{\"bucketMax\":463,\"count\":1},{\"bucketMax\":519,\"count\":1},{\"bucketMax\":522,\"count\":2},{\"bucketMax\":633,\"count\":1},{\"bucketMax\":661,\"count\":1},{\"bucketMax\":1396,\"count\":1}],\"memoryBytesAccessedBySolution\":[{\"bucketMax\":48,\"count\":1},{\"bucketMax\":49,\"count\":1},{\"bucketMax\":50,\"count\":1},{\"bucketMax\":51,\"count\":3},{\"bucketMax\":52,\"count\":1},{\"bucketMax\":55,\"count\":2},{\"bucketMax\":57,\"count\":2},{\"bucketMax\":61,\"count\":2},{\"bucketMax\":62,\"count\":7},{\"bucketMax\":63,\"count\":2},{\"bucketMax\":66,\"count\":2},{\"bucketMax\":69,\"count\":3},{\"bucketMax\":71,\"count\":1},{\"bucketMax\":72,\"count\":1},{\"bucketMax\":73,\"count\":2},{\"bucketMax\":75,\"count\":1},{\"bucketMax\":79,\"count\":2},{\"bucketMax\":80,\"count\":1},{\"bucketMax\":81,\"count\":2},{\"bucketMax\":83,\"count\":2},{\"bucketMax\":84,\"count\":2},{\"bucketMax\":86,\"count\":2},{\"bucketMax\":88,\"count\":1},{\"bucketMax\":89,\"count\":1},{\"bucketMax\":92,\"count\":2},{\"bucketMax\":93,\"count\":4},{\"bucketMax\":94,\"count\":3},{\"bucketMax\":95,\"count\":2},{\"bucketMax\":96,\"count\":1},{\"bucketMax\":97,\"count\":5},{\"bucketMax\":98,\"count\":1},{\"bucketMax\":99,\"count\":3},{\"bucketMax\":101,\"count\":2},{\"bucketMax\":104,\"count\":2},{\"bucketMax\":105,\"count\":1},{\"bucketMax\":106,\"count\":1},{\"bucketMax\":107,\"count\":3},{\"bucketMax\":108,\"count\":3},{\"bucketMax\":109,\"count\":3},{\"bucketMax\":110,\"count\":1},{\"bucketMax\":111,\"count\":2},{\"bucketMax\":113,\"count\":2},{\"bucketMax\":114,\"count\":2},{\"bucketMax\":115,\"count\":1},{\"bucketMax\":116,\"count\":1},{\"bucketMax\":118,\"count\":1},{\"bucketMax\":119,\"count\":1},{\"bucketMax\":121,\"count\":4},{\"bucketMax\":123,\"count\":1},{\"bucketMax\":125,\"count\":2},{\"bucketMax\":127,\"count\":1},{\"bucketMax\":128,\"count\":2},{\"bucketMax\":129,\"count\":2},{\"bucketMax\":130,\"count\":1},{\"bucketMax\":133,\"count\":2},{\"bucketMax\":134,\"count\":1},{\"bucketMax\":135,\"count\":1},{\"bucketMax\":136,\"count\":2},{\"bucketMax\":138,\"count\":2},{\"bucketMax\":139,\"count\":3},{\"bucketMax\":140,\"count\":1},{\"bucketMax\":142,\"count\":1},{\"bucketMax\":143,\"count\":2},{\"bucketMax\":144,\"count\":1},{\"bucketMax\":148,\"count\":2},{\"bucketMax\":150,\"count\":1},{\"bucketMax\":152,\"count\":1},{\"bucketMax\":153,\"count\":1},{\"bucketMax\":154,\"count\":1},{\"bucketMax\":156,\"count\":1},{\"bucketMax\":159,\"count\":1},{\"bucketMax\":163,\"count\":1},{\"bucketMax\":166,\"count\":2},{\"bucketMax\":168,\"count\":5},{\"bucketMax\":174,\"count\":1},{\"bucketMax\":179,\"count\":2},{\"bucketMax\":181,\"count\":2},{\"bucketMax\":195,\"count\":1}]},\"Indicator Function\":{\"cyclesExecutedBySolution\":[{\"bucketMax\":99,\"count\":1},{\"bucketMax\":106,\"count\":1},{\"bucketMax\":116,\"count\":1},{\"bucketMax\":118,\"count\":1},{\"bucketMax\":133,\"count\":1},{\"bucketMax\":141,\"count\":1},{\"bucketMax\":145,\"count\":1},{\"bucketMax\":149,\"count\":1},{\"bucketMax\":153,\"count\":1},{\"bucketMax\":154,\"count\":1},{\"bucketMax\":155,\"count\":1},{\"bucketMax\":156,\"count\":1},{\"bucketMax\":166,\"count\":1},{\"bucketMax\":177,\"count\":1},{\"bucketMax\":179,\"count\":2},{\"bucketMax\":184,\"count\":1},{\"bucketMax\":186,\"count\":2},{\"bucketMax\":187,\"count\":1},{\"bucketMax\":189,\"count\":2},{\"bucketMax\":192,\"count\":1},{\"bucketMax\":194,\"count\":1},{\"bucketMax\":197,\"count\":1},{\"bucketMax\":199,\"count\":4},{\"bucketMax\":200,\"count\":1},{\"bucketMax\":201,\"count\":1},{\"bucketMax\":202,\"count\":1},{\"bucketMax\":204,\"count\":2},{\"bucketMax\":208,\"count\":1},{\"bucketMax\":211,\"count\":1},{\"bucketMax\":217,\"count\":1},{\"bucketMax\":220,\"count\":1},{\"bucketMax\":222,\"count\":1},{\"bucketMax\":225,\"count\":1},{\"bucketMax\":228,\"count\":1},{\"bucketMax\":229,\"count\":1},{\"bucketMax\":235,\"count\":1},{\"bucketMax\":239,\"count\":1},{\"bucketMax\":242,\"count\":1},{\"bucketMax\":243,\"count\":1},{\"bucketMax\":244,\"count\":1},{\"bucketMax\":246,\"count\":1},{\"bucketMax\":247,\"count\":1},{\"bucketMax\":250,\"count\":1},{\"bucketMax\":258,\"count\":1},{\"bucketMax\":263,\"count\":1},{\"bucketMax\":266,\"count\":1},{\"bucketMax\":270,\"count\":1},{\"bucketMax\":272,\"count\":1},{\"bucketMax\":273,\"count\":1},{\"bucketMax\":276,\"count\":1},{\"bucketMax\":277,\"count\":1},{\"bucketMax\":287,\"count\":1},{\"bucketMax\":288,\"count\":1},{\"bucketMax\":295,\"count\":1},{\"bucketMax\":297,\"count\":1},{\"bucketMax\":305,\"count\":1},{\"bucketMax\":309,\"count\":2},{\"bucketMax\":311,\"count\":1},{\"bucketMax\":317,\"count\":1},{\"bucketMax\":322,\"count\":1},{\"bucketMax\":330,\"count\":1},{\"bucketMax\":345,\"count\":1},{\"bucketMax\":349,\"count\":2},{\"bucketMax\":360,\"count\":1},{\"bucketMax\":379,\"count\":1},{\"bucketMax\":422,\"count\":1},{\"bucketMax\":425,\"count\":1},{\"bucketMax\":501,\"count\":1},{\"bucketMax\":509,\"count\":1},{\"bucketMax\":533,\"count\":2},{\"bucketMax\":581,\"count\":1},{\"bucketMax\":645,\"count\":1},{\"bucketMax\":710,\"count\":1},{\"bucketMax\":1016,\"count\":1}],\"memoryBytesAccessedBySolution\":[{\"bucketMax\":76,\"count\":1},{\"bucketMax\":79,\"count\":1},{\"bucketMax\":81,\"count\":1},{\"bucketMax\":82,\"count\":2},{\"bucketMax\":83,\"count\":1},{\"bucketMax\":90,\"count\":1},{\"bucketMax\":91,\"count\":1},{\"bucketMax\":97,\"count\":3},{\"bucketMax\":98,\"count\":1},{\"bucketMax\":102,\"count\":1},{\"bucketMax\":103,\"count\":1},{\"bucketMax\":106,\"count\":1},{\"bucketMax\":107,\"count\":1},{\"bucketMax\":108,\"count\":1},{\"bucketMax\":110,\"count\":2},{\"bucketMax\":111,\"count\":1},{\"bucketMax\":115,\"count\":3},{\"bucketMax\":117,\"count\":2},{\"bucketMax\":118,\"count\":2},{\"bucketMax\":120,\"count\":1},{\"bucketMax\":122,\"count\":2},{\"bucketMax\":123,\"count\":1},{\"bucketMax\":124,\"count\":1},{\"bucketMax\":125,\"count\":1},{\"bucketMax\":126,\"count\":1},{\"bucketMax\":130,\"count\":1},{\"bucketMax\":132,\"count\":5},{\"bucketMax\":133,\"count\":1},{\"bucketMax\":135,\"count\":2},{\"bucketMax\":138,\"count\":1},{\"bucketMax\":139,\"count\":2},{\"bucketMax\":146,\"count\":1},{\"bucketMax\":148,\"count\":2},{\"bucketMax\":151,\"count\":1},{\"bucketMax\":155,\"count\":1},{\"bucketMax\":156,\"count\":1},{\"bucketMax\":158,\"count\":1},{\"bucketMax\":159,\"count\":1},{\"bucketMax\":163,\"count\":2},{\"bucketMax\":166,\"count\":1},{\"bucketMax\":167,\"count\":3},{\"bucketMax\":168,\"count\":1},{\"bucketMax\":171,\"count\":2},{\"bucketMax\":172,\"count\":1},{\"bucketMax\":174,\"count\":1},{\"bucketMax\":176,\"count\":1},{\"bucketMax\":177,\"count\":1},{\"bucketMax\":178,\"count\":2},{\"bucketMax\":183,\"count\":2},{\"bucketMax\":191,\"count\":1},{\"bucketMax\":196,\"count\":1},{\"bucketMax\":197,\"count\":2},{\"bucketMax\":198,\"count\":1},{\"bucketMax\":208,\"count\":1},{\"bucketMax\":214,\"count\":1},{\"bucketMax\":223,\"count\":1},{\"bucketMax\":225,\"count\":3},{\"bucketMax\":234,\"count\":1}]},\"Sort\":{\"cyclesExecutedBySolution\":[{\"bucketMax\":305,\"count\":1},{\"bucketMax\":360,\"count\":1},{\"bucketMax\":390,\"count\":1},{\"bucketMax\":398,\"count\":1},{\"bucketMax\":433,\"count\":1},{\"bucketMax\":486,\"count\":1},{\"bucketMax\":512,\"count\":1},{\"bucketMax\":565,\"count\":1},{\"bucketMax\":572,\"count\":1},{\"bucketMax\":599,\"count\":1},{\"bucketMax\":612,\"count\":1},{\"bucketMax\":624,\"count\":1},{\"bucketMax\":631,\"count\":2},{\"bucketMax\":639,\"count\":1},{\"bucketMax\":665,\"count\":1},{\"bucketMax\":695,\"count\":1},{\"bucketMax\":699,\"count\":1},{\"bucketMax\":711,\"count\":1},{\"bucketMax\":719,\"count\":1},{\"bucketMax\":720,\"count\":1},{\"bucketMax\":723,\"count\":1},{\"bucketMax\":724,\"count\":1},{\"bucketMax\":743,\"count\":1},{\"bucketMax\":757,\"count\":1},{\"bucketMax\":806,\"count\":1},{\"bucketMax\":810,\"count\":1},{\"bucketMax\":818,\"count\":1},{\"bucketMax\":835,\"count\":1},{\"bucketMax\":861,\"count\":1},{\"bucketMax\":862,\"count\":1},{\"bucketMax\":866,\"count\":1},{\"bucketMax\":886,\"count\":1},{\"bucketMax\":915,\"count\":1},{\"bucketMax\":924,\"count\":1},{\"bucketMax\":944,\"count\":1},{\"bucketMax\":959,\"count\":2},{\"bucketMax\":981,\"count\":1},{\"bucketMax\":1027,\"count\":1},{\"bucketMax\":1134,\"count\":1},{\"bucketMax\":1174,\"count\":1},{\"bucketMax\":1202,\"count\":2},{\"bucketMax\":1260,\"count\":1},{\"bucketMax\":1485,\"count\":1},{\"bucketMax\":1948,\"count\":1},{\"bucketMax\":2071,\"count\":1},{\"bucketMax\":2112,\"count\":1},{\"bucketMax\":5393,\"count\":1},{\"bucketMax\":6129,\"count\":1},{\"bucketMax\":11014,\"count\":1}],\"memoryBytesAccessedBySolution\":[{\"bucketMax\":87,\"count\":1},{\"bucketMax\":88,\"count\":1},{\"bucketMax\":95,\"count\":1},{\"bucketMax\":99,\"count\":1},{\"bucketMax\":113,\"count\":1},{\"bucketMax\":116,\"count\":1},{\"bucketMax\":121,\"count\":1},{\"bucketMax\":134,\"count\":1},{\"bucketMax\":139,\"count\":1},{\"bucketMax\":142,\"count\":1},{\"bucketMax\":145,\"count\":1},{\"bucketMax\":156,\"count\":1},{\"bucketMax\":157,\"count\":2},{\"bucketMax\":164,\"count\":2},{\"bucketMax\":168,\"count\":1},{\"bucketMax\":169,\"count\":1},{\"bucketMax\":171,\"count\":2},{\"bucketMax\":172,\"count\":1},{\"bucketMax\":174,\"count\":1},{\"bucketMax\":175,\"count\":1},{\"bucketMax\":176,\"count\":2},{\"bucketMax\":177,\"count\":1},{\"bucketMax\":178,\"count\":1},{\"bucketMax\":180,\"count\":1},{\"bucketMax\":182,\"count\":1},{\"bucketMax\":189,\"count\":1},{\"bucketMax\":192,\"count\":1},{\"bucketMax\":197,\"count\":3},{\"bucketMax\":199,\"count\":1},{\"bucketMax\":203,\"count\":2},{\"bucketMax\":209,\"count\":1},{\"bucketMax\":211,\"count\":1},{\"bucketMax\":213,\"count\":1},{\"bucketMax\":219,\"count\":2},{\"bucketMax\":224,\"count\":1},{\"bucketMax\":232,\"count\":1},{\"bucketMax\":234,\"count\":1},{\"bucketMax\":236,\"count\":1},{\"bucketMax\":241,\"count\":2},{\"bucketMax\":248,\"count\":1},{\"bucketMax\":250,\"count\":3}]},\"Mode\":{\"cyclesExecutedBySolution\":[{\"bucketMax\":310,\"count\":1},{\"bucketMax\":371,\"count\":1},{\"bucketMax\":405,\"count\":1},{\"bucketMax\":417,\"count\":1},{\"bucketMax\":437,\"count\":1},{\"bucketMax\":466,\"count\":1},{\"bucketMax\":489,\"count\":1},{\"bucketMax\":545,\"count\":1},{\"bucketMax\":625,\"count\":1},{\"bucketMax\":635,\"count\":1},{\"bucketMax\":669,\"count\":2},{\"bucketMax\":687,\"count\":2},{\"bucketMax\":731,\"count\":1},{\"bucketMax\":783,\"count\":1},{\"bucketMax\":786,\"count\":1},{\"bucketMax\":814,\"count\":1},{\"bucketMax\":977,\"count\":1},{\"bucketMax\":981,\"count\":1},{\"bucketMax\":1008,\"count\":1},{\"bucketMax\":1127,\"count\":1},{\"bucketMax\":1349,\"count\":1},{\"bucketMax\":1472,\"count\":2},{\"bucketMax\":1774,\"count\":1},{\"bucketMax\":2144,\"count\":1},{\"bucketMax\":2629,\"count\":1},{\"bucketMax\":2897,\"count\":1},{\"bucketMax\":2900,\"count\":1},{\"bucketMax\":2989,\"count\":2},{\"bucketMax\":3316,\"count\":1},{\"bucketMax\":3322,\"count\":1},{\"bucketMax\":3522,\"count\":1},{\"bucketMax\":3781,\"count\":1},{\"bucketMax\":6614,\"count\":1}],\"memoryBytesAccessedBySolution\":[{\"bucketMax\":101,\"count\":1},{\"bucketMax\":110,\"count\":1},{\"bucketMax\":122,\"count\":1},{\"bucketMax\":126,\"count\":1},{\"bucketMax\":130,\"count\":1},{\"bucketMax\":142,\"count\":1},{\"bucketMax\":152,\"count\":1},{\"bucketMax\":155,\"count\":1},{\"bucketMax\":158,\"count\":1},{\"bucketMax\":167,\"count\":2},{\"bucketMax\":171,\"count\":1},{\"bucketMax\":178,\"count\":1},{\"bucketMax\":186,\"count\":2},{\"bucketMax\":189,\"count\":1},{\"bucketMax\":190,\"count\":1},{\"bucketMax\":193,\"count\":1},{\"bucketMax\":196,\"count\":1},{\"bucketMax\":197,\"count\":2},{\"bucketMax\":201,\"count\":1},{\"bucketMax\":204,\"count\":1},{\"bucketMax\":206,\"count\":1},{\"bucketMax\":209,\"count\":1},{\"bucketMax\":216,\"count\":1},{\"bucketMax\":218,\"count\":2},{\"bucketMax\":228,\"count\":1},{\"bucketMax\":230,\"count\":2},{\"bucketMax\":235,\"count\":1},{\"bucketMax\":243,\"count\":1},{\"bucketMax\":251,\"count\":2},{\"bucketMax\":252,\"count\":1}]},\"Characters\":{\"cyclesExecutedBySolution\":[{\"bucketMax\":2,\"count\":39}],\"memoryBytesAccessedBySolution\":[{\"bucketMax\":7,\"count\":9},{\"bucketMax\":9,\"count\":30}]},\"Decimal Digits\":{\"cyclesExecutedBySolution\":[{\"bucketMax\":6,\"count\":1},{\"bucketMax\":8,\"count\":1},{\"bucketMax\":11,\"count\":37},{\"bucketMax\":13,\"count\":1}],\"memoryBytesAccessedBySolution\":[{\"bucketMax\":12,\"count\":3},{\"bucketMax\":13,\"count\":1},{\"bucketMax\":14,\"count\":3},{\"bucketMax\":15,\"count\":6},{\"bucketMax\":16,\"count\":26},{\"bucketMax\":18,\"count\":1}]},\"Uppercase\":{\"cyclesExecutedBySolution\":[{\"bucketMax\":14,\"count\":1},{\"bucketMax\":20,\"count\":1},{\"bucketMax\":39,\"count\":2},{\"bucketMax\":41,\"count\":1},{\"bucketMax\":45,\"count\":1},{\"bucketMax\":49,\"count\":1},{\"bucketMax\":50,\"count\":5},{\"bucketMax\":51,\"count\":1},{\"bucketMax\":52,\"count\":1},{\"bucketMax\":63,\"count\":1},{\"bucketMax\":65,\"count\":1},{\"bucketMax\":66,\"count\":2},{\"bucketMax\":67,\"count\":1},{\"bucketMax\":71,\"count\":1},{\"bucketMax\":73,\"count\":1},{\"bucketMax\":74,\"count\":1},{\"bucketMax\":76,\"count\":1},{\"bucketMax\":94,\"count\":1},{\"bucketMax\":106,\"count\":1}],\"memoryBytesAccessedBySolution\":[{\"bucketMax\":17,\"count\":1},{\"bucketMax\":18,\"count\":1},{\"bucketMax\":26,\"count\":1},{\"bucketMax\":28,\"count\":1},{\"bucketMax\":29,\"count\":3},{\"bucketMax\":31,\"count\":4},{\"bucketMax\":34,\"count\":1},{\"bucketMax\":37,\"count\":4},{\"bucketMax\":38,\"count\":1},{\"bucketMax\":41,\"count\":2},{\"bucketMax\":44,\"count\":1},{\"bucketMax\":45,\"count\":1},{\"bucketMax\":56,\"count\":1},{\"bucketMax\":58,\"count\":1},{\"bucketMax\":60,\"count\":1},{\"bucketMax\":66,\"count\":1}]},\"Strings\":{\"cyclesExecutedBySolution\":[{\"bucketMax\":14,\"count\":3},{\"bucketMax\":27,\"count\":4},{\"bucketMax\":33,\"count\":1},{\"bucketMax\":40,\"count\":31}],\"memoryBytesAccessedBySolution\":[{\"bucketMax\":21,\"count\":2},{\"bucketMax\":22,\"count\":2},{\"bucketMax\":23,\"count\":2},{\"bucketMax\":24,\"count\":1},{\"bucketMax\":25,\"count\":1},{\"bucketMax\":26,\"count\":31}]},\"Tokenizer\":{\"cyclesExecutedBySolution\":[{\"bucketMax\":103,\"count\":1},{\"bucketMax\":150,\"count\":1},{\"bucketMax\":168,\"count\":1},{\"bucketMax\":182,\"count\":5},{\"bucketMax\":183,\"count\":1},{\"bucketMax\":184,\"count\":1},{\"bucketMax\":189,\"count\":1},{\"bucketMax\":219,\"count\":3},{\"bucketMax\":220,\"count\":1},{\"bucketMax\":226,\"count\":5},{\"bucketMax\":227,\"count\":4},{\"bucketMax\":231,\"count\":1},{\"bucketMax\":233,\"count\":2},{\"bucketMax\":234,\"count\":1},{\"bucketMax\":241,\"count\":1},{\"bucketMax\":251,\"count\":1},{\"bucketMax\":257,\"count\":1},{\"bucketMax\":259,\"count\":1},{\"bucketMax\":264,\"count\":1},{\"bucketMax\":320,\"count\":1},{\"bucketMax\":498,\"count\":1}],\"memoryBytesAccessedBySolution\":[{\"bucketMax\":18,\"count\":2},{\"bucketMax\":22,\"count\":1},{\"bucketMax\":23,\"count\":2},{\"bucketMax\":24,\"count\":1},{\"bucketMax\":25,\"count\":1},{\"bucketMax\":26,\"count\":7},{\"bucketMax\":28,\"count\":2},{\"bucketMax\":30,\"count\":4},{\"bucketMax\":31,\"count\":3},{\"bucketMax\":32,\"count\":2},{\"bucketMax\":33,\"count\":1},{\"bucketMax\":36,\"count\":4},{\"bucketMax\":37,\"count\":1},{\"bucketMax\":38,\"count\":1},{\"bucketMax\":39,\"count\":2},{\"bucketMax\":83,\"count\":1}]},\"Parse Decimal\":{\"cyclesExecutedBySolution\":[{\"bucketMax\":23,\"count\":1},{\"bucketMax\":29,\"count\":1},{\"bucketMax\":47,\"count\":1},{\"bucketMax\":55,\"count\":1},{\"bucketMax\":58,\"count\":1},{\"bucketMax\":60,\"count\":2},{\"bucketMax\":61,\"count\":1},{\"bucketMax\":70,\"count\":1},{\"bucketMax\":71,\"count\":1},{\"bucketMax\":77,\"count\":1},{\"bucketMax\":78,\"count\":1},{\"bucketMax\":81,\"count\":1},{\"bucketMax\":82,\"count\":2},{\"bucketMax\":86,\"count\":1},{\"bucketMax\":94,\"count\":1},{\"bucketMax\":96,\"count\":2},{\"bucketMax\":98,\"count\":1},{\"bucketMax\":100,\"count\":1},{\"bucketMax\":101,\"count\":1},{\"bucketMax\":104,\"count\":1},{\"bucketMax\":106,\"count\":2},{\"bucketMax\":113,\"count\":1},{\"bucketMax\":116,\"count\":1},{\"bucketMax\":117,\"count\":1},{\"bucketMax\":129,\"count\":2},{\"bucketMax\":138,\"count\":1},{\"bucketMax\":160,\"count\":1}],\"memoryBytesAccessedBySolution\":[{\"bucketMax\":33,\"count\":1},{\"bucketMax\":34,\"count\":1},{\"bucketMax\":48,\"count\":2},{\"bucketMax\":51,\"count\":3},{\"bucketMax\":52,\"count\":3},{\"bucketMax\":53,\"count\":1},{\"bucketMax\":54,\"count\":2},{\"bucketMax\":56,\"count\":1},{\"bucketMax\":57,\"count\":1},{\"bucketMax\":58,\"count\":1},{\"bucketMax\":60,\"count\":1},{\"bucketMax\":63,\"count\":1},{\"bucketMax\":66,\"count\":1},{\"bucketMax\":67,\"count\":1},{\"bucketMax\":69,\"count\":2},{\"bucketMax\":70,\"count\":1},{\"bucketMax\":73,\"count\":2},{\"bucketMax\":76,\"count\":1},{\"bucketMax\":79,\"count\":1},{\"bucketMax\":80,\"count\":2},{\"bucketMax\":90,\"count\":1},{\"bucketMax\":91,\"count\":1},{\"bucketMax\":125,\"count\":1}]},\"Print Decimal\":{\"cyclesExecutedBySolution\":[{\"bucketMax\":43,\"count\":1},{\"bucketMax\":47,\"count\":1},{\"bucketMax\":49,\"count\":1},{\"bucketMax\":58,\"count\":1},{\"bucketMax\":62,\"count\":1},{\"bucketMax\":67,\"count\":1},{\"bucketMax\":70,\"count\":3},{\"bucketMax\":75,\"count\":1},{\"bucketMax\":78,\"count\":1},{\"bucketMax\":83,\"count\":1},{\"bucketMax\":96,\"count\":1},{\"bucketMax\":101,\"count\":1},{\"bucketMax\":118,\"count\":1},{\"bucketMax\":122,\"count\":1},{\"bucketMax\":124,\"count\":1},{\"bucketMax\":138,\"count\":1},{\"bucketMax\":143,\"count\":1},{\"bucketMax\":162,\"count\":1},{\"bucketMax\":166,\"count\":3},{\"bucketMax\":253,\"count\":1}],\"memoryBytesAccessedBySolution\":[{\"bucketMax\":37,\"count\":1},{\"bucketMax\":52,\"count\":1},{\"bucketMax\":64,\"count\":1},{\"bucketMax\":66,\"count\":1},{\"bucketMax\":68,\"count\":2},{\"bucketMax\":71,\"count\":1},{\"bucketMax\":73,\"count\":1},{\"bucketMax\":76,\"count\":1},{\"bucketMax\":85,\"count\":1},{\"bucketMax\":86,\"count\":1},{\"bucketMax\":90,\"count\":1},{\"bucketMax\":93,\"count\":1},{\"bucketMax\":95,\"count\":1},{\"bucketMax\":103,\"count\":2},{\"bucketMax\":112,\"count\":1},{\"bucketMax\":116,\"count\":1},{\"bucketMax\":117,\"count\":1},{\"bucketMax\":125,\"count\":1},{\"bucketMax\":154,\"count\":2},{\"bucketMax\":161,\"count\":1},{\"bucketMax\":186,\"count\":1}]},\"Calculator\":{\"cyclesExecutedBySolution\":[{\"bucketMax\":98,\"count\":1},{\"bucketMax\":150,\"count\":1},{\"bucketMax\":151,\"count\":1},{\"bucketMax\":159,\"count\":1},{\"bucketMax\":162,\"count\":1},{\"bucketMax\":194,\"count\":1},{\"bucketMax\":201,\"count\":1},{\"bucketMax\":214,\"count\":1},{\"bucketMax\":224,\"count\":1},{\"bucketMax\":235,\"count\":1},{\"bucketMax\":237,\"count\":1},{\"bucketMax\":246,\"count\":1},{\"bucketMax\":255,\"count\":1},{\"bucketMax\":270,\"count\":1},{\"bucketMax\":276,\"count\":1},{\"bucketMax\":308,\"count\":1},{\"bucketMax\":310,\"count\":1},{\"bucketMax\":311,\"count\":1},{\"bucketMax\":329,\"count\":1},{\"bucketMax\":345,\"count\":1},{\"bucketMax\":348,\"count\":1},{\"bucketMax\":354,\"count\":2},{\"bucketMax\":411,\"count\":1}],\"memoryBytesAccessedBySolution\":[{\"bucketMax\":78,\"count\":1},{\"bucketMax\":113,\"count\":1},{\"bucketMax\":121,\"count\":1},{\"bucketMax\":142,\"count\":1},{\"bucketMax\":144,\"count\":1},{\"bucketMax\":145,\"count\":1},{\"bucketMax\":154,\"count\":1},{\"bucketMax\":156,\"count\":1},{\"bucketMax\":158,\"count\":1},{\"bucketMax\":159,\"count\":1},{\"bucketMax\":161,\"count\":1},{\"bucketMax\":164,\"count\":2},{\"bucketMax\":166,\"count\":1},{\"bucketMax\":184,\"count\":3},{\"bucketMax\":186,\"count\":1},{\"bucketMax\":187,\"count\":1},{\"bucketMax\":205,\"count\":1},{\"bucketMax\":221,\"count\":1},{\"bucketMax\":222,\"count\":1},{\"bucketMax\":230,\"count\":1},{\"bucketMax\":249,\"count\":1}]},\"Multi-Line Strings\":{\"cyclesExecutedBySolution\":[{\"bucketMax\":24,\"count\":1},{\"bucketMax\":69,\"count\":1},{\"bucketMax\":71,\"count\":1},{\"bucketMax\":116,\"count\":4},{\"bucketMax\":117,\"count\":2},{\"bucketMax\":118,\"count\":1},{\"bucketMax\":140,\"count\":2},{\"bucketMax\":141,\"count\":1},{\"bucketMax\":142,\"count\":3},{\"bucketMax\":143,\"count\":2},{\"bucketMax\":144,\"count\":1},{\"bucketMax\":145,\"count\":3},{\"bucketMax\":149,\"count\":1},{\"bucketMax\":163,\"count\":1},{\"bucketMax\":167,\"count\":1}],\"memoryBytesAccessedBySolution\":[{\"bucketMax\":18,\"count\":2},{\"bucketMax\":19,\"count\":1},{\"bucketMax\":23,\"count\":2},{\"bucketMax\":25,\"count\":2},{\"bucketMax\":26,\"count\":3},{\"bucketMax\":27,\"count\":3},{\"bucketMax\":30,\"count\":3},{\"bucketMax\":31,\"count\":3},{\"bucketMax\":32,\"count\":1},{\"bucketMax\":33,\"count\":1},{\"bucketMax\":34,\"count\":1},{\"bucketMax\":36,\"count\":3}]},\"Parse Data Directives\":{\"cyclesExecutedBySolution\":[{\"bucketMax\":55,\"count\":1},{\"bucketMax\":69,\"count\":1},{\"bucketMax\":73,\"count\":1},{\"bucketMax\":76,\"count\":1},{\"bucketMax\":83,\"count\":1},{\"bucketMax\":88,\"count\":1},{\"bucketMax\":94,\"count\":1},{\"bucketMax\":131,\"count\":1},{\"bucketMax\":137,\"count\":1},{\"bucketMax\":143,\"count\":2},{\"bucketMax\":154,\"count\":1},{\"bucketMax\":176,\"count\":2},{\"bucketMax\":188,\"count\":1},{\"bucketMax\":190,\"count\":1},{\"bucketMax\":193,\"count\":1},{\"bucketMax\":198,\"count\":1},{\"bucketMax\":205,\"count\":2},{\"bucketMax\":208,\"count\":1},{\"bucketMax\":216,\"count\":1}],\"memoryBytesAccessedBySolution\":[{\"bucketMax\":50,\"count\":1},{\"bucketMax\":73,\"count\":1},{\"bucketMax\":87,\"count\":1},{\"bucketMax\":90,\"count\":1},{\"bucketMax\":99,\"count\":1},{\"bucketMax\":107,\"count\":1},{\"bucketMax\":112,\"count\":1},{\"bucketMax\":113,\"count\":1},{\"bucketMax\":114,\"count\":1},{\"bucketMax\":120,\"count\":1},{\"bucketMax\":129,\"count\":1},{\"bucketMax\":132,\"count\":1},{\"bucketMax\":135,\"count\":1},{\"bucketMax\":136,\"count\":1},{\"bucketMax\":137,\"count\":2},{\"bucketMax\":142,\"count\":1},{\"bucketMax\":143,\"count\":1},{\"bucketMax\":155,\"count\":1},{\"bucketMax\":158,\"count\":1},{\"bucketMax\":168,\"count\":1},{\"bucketMax\":171,\"count\":1}]},\"Parse Subleq Instructions\":{\"cyclesExecutedBySolution\":[{\"bucketMax\":158,\"count\":1},{\"bucketMax\":180,\"count\":1},{\"bucketMax\":181,\"count\":1},{\"bucketMax\":221,\"count\":1},{\"bucketMax\":238,\"count\":1},{\"bucketMax\":263,\"count\":1},{\"bucketMax\":317,\"count\":1},{\"bucketMax\":338,\"count\":2},{\"bucketMax\":341,\"count\":1},{\"bucketMax\":361,\"count\":1},{\"bucketMax\":407,\"count\":1},{\"bucketMax\":421,\"count\":1},{\"bucketMax\":423,\"count\":1},{\"bucketMax\":451,\"count\":1},{\"bucketMax\":499,\"count\":1},{\"bucketMax\":514,\"count\":1},{\"bucketMax\":517,\"count\":1},{\"bucketMax\":534,\"count\":1},{\"bucketMax\":596,\"count\":1},{\"bucketMax\":1014,\"count\":1},{\"bucketMax\":2213,\"count\":1}],\"memoryBytesAccessedBySolution\":[{\"bucketMax\":49,\"count\":1},{\"bucketMax\":59,\"count\":1},{\"bucketMax\":73,\"count\":1},{\"bucketMax\":79,\"count\":1},{\"bucketMax\":83,\"count\":1},{\"bucketMax\":89,\"count\":1},{\"bucketMax\":93,\"count\":1},{\"bucketMax\":94,\"count\":1},{\"bucketMax\":103,\"count\":1},{\"bucketMax\":108,\"count\":1},{\"bucketMax\":109,\"count\":1},{\"bucketMax\":116,\"count\":1},{\"bucketMax\":118,\"count\":2},{\"bucketMax\":125,\"count\":1},{\"bucketMax\":126,\"count\":1},{\"bucketMax\":130,\"count\":1},{\"bucketMax\":135,\"count\":1},{\"bucketMax\":152,\"count\":1},{\"bucketMax\":158,\"count\":1},{\"bucketMax\":171,\"count\":1},{\"bucketMax\":174,\"count\":1}]},\"Self-Hosting\":{\"cyclesExecutedBySolution\":[{\"bucketMax\":335,\"count\":1},{\"bucketMax\":414,\"count\":1},{\"bucketMax\":438,\"count\":1},{\"bucketMax\":492,\"count\":1},{\"bucketMax\":630,\"count\":1},{\"bucketMax\":652,\"count\":1},{\"bucketMax\":681,\"count\":1},{\"bucketMax\":708,\"count\":1},{\"bucketMax\":848,\"count\":3},{\"bucketMax\":857,\"count\":1},{\"bucketMax\":892,\"count\":1},{\"bucketMax\":945,\"count\":1},{\"bucketMax\":974,\"count\":1},{\"bucketMax\":1063,\"count\":1},{\"bucketMax\":1157,\"count\":1},{\"bucketMax\":1343,\"count\":1},{\"bucketMax\":1561,\"count\":2},{\"bucketMax\":1836,\"count\":1}],\"memoryBytesAccessedBySolution\":[{\"bucketMax\":170,\"count\":1},{\"bucketMax\":178,\"count\":1},{\"bucketMax\":180,\"count\":1},{\"bucketMax\":181,\"count\":1},{\"bucketMax\":187,\"count\":1},{\"bucketMax\":190,\"count\":1},{\"bucketMax\":195,\"count\":1},{\"bucketMax\":196,\"count\":2},{\"bucketMax\":202,\"count\":3},{\"bucketMax\":205,\"count\":1},{\"bucketMax\":206,\"count\":1},{\"bucketMax\":207,\"count\":1},{\"bucketMax\":224,\"count\":1},{\"bucketMax\":240,\"count\":1},{\"bucketMax\":244,\"count\":1},{\"bucketMax\":246,\"count\":2},{\"bucketMax\":252,\"count\":1}]},\"Self-Hosting Part 2\":{\"cyclesExecutedBySolution\":[{\"bucketMax\":989,\"count\":1},{\"bucketMax\":1105,\"count\":1},{\"bucketMax\":1641,\"count\":1},{\"bucketMax\":1910,\"count\":1},{\"bucketMax\":2095,\"count\":1},{\"bucketMax\":2693,\"count\":1}],\"memoryBytesAccessedBySolution\":[{\"bucketMax\":203,\"count\":1},{\"bucketMax\":216,\"count\":1},{\"bucketMax\":228,\"count\":1},{\"bucketMax\":229,\"count\":1},{\"bucketMax\":242,\"count\":1},{\"bucketMax\":243,\"count\":1}]}}};\n\nexport { steamStatsCache, webStatsCache };\n", "sic1/client/ts/language-selector.tsx": "import React from \"react\";\nimport { FormattedMessage } from \"react-intl\";\nimport { localeToLanguageName } from \"./language-data\";\n\nconst defaultLocaleValue = \"_\";\n\nexport interface LanguageSelectorProps {\n    locale: string | undefined;\n    defaultLocale: string;\n    onLanguageUpdated: (locale: string) => void;\n}\n\nexport class LanguageSelector extends React.Component<LanguageSelectorProps> {\n    private select = React.createRef<HTMLSelectElement>();\n\n    public render(): React.ReactNode {\n        return <select\n            ref={this.select}\n            defaultValue={this.props.locale ?? defaultLocaleValue}\n            onChange={(event) => {\n                const value = event.currentTarget.value;\n                const locale: string | undefined = (value === defaultLocaleValue) ? undefined : value;\n                this.props.onLanguageUpdated(locale);\n            }}\n            >\n                <option value={defaultLocaleValue}>\n                    <FormattedMessage\n                        id=\"languageDefault\"\n                        description=\"Text shown in the language selector for the default language\"\n                        defaultMessage=\"Default ({defaultLanguage})\"\n                        values={{ defaultLanguage: localeToLanguageName[this.props.defaultLocale] }}\n                        />\n                </option>\n            {Object\n                .entries(localeToLanguageName)\n                .filter(([locale]) => (locale !== this.props.defaultLocale))\n                .map(([locale, languageName]) =>\n                <option\n                    key={locale}\n                    value={locale}\n                    >\n                        <FormattedMessage\n                            id=\"languageOption\"\n                            description=\"Text shown in the language selector for each language, using its native name (e.g. 'English') and locale string (e.g. 'en')\"\n                            defaultMessage=\"{name} ({locale})\"\n                            values={{\n                                name: languageName,\n                                locale,\n                            }}\n                            />\n                </option>\n            )}\n        </select>;\n    }\n}\n", "sic1/client/ts/mail-shared.tsx": "import { Contact } from \"./contacts\";\nimport { PuzzleListTypes } from \"./puzzle-list\";\nimport { Shared } from \"./shared\";\n\nexport interface MailContext {\n    // Mail-specific context\n    from: Contact;\n\n    // Global context\n    self: Contact;\n    jobTitles: typeof Shared.jobTitles,\n}\n\ninterface AllMailData {\n    to?: Readonly<string[]>;\n    from: Contact;\n    create: (context: MailContext) => React.ReactNode;\n    unimportant?: boolean;\n\n    loadLabel?: string;\n    loadType?: PuzzleListTypes;\n\n    actions?: Readonly<string[]>;\n}\n\nexport type PuzzleMailData = AllMailData & {\n    loadType: \"puzzle\";\n};\n\nexport type NonPuzzleMailData = AllMailData & {\n    subject: React.ReactNode;\n};\n\nexport type MailData = PuzzleMailData | NonPuzzleMailData;\n\nexport type Mail = MailData & {\n    id: string;\n    solvedCount?: number;\n};\n", "sic1/client/ts/root.tsx": "import { Assembler, Command, CompilationError } from \"../../../lib/src/sic1asm\";\nimport { puzzleCount } from \"../../shared/puzzles\";\nimport { Platform } from \"./platform\";\nimport { menuBehavior, MessageBox, MessageBoxContent } from \"./message-box\";\nimport { Shared } from \"./shared\";\nimport { TextButton } from \"./text-button\";\nimport { Sic1DataManager } from \"./data-manager\";\nimport { Sic1WebService, StatChanges } from \"./service\";\nimport { Sic1Ide } from \"./ide\";\nimport { addMailForPuzzle, ensureSolutionStatsMailUnread, hasUnreadMail, migrateInbox, updateSessionStats } from \"./mail\";\nimport { MailViewer } from \"./mail-viewer\";\nimport licenses from \"./licenses\";\nimport React from \"react\";\nimport { PuzzleList, PuzzleListTypes } from \"./puzzle-list\";\nimport { Music, SongId } from \"./music\";\nimport { SoundEffects } from \"./sound-effects\";\nimport { Button } from \"./button\";\nimport { Achievement, achievements, jobTitleAchievementIds } from \"./achievements\";\nimport { AvoisionUI } from \"./avoision-ui\";\nimport { Toaster } from \"./toaster\";\nimport { loadImageAsync } from \"./image-cache\";\nimport packageJson from \"../package.json\";\nimport { ColorScheme, colorSchemeNames } from \"./colors\";\nimport { ClientPuzzle, ClientPuzzleGroup, initializePuzzles } from \"./puzzles\";\nimport { CopyToClipboardButton } from \"./button-clipboard\";\nimport { ButtonWithResult } from \"./button-result\";\nimport { FormattedMessage, IntlShape } from \"react-intl\";\nimport { LanguageSelector } from \"./language-selector\";\n\nexport type InitialPage = \"puzzleList\" | \"presentationSettings\";\n\nfunction Link(props: { title: string, link: string }) {\n    const { title, link } = props;\n    return <span>{title}</span>;\n}\n\ninterface Sic1UserProfileFormProps {\n    intl: IntlShape;\n    onCompleted: (name: string, uploadName: boolean) => void;\n}\n\nclass Sic1UserProfileForm extends React.Component<Sic1UserProfileFormProps> {\n    private inputName = React.createRef<HTMLInputElement>();\n    private inputUploadName = React.createRef<HTMLInputElement>();\n\n    public submit() {\n        this.props.onCompleted(this.inputName.current.value, this.inputUploadName.current.checked);\n    }\n\n    public render(): React.ReactNode {\n        const data = Sic1DataManager.getData();\n\n        return <form onSubmit={(event) => {\n                event.preventDefault();\n                this.submit();\n            }}>\n                <label><FormattedMessage\n                    id=\"introLabelName\"\n                    description=\"Label for user name on the introductory form\"\n                    defaultMessage=\"Name:\"/> <input\n                    ref={this.inputName}\n                    autoFocus={true}\n                    maxLength={Sic1WebService.userNameMaxLength}\n                    defaultValue={data.name || this.props.intl.formatMessage({\n                        id: \"defaultName\",\n                        description: \"Default user name (only used in web version)\",\n                        defaultMessage: \"Bill\",\n                    })}\n                    /></label>\n                <p><label><input\n                    ref={this.inputUploadName} type=\"checkbox\"\n                    defaultChecked={(typeof(data.uploadName) === \"boolean\") ? data.uploadName : true}\n                    /> <FormattedMessage\n                        id=\"checkboxShareName\"\n                        description=\"Explanatory text for checkbox that opts into showing the player's name in public leaderboards\"\n                        defaultMessage=\"Show my name in public leaderboards (if unchecked, your statistics will be shown without a name)\"/></label></p>\n            </form>;\n    }\n}\n\nconst importSaveDataButtonText = <FormattedMessage\n    id=\"buttonSaveDataImport\"\n    description=\"Text shown on the 'import save data' button\"\n    defaultMessage=\"Import Save Data\"\n    />;\n\nclass Sic1SaveDataImportForm extends React.Component<{ onImport: (compressed: string) => void }> {\n    private input = React.createRef<HTMLTextAreaElement>();\n\n    public render(): React.ReactNode {\n        return <>\n            <p>\n                <FormattedMessage\n                    id=\"textSaveDataImport\"\n                    description=\"Instructional text shown in the 'import save data' window\"\n                    defaultMessage=\"Paste in your previously exported save data string here:\"\n                    />\n            </p>\n            <textarea ref={this.input} className=\"saveData\"></textarea>\n            <Button onClick={() => this.props.onImport(this.input.current?.value)}>{importSaveDataButtonText}</Button>\n        </>;\n    }\n}\n\ninterface ZoomSliderProps {\n    zoom: number;\n    onZoomUpdated: (zoom: number) => void;\n}\n\nclass ZoomSlider extends React.Component<ZoomSliderProps> {\n    constructor(props) {\n        super(props);\n    }\n\n    public render(): React.ReactNode {\n        return <label>\n            <FormattedMessage\n                id=\"sliderZoom\"\n                description=\"Label for the text size slider\"\n                defaultMessage=\"Zoom:\"\n                />\n            &nbsp;\n            <input\n                type=\"range\"\n                min={0.6}\n                max={2}\n                step={0.2}\n                defaultValue={`${this.props.zoom}`}\n                onChange={(event) => this.props.onZoomUpdated(parseFloat(event.currentTarget.value))}\n                />\n        </label>;\n    }\n}\n\ninterface Sic1CheckboxInstanceProps {\n    intl: IntlShape;\n    position: \"left\" | \"right\";\n    value: boolean;\n    onUpdated: (value: boolean) => void;\n}\n\ntype Sic1CheckboxProps = Sic1CheckboxInstanceProps & {\n    labelAfter: string;\n    labelBefore: string;\n}\n\nclass Sic1Checkbox extends React.Component<Sic1CheckboxProps> {\n    public render(): React.ReactNode {\n        const checkbox = <input\n            className={this.props.position}\n            type=\"checkbox\"\n            onChange={(event) => this.props.onUpdated(event.currentTarget.checked)}\n            defaultChecked={this.props.value}\n            />;\n\n        if (this.props.position === \"left\") {\n            return <label>{checkbox} {this.props.labelAfter}</label>;\n        } else {\n            return <label>{this.props.labelBefore}: {checkbox}</label>;\n        }\n    }\n}\n\nclass Sic1SoundCheckbox extends React.Component<Sic1CheckboxInstanceProps> {\n    public render(): React.ReactNode {\n        const { intl } = this.props;\n        return <Sic1Checkbox\n            labelBefore={intl.formatMessage({\n                id: \"checkboxSoundEffectsBefore\",\n                description: \"Label for sound effects checkbox, when appearing before the checkbox\",\n                defaultMessage: \"Sound effects\",\n            })}\n            labelAfter={intl.formatMessage({\n                id: \"checkboxSoundEffectsAfter\",\n                description: \"Label for the sound effects checkbox, when appearing after the checkbox\",\n                defaultMessage: \"Enable sound effects\",\n             })} {...this.props} />;\n    }\n}\n\nclass Sic1MusicCheckbox extends React.Component<Sic1CheckboxInstanceProps> {\n    public render(): React.ReactNode {\n        const { intl } = this.props;\n        return <Sic1Checkbox\n            labelBefore={intl.formatMessage({\n                id: \"checkboxMusicBefore\",\n                description: \"Label for music checkbox, when appearing before the checkbox\",\n                defaultMessage: \"Music\",\n            })}\n            labelAfter={intl.formatMessage({\n                id: \"checkboxMusicAfter\",\n                description: \"Label for the music checkbox, when appearing after the checkbox\",\n                defaultMessage: \"Enable music\",\n            })} {...this.props} />;\n    }\n}\n\ninterface Sic1PresentationSettingsProps {\n    intl: IntlShape;\n    locale: string | undefined; // If undefined, use defaultLocale\n    defaultLocale: string;\n    onLanguageUpdated: (locale: string) => void;\n\n    fullscreen: boolean;\n    onFullscreenUpdated: (fullscreen: boolean) => void;\n    zoom: number;\n    onZoomUpdated: (zoom: number) => void;\n    colorScheme: ColorScheme;\n    onColorSchemeUpdated: (colorScheme: ColorScheme) => void;\n\n    soundEffects: boolean;\n    onSoundEffectsUpdated: (soundEffects: boolean) => void;\n    soundVolume: number;\n    onSoundVolumeUpdated: (volume: number) => void;\n\n    music: boolean;\n    onMusicUpdated: (music: boolean) => void;\n    musicVolume: number;\n    onMusicVolumeUpdated: (volume: number) => void;\n}\n\nclass Sic1PresentationSettings extends React.Component<Sic1PresentationSettingsProps> {\n    public render(): React.ReactNode {\n        const { intl } = this.props;\n        return <>\n            <form onSubmit={(event) => event.preventDefault()}>\n                <label>\n                    <FormattedMessage\n                        id=\"selectLanguage\"\n                        description=\"Label for the 'language selection' dropdown menu\"\n                        defaultMessage=\"Language:\"\n                        />\n                    &nbsp;\n                    <LanguageSelector\n                        locale={this.props.locale}\n                        defaultLocale={this.props.defaultLocale}\n                        onLanguageUpdated={this.props.onLanguageUpdated}\n                        />\n                </label>\n                <br/>\n                <label>\n                    <FormattedMessage\n                        id=\"checkboxFullscreen\"\n                        description=\"Label for the 'full screen' checkbox toggle\"\n                        defaultMessage=\"Full screen:\"\n                        />\n                    &nbsp;\n                    <input\n                    className=\"right\"\n                    type=\"checkbox\"\n                    defaultChecked={this.props.fullscreen && Platform.fullscreen.get()}\n                    onChange={(event) => this.props.onFullscreenUpdated(event.currentTarget.checked) }\n                    /></label>\n                <ZoomSlider\n                    zoom={this.props.zoom}\n                    onZoomUpdated={this.props.onZoomUpdated}\n                    />\n                <label>\n                    <FormattedMessage\n                        id=\"selectColorScheme\"\n                        description=\"Label for the 'color scheme' dropdown menu\"\n                        defaultMessage=\"Color scheme:\"\n                        />\n                    &nbsp;\n                    <select\n                        onChange={(event) => this.props.onColorSchemeUpdated(event.currentTarget.value as ColorScheme)}\n                        defaultValue={this.props.colorScheme}\n                        >\n                        {colorSchemeNames.map(name => <option key={name} value={name}>{(() => {\n                            switch (name) {\n                                case \"White on Black\":\n                                    return <FormattedMessage\n                                        id=\"colorSchemeWhite on Black\"\n                                        description=\"Display name for the 'White on Black' color scheme\"\n                                        defaultMessage=\"White on Black\"\n                                        />;\n\n                                case \"Black on White\":\n                                    return <FormattedMessage\n                                        id=\"colorSchemeBlack on White\"\n                                        description=\"Display name for the 'Black on White' color scheme\"\n                                        defaultMessage=\"Black on White\"\n                                        />;\n\n                                case \"Green Phosphor\":\n                                    return <FormattedMessage\n                                        id=\"colorSchemeGreen Phosphor\"\n                                        description=\"Display name for the 'Green Phosphor' color scheme\"\n                                        defaultMessage=\"Green Phosphor\"\n                                        />;\n\n                                case \"Amber Phosphor\":\n                                    return <FormattedMessage\n                                        id=\"colorSchemeAmber Phosphor\"\n                                        description=\"Display name for the 'Amber Phosphor' color scheme\"\n                                        defaultMessage=\"Amber Phosphor\"\n                                        />;\n\n                                default:\n                                    return <FormattedMessage\n                                        id=\"colorSchemeDefault\"\n                                        description=\"Display name for the 'Default' color scheme\"\n                                        defaultMessage=\"Default\"\n                                        />;\n                            }\n                        })()}</option>)}\n                    </select>\n                </label>\n                <br/>\n                <Sic1SoundCheckbox intl={intl} position=\"right\" value={this.props.soundEffects} onUpdated={this.props.onSoundEffectsUpdated} />\n                <label>\n                    <FormattedMessage\n                        id=\"sliderSoundVolume\"\n                        description=\"Label for the 'sound effects volume' slider\"\n                        defaultMessage=\"Sound effects volume:\"\n                        />\n                    &nbsp;\n                    <input\n                        type=\"range\"\n                        min={0}\n                        max={1}\n                        step={0.1}\n                        disabled={false}\n                        defaultValue={`${this.props.soundVolume}`}\n                        onChange={(event) => { this.props.onSoundVolumeUpdated(parseFloat(event.currentTarget.value)) } }\n                        />\n                </label>\n                <br/>\n\n            </form>\n        </>;\n    }\n}\n\ninterface Sic1RootProps extends Sic1PresentationSettingsProps {\n    intl: IntlShape;\n    onRestart: () => void;\n    initialPage: InitialPage;\n}\n\ninterface Sic1RootPuzzleState {\n    puzzle: ClientPuzzle;\n    solutionName: string;\n    defaultCode: string;\n}\n\ninterface Sic1RootState extends Sic1RootPuzzleState {\n    messageBoxQueue: MessageBoxContent[];\n    previousFocus: (string | Element)[]; // Element's id, or the element itself, if no id\n    clientPuzzlesGrouped: ClientPuzzleGroup[];\n    puzzleFlatArray: ClientPuzzle[];\n    clientPuzzles: ClientPuzzle[];\n    titleToClientPuzzle: { [title: string]: ClientPuzzle };\n    puzzleSandbox: ClientPuzzle;\n}\n\nexport class Sic1Root extends React.Component<Sic1RootProps, Sic1RootState> {\n    private static readonly manualMailId = \"s0_0\";\n    private static readonly devEnvMailId = \"s0_1\";\n    private readonly warningPeriodMS = 1000;\n\n    private ide = React.createRef<Sic1Ide>();\n    private toaster = React.createRef<Toaster>();\n    private userProfileForm = React.createRef<Sic1UserProfileForm>();\n    private mailViewer = React.createRef<MailViewer>();\n    private achievements: { [achievement: string]: boolean } = {};\n\n    constructor(props) {\n        super(props);\n\n        // User data migration\n        migrateInbox();\n\n        // Load previous puzzle, if available\n        const { clientPuzzles, ...otherPuzzleInfo } = initializePuzzles(this.props.intl);\n        const previousPuzzleTitle = Sic1DataManager.getData().currentPuzzle;\n        const puzzle = clientPuzzles.find(p => p.title === previousPuzzleTitle) ?? clientPuzzles[0];\n        const { currentSolutionName } = Sic1DataManager.getPuzzleData(puzzle.title);\n        const { solution } = Sic1DataManager.getPuzzleDataAndSolution(puzzle.title, currentSolutionName, true);\n        const { defaultCode } = Sic1Root.getStateForPuzzle(puzzle, solution.name);\n\n        this.state = {\n            ...otherPuzzleInfo,\n            clientPuzzles,\n            puzzle,\n            solutionName: solution.name,\n            defaultCode,\n            messageBoxQueue: [],\n            previousFocus: [],\n        }\n    }\n\n    private static wrapComments(code: string): string {\n        const maxLineLength = 68;\n        const lines = code.split(\"\\n\");\n        const result: string[] = [];\n        const addCommentPrefix = (s: string) => `; ${s}`;\n        for (const line of lines) {\n            if (line.startsWith(\"; \") && line.charAt(2) !== \" \") {\n                let l = line.replace(/^;[ ]*/, \"\");\n                while (true) {\n                    if (l.length <= maxLineLength) {\n                        result.push(addCommentPrefix(l));\n                        break;\n                    }\n    \n                    const end = l.lastIndexOf(\" \", maxLineLength - 1);\n                    if (end < 0) {\n                        result.push(addCommentPrefix(l));\n                        break;\n                    }\n    \n                    result.push(addCommentPrefix(l.substring(0, end)));\n                    l = l.substring(end + 1);\n                }\n            } else {\n                result.push(line);\n            }\n        }\n        return result.join(\"\\n\");\n    }\n\n    private static getUnmodifiedCode(puzzle: ClientPuzzle) {\n        const prewrappedCode = puzzle.code || `; ${puzzle.description}\\n`;\n        return Sic1Root.wrapComments(prewrappedCode);\n    }\n\n    private static getDefaultCode(puzzle: ClientPuzzle, solutionName: string) {\n        // Load progress (or fallback to default)\n        const { solution } = Sic1DataManager.getPuzzleDataAndSolution(puzzle.title, solutionName, false);\n        let code = solution?.code;\n        if (code === undefined || code === null) {\n            code = Sic1Root.getUnmodifiedCode(puzzle);\n        }\n        return code;\n    }\n\n    private static getStateForPuzzle(puzzle: ClientPuzzle, solutionName: string): Sic1RootPuzzleState {\n        return {\n            puzzle,\n            solutionName,\n            defaultCode: Sic1Root.getDefaultCode(puzzle, solutionName),\n        };\n    }\n\n    private playSoundCorrect = Shared.createFunctionWithMinimumPeriod(() => SoundEffects.play(\"correct\"), 50);\n\n    private playSoundIncorrect(): void {\n        SoundEffects.stop(\"correct\");\n        SoundEffects.play(\"incorrect\");\n    }\n\n    private playSoundCompleted(): void {\n        SoundEffects.stop(\"correct\");\n        SoundEffects.play(\"completed\");\n    }\n\n    private saveProgress(): void {\n        if (this.ide.current) {\n            const { puzzle, solutionName } = this.state;\n            let code = this.ide.current.getCode();\n            if (code === Sic1Root.getUnmodifiedCode(puzzle)) {\n                code = null;\n            }\n\n            const { solution } = Sic1DataManager.getPuzzleDataAndSolution(puzzle.title, solutionName, false);\n            if (solution && (solution.code !== code)) {\n                solution.code = code;\n\n                // Also invalidate metrics\n                solution.solutionCycles = undefined;\n                solution.solutionBytes = undefined;\n\n                Sic1DataManager.savePuzzleData(puzzle.title);\n            }\n        }\n    }\n\n    private loadPuzzle(puzzle: ClientPuzzle, solutionName: string): void {\n        // Save progress on previous puzzle\n        this.saveProgress();\n\n        // Save as last open puzzle\n        const data = Sic1DataManager.getData();\n        if (data.currentPuzzle !== puzzle.title) {\n            data.currentPuzzle = puzzle.title;\n            Sic1DataManager.saveData();\n        }\n\n        // Mark new puzzle as viewed\n        const puzzleData = Sic1DataManager.getPuzzleData(puzzle.title);\n        let puzzleDataModified = false;\n        if (!puzzleData.viewed) {\n            puzzleData.viewed = true;\n            puzzleDataModified = true;\n        }\n\n        // Mark as last open solution for this puzzle\n        if (puzzleData.currentSolutionName !== solutionName) {\n            puzzleData.currentSolutionName = solutionName;\n            puzzleDataModified = true;\n        }\n\n        if (puzzleDataModified) {\n            Sic1DataManager.savePuzzleData(puzzle.title);\n        }\n\n        this.setState(Sic1Root.getStateForPuzzle(puzzle, solutionName));\n        if (this.ide.current) {\n            this.ide.current.reset(puzzle, solutionName);\n        }\n\n        this.messageBoxClear();\n    }\n\n    private recordAchievement(achievement: Achievement): void {\n        // Note: This is not persisted and is only for this session\n        const achievements = this.achievements;\n        if (achievements[achievement] !== true) {\n            achievements[achievement] = true;\n        }\n    }\n\n    private async showAchievementNotificationAsync(achievement: Achievement): Promise<void> {\n        const achievementInfo = achievements[achievement];\n        const image = await loadImageAsync(achievementInfo.imageUri, 64, 64);\n        if (this.toaster.current) {\n            this.toaster.current.enqueue({\n                image,\n                title: <FormattedMessage\n                    id=\"achievementPopUpTitle\"\n                    description=\"Title of the 'achievement unlocked' pop-up message\"\n                    defaultMessage=\"Achievement Unlocked\"\n                    />,\n                text: achievementInfo.title,\n            });\n        }\n    }\n\n    private ensureAchievement(achievement: Achievement): void {\n        if (this.achievements[achievement] === true) {\n            return;\n        }\n\n        Platform.setAchievementAsync(achievement).then(newlyAchieved => {\n            this.recordAchievement(achievement);\n\n            if (newlyAchieved && Platform.shouldShowAchievementNotification?.()) {\n                this.showAchievementNotificationAsync(achievement);\n            }\n        });\n    }\n\n    private ensureJobTitleAchievements(): void {\n        const data = Sic1DataManager.getData();\n        for (let i = 1; i < Shared.jobTitles.length && (i - 1) < jobTitleAchievementIds.length; i++) {\n            const job = Shared.jobTitles[i];\n            if (job.minimumSolved <= data.solvedCount) {\n                this.ensureAchievement(jobTitleAchievementIds[i - 1]);\n            } else {\n                break;\n            }\n        }\n\n        // Check for new ending achievement\n        if (data.solvedCount >= puzzleCount) {\n            this.ensureAchievement(\"NEW_END\");\n        }\n    }\n\n    private checkForSolutionAchievements(): void {\n        // Ensure job title-associated achievements are set\n        this.ensureJobTitleAchievements();\n\n        // Check for time-based achievements\n        const now = new Date();\n        if (now.getHours() < 6) {\n            this.ensureAchievement(\"TIME_EARLY\");\n        } else if (now.getHours() >= 21) {\n            this.ensureAchievement(\"TIME_LATE\");\n        }\n\n        // Check for \"no subleq\" achievement\n        if (this.state.puzzle.title === \"Addition\") {\n            const noSubleq = this.ide.current.getCode()\n                .split(\"\\n\")\n                .map(line => Assembler.parseLine(line).command)\n                .every(command => (command !== Command.subleqInstruction));\n\n            if (noSubleq) {\n                this.ensureAchievement(\"OMIT_SUBLEQ\");\n            }\n        }\n    }\n\n    private puzzleCompleted(cycles: number, bytes: number, programBytes: number[]): void {\n        // Mark as solved in persistent state\n        const { puzzle, solutionName } = this.state;\n        const { puzzleData, solution } = Sic1DataManager.getPuzzleDataAndSolution(puzzle.title, solutionName, false);\n        const data = Sic1DataManager.getData();\n        const solvedCountOld = data.solvedCount;\n        const cyclesOld = puzzleData.solutionCycles;\n        const bytesOld = puzzleData.solutionBytes;\n\n        let puzzleDataModified = false;\n        if (!puzzleData.solved) {\n            data.solvedCount = Math.min(puzzleCount, data.solvedCount + 1);\n\n            puzzleData.solved = true;\n            puzzleData.solutionCycles = cycles;\n            puzzleData.solutionBytes = bytes;\n\n            Sic1DataManager.saveData();\n            puzzleDataModified = true;\n        } else if (cycles < puzzleData.solutionCycles || bytes < puzzleData.solutionBytes) {\n            puzzleData.solutionCycles = Math.min(puzzleData.solutionCycles, cycles);\n            puzzleData.solutionBytes = Math.min(puzzleData.solutionBytes, bytes);\n            puzzleDataModified = true;\n        }\n\n        if (solution && ((cycles !== solution.solutionCycles) || (bytes !== solution.solutionBytes))) {\n            solution.solutionCycles = cycles;\n            solution.solutionBytes = bytes;\n            puzzleDataModified = true;\n        }\n\n        if (puzzleDataModified) {\n            Sic1DataManager.savePuzzleData(puzzle.title);\n        }\n\n        // Prepare a list of potential changes\n        const statChanges: StatChanges = {\n            solvedCount: {\n                improved: (solvedCountOld === undefined) || (data.solvedCount > solvedCountOld),\n                oldScore: solvedCountOld,\n                newScore: data.solvedCount,\n            },\n            cycles: {\n                improved: (cyclesOld === undefined) || (cycles < cyclesOld),\n                oldScore: cyclesOld,\n                newScore: cycles,\n            },\n            bytes: {\n                improved: (bytesOld === undefined) || (bytes < bytesOld),\n                oldScore: bytesOld,\n                newScore: bytes,\n            },\n        }\n\n        // Check for new mail\n        addMailForPuzzle(puzzle.title);\n\n        // Force the automated stats mail to be unread\n        ensureSolutionStatsMailUnread(puzzle.title);\n\n        // Start uploading solution/stats\n        const leaderboardPromises = Platform.service.updateStatsIfNeededAsync(data.userId, puzzle.title, programBytes, statChanges);\n\n        // Update session stats (and any leaderboard update+loading promises) so they'll be shown in the mail viewer\n        updateSessionStats(puzzle.title, cycles, bytes, leaderboardPromises);\n\n        this.messageBoxPush(this.createMessageMailViewer(puzzle.title));\n        this.checkForSolutionAchievements();\n    }\n\n    /** Gets the title of the next unsolved puzzle, or null if all puzzles have been solved. \"Next\" meaning the current\n     * puzzle if it's unsolved, otherwise the next higher one, wrapping around, if needed. */\n    private getNextPuzzle(): ClientPuzzle | null {\n        const solvedCount = Sic1DataManager.getData().solvedCount;\n        const currentPuzzleTitle = this.state.puzzle.title;\n        const { puzzleFlatArray, clientPuzzles } = this.state;\n        const currentPuzzleIndex = Math.max(0, puzzleFlatArray.findIndex(p => p.title === currentPuzzleTitle));\n        let index = currentPuzzleIndex;\n\n        if (!Sic1DataManager.getPuzzleData(puzzleFlatArray[index].title).solved) {\n            return this.state.puzzle;\n        }\n\n        do {\n            index = (index + 1) % puzzleCount;\n        } while (index !== currentPuzzleIndex && ((puzzleFlatArray[index].minimumSolvedToUnlock > solvedCount) || Sic1DataManager.getPuzzleData(puzzleFlatArray[index].title).solved));\n        if (index !== currentPuzzleIndex) {\n            return clientPuzzles[index];\n        }\n\n        return null;\n    }\n\n    private toggleMenu() {\n        if (this.state.messageBoxQueue.length > 0) {\n            if (this.state.messageBoxQueue[0].modal !== true) {\n                this.messageBoxPop();\n            }\n        } else {\n            this.messageBoxPush(this.createMessageMenu());\n        }\n    }\n\n    private beforeUnloadHandler = (event: BeforeUnloadEvent) => {\n        this.saveProgress();\n    };\n\n    private keyDownHandler = (event: KeyboardEvent) => {\n        if (event.key === \"Escape\") {\n            if (this.state.messageBoxQueue.length > 0) {\n                if (this.state.messageBoxQueue[0].modal !== true) {\n                    this.messageBoxPop();\n                }\n            } else if (this.ide.current && this.ide.current.pauseOrStop()) {\n                // Already handled\n            } else {\n                this.messageBoxPush(this.createMessageMenu());\n            }\n        }\n    }\n\n    private updateUserProfile(name: string, uploadName: boolean | undefined, callback: () => void) {\n        const data = Sic1DataManager.getData();\n        data.name = name;\n        if (uploadName !== undefined) {\n            data.uploadName = uploadName;\n        }\n\n        data.introCompleted = true;\n        Sic1DataManager.saveData();\n\n        // No need to wait for completion\n        Platform.service.updateUserProfileAsync(data.userId, uploadName ? name : \"\").catch(() => {});\n\n        callback();\n    }\n\n    private openManualInGame(): void {\n        this.messageBoxPush(this.createMessageMailViewer(Sic1Root.manualMailId));\n    }\n\n    private openDevManualInGame(): void {\n        this.messageBoxPush(this.createMessageMailViewer(Sic1Root.devEnvMailId));\n    }\n\n    private openManualInNewWindow(clearMessageBox: boolean): void {\n        if (clearMessageBox) {\n            this.messageBoxClear();\n        }\n        this.openManualInGame();\n    }\n\n    private createMessageIntro(): MessageBoxContent {\n        const { intl } = this.props;\n        const applyButtonText = <FormattedMessage\n            id=\"introApplyButton\"\n            description=\"Button text for the 'apply' button in the introductory form\"\n            defaultMessage=\"Apply for the Job\"/>;\n\n        return {\n            title: this.props.intl.formatMessage({\n                id: \"windowIntro\",\n                description: \"Window title for introduction ('job application') message box\",\n                defaultMessage: \"Job Application\",\n            }),\n            modal: true,\n            body: <>\n                <FormattedMessage\n                    id=\"intro\"\n                    description=\"HTML content shown in the introductory message box ('job application')\"\n                    defaultMessage=\"<h3>Job Description:</h3>\n<p>SIC Systems is looking for experienced programmers to join our team!</p>\n<p>As an engineer at SIC Systems, you'll produce highly efficient programs for our flagship product: the Single Instruction Computer Mark 1 (SIC-1). You will be competing against other engineers to produce the fastest and smallest programs.</p>\n<p>This is a full-time salaried role. The ideal candidate for this job will have a PhD and 15 - 20 years (or more) of industry experience, along with a relentless attention to detail and exemplary interpersonal skills. Scheduling flexibility is a plus, as we push toward our worldwide launch.</p>\n<h3>About SIC Systems:</h3>\n<p>SIC Systems is the world leader in single-instruction computing. Our mission is to simplify computation, and thus simplify the world. We are innovative, trustworthy, and ethical.</p>\"/>\n                {\n                    Platform.disableUserNameUpload\n                    ? <>\n                        <p><FormattedMessage\n                            id=\"introApplyLabel\"\n                            description=\"Label for the 'apply for the job' button on the introductory form\"\n                            defaultMessage=\"Click the button below to submit your job application:\"/></p>\n                        <br/><Button onClick={() => this.updateUserProfile(\"\", undefined, () => this.messageBoxReplace(this.createMessageMailViewer()))}>{applyButtonText}</Button>\n                    </>\n                    : <>\n                        <h3><FormattedMessage\n                            id=\"introHeaderJobApplication\"\n                            description=\"Header text for the 'job application' form\"\n                            defaultMessage=\"Job Application:\"/></h3>\n                        <Sic1UserProfileForm intl={intl} ref={this.userProfileForm} onCompleted={(name, uploadName) => this.updateUserProfile(name, uploadName, () => this.messageBoxReplace(this.createMessageMailViewer()))} />\n                        <p><Sic1SoundCheckbox intl={intl} position=\"left\" value={this.props.soundEffects} onUpdated={this.props.onSoundEffectsUpdated} /></p>\n                        <p><FormattedMessage\n                            id=\"introApplyInvitation\"\n                            description=\"Invitation to click the 'apply' button in the introductory form\"\n                            defaultMessage=\"After completing the form above, click the button below to submit your job application:\"/></p>\n                        <br/><Button onClick={() => this.userProfileForm.current.submit()}>{applyButtonText}</Button>\n                        {\n                            (navigator?.userAgent && (navigator.userAgent.indexOf(\"iPad\") > 0 || navigator.userAgent.indexOf(\"iPhone\") > 0 || navigator.userAgent.indexOf(\"Macintosh\") > 0))\n                                ? <p>* <strong>Note for iPad users</strong>, progress will <em>not</em> be saved if the \"Prevent Cross-Site Tracking\" option is enabled on Safari (the setting is enabled by default). Unfortunately, avoiding this problem would require hosting the game somewhere other than itch.io, and there are currently no plans to change hosts. Sorry for the inconvenience!</p>\n                                : null\n                        }\n                    </>\n                }\n            </>\n        };\n    }\n\n    private createMessageUserProfileEdit(): MessageBoxContent {\n        const { intl } = this.props;\n        const userId = Sic1DataManager.getData().userId;\n        return {\n            title: this.props.intl.formatMessage({\n                id: \"windowEditProfile\",\n                description: \"Window title for the user profile editing message box (only used on the web version)\",\n                defaultMessage: \"User Profile\",\n            }),\n            body: <>\n                <FormattedMessage\n                    id=\"contentEditProfile\"\n                    description=\"Markup shown when editing the user profile (only used on the web version)\"\n                    defaultMessage={`<p>Update your user profile as needed:</p>{form}<p>Note: if you would like to have all of your leaderboard data deleted, send an email to {email} with \"{userId}\" (your randomly-generated user id) in the subject.</p>`}\n                    values={{\n                        form: <Sic1UserProfileForm intl={intl} ref={this.userProfileForm} onCompleted={(name, uploadName) => this.updateUserProfile(name, uploadName, () => this.messageBoxPop())} />,\n                        email: <Link title=\"sic1data@schemescape.com\" link={`mailto:sic1data@schemescape.com?subject=Delete_${userId}`}/>,\n                        userId,\n                    }}\n                    />\n                <br/>\n                <Button onClick={() => this.userProfileForm.current.submit()}>{Shared.resources.saveChanges}</Button>\n                <Button onClick={() => this.messageBoxPop()}>{Shared.resources.cancel}</Button>\n            </>,\n        };\n    }\n\n    private createMessageSaveDataImportConfirm(compressed: string): MessageBoxContent {\n        return {\n            title: this.props.intl.formatMessage({\n                id: \"windowSaveOverwrite\",\n                description: \"Window title for the 'overwrite data when importing' confirmation message box (only used on web version)\",\n                defaultMessage: \"Overwrite Data?\",\n            }),\n            body: <>\n                <FormattedMessage\n                    id=\"contentSaveOverwrite\"\n                    description=\"Markup shown as a warning when overwriting save data during an import (only used on web version)\"\n                    defaultMessage=\"<h3>WARNING</h3><p>This will overwrite ALL of your current save data with the imported save data!</p><p>Are you sure you want to overwrite any existing save data?</p>\"\n                    />\n                <ButtonWithResult\n                    onClickAsync={async () => {\n                        await Sic1DataManager.overwriteDataAsync(compressed);\n                        this.props.onRestart();\n                    }}\n                    successMessage=\"\"\n                    errorMessage={this.props.intl.formatMessage({\n                        id: \"textSaveImportFailed\",\n                        description: \"Text shown when importing save data fails (only used on web version)\",\n                        defaultMessage: \"Error: Failed to overwrite save data.\",\n                    })}\n                    enableDelayMS={this.warningPeriodMS}\n                    >\n                        <FormattedMessage\n                            id=\"buttonSaveOverwriteConfirm\"\n                            description=\"Text shown on the 'yes, overwrite save data' confirmation button when importing save data (only used on the web version)\"\n                            defaultMessage=\"Yes, Overwrite My Save Data\"\n                            />\n                        </ButtonWithResult>\n                <Button onClick={() => this.messageBoxPop()}>{Shared.resources.cancel}</Button>\n            </>,\n        };\n    }\n\n    private createMessageSaveDataImport(): MessageBoxContent {\n        return {\n            title: this.props.intl.formatMessage({\n                id: \"windowSaveImport\",\n                description: \"Title of the 'import save data' message box' (only used on the web version)\",\n                defaultMessage: \"Import Data\",\n            }),\n            body: <Sic1SaveDataImportForm onImport={(compressed) => {\n                if (compressed) {\n                    this.messageBoxPush(this.createMessageSaveDataImportConfirm(compressed));\n                }\n            }}/>,\n        };\n    }\n\n    private createMessageSaveDataExport(): MessageBoxContent {\n        const str = Sic1DataManager.exportData();\n        return {\n            title: this.props.intl.formatMessage({\n                id: \"windowSaveExport\",\n                description: \"Title of the 'export save data' message box (only used on the web version)\",\n                defaultMessage: \"Export Data\",\n            }),\n            body: <>\n                <p>\n                    <FormattedMessage\n                        id=\"textSaveExport\"\n                        description=\"Text shown in the 'export save data' message box (only used in the web version)\"\n                        defaultMessage=\"Below is a compressed and encoded copy of your save data. You can later import this data to restore it.\"\n                        />\n                </p>\n                <textarea readOnly={true} className=\"saveData\" defaultValue={str}></textarea>\n                <CopyToClipboardButton intl={this.props.intl} text={str}/>\n            </>,\n        };\n    }\n\n    private createMessageSaveDataClearConfirm(): MessageBoxContent {\n        return {\n            title: this.props.intl.formatMessage({\n                id: \"windowSaveClearConfirm\",\n                description: \"Window title of the 'clear save data' confirmation message box (only used on the web version)\",\n                defaultMessage: \"Clear Data?\",\n            }),\n            body: <>\n                <FormattedMessage\n                    id=\"contentSaveClearConfirm\"\n                    description=\"Markup shown in the 'clear save data' confirmation message box (only used on the web version)\"\n                    defaultMessage=\"<h3>WARNING</h3><p>This will delete ALL of your save data! All of your solutions, your user name, and achievements will be lost!</p><p>Are you sure you want to delete all of your data?</p>\"\n                    />\n                <ButtonWithResult\n                    onClickAsync={async () => {\n                        await Sic1DataManager.clearAllDataAsync();\n                        this.props.onRestart();\n                    }}\n                    successMessage=\"\"\n                    errorMessage={this.props.intl.formatMessage({\n                        id: \"textSaveClearFailed\",\n                        description: \"Message shown when clearing save data fails (only used on the web version)\",\n                        defaultMessage: \"Error: Failed to clear save data.\",\n                    })}\n                    enableDelayMS={this.warningPeriodMS}\n                    >\n                        <FormattedMessage\n                            id=\"buttonSaveClearConfirm\"\n                            description=\"Text shown on the 'delete save data' confirmation button (only used on the web version)\"\n                            defaultMessage=\"Yes, Delete My Save Data\"\n                            />\n                    </ButtonWithResult>\n                <Button onClick={() => this.messageBoxPop()}>\n                    <FormattedMessage\n                        id=\"buttonSaveClearCancel\"\n                        description=\"Text shown on the 'delete save data' cancellation button (only used on the web version)\"\n                        defaultMessage=\"No, Keep My Save Data\"\n                        />\n                </Button>\n            </>,\n        };\n    }\n\n    private createMessageSaveDataClear(): MessageBoxContent {\n        return {\n            title: this.props.intl.formatMessage({\n                id: \"windowSaveClear\",\n                description: \"Window title for the 'clear data' initial message box (only used on the web version)\",\n                defaultMessage: \"Clear Data\",\n            }),\n            body: <>\n                <p>\n                    <FormattedMessage\n                        id=\"textSaveClear\"\n                        description=\"Text content shown in the initial 'clear save data' message box (only used on the web version)\"\n                        defaultMessage=\"Use the button below to delete your solutions, user name, and achievements:\"\n                        />\n                </p>\n                <Button onClick={() => this.messageBoxPush(this.createMessageSaveDataClearConfirm())}>\n                    <FormattedMessage\n                        id=\"buttonSaveClear\"\n                        description=\"Text shown on the initial 'clear save data' button (only used on the web version)\"\n                        defaultMessage=\"Clear Data\"\n                        />\n                </Button>\n                <Button onClick={() => this.messageBoxPop()}>{Shared.resources.cancel}</Button>\n            </>,\n        };\n    }\n\n    private createMessageSaveDataManage(): MessageBoxContent {\n        return {\n            title: this.props.intl.formatMessage({\n                id: \"windowSaveManage\",\n                description: \"Window title for the 'manage save data' message box (only used on the web version)\",\n                defaultMessage: \"Manage Save Data\",\n            }),\n            behavior: menuBehavior,\n            body: <>\n                <Button onClick={() => this.messageBoxPush(this.createMessageSaveDataImport())}>\n                    <FormattedMessage\n                        id=\"buttonSaveImportMenu\"\n                        description=\"Text on the button to open the 'import save data' message box (only used on the web version)\"\n                        defaultMessage=\"Import Save Data\"\n                        />\n                </Button>\n                <Button onClick={() => this.messageBoxPush(this.createMessageSaveDataExport())}>\n                    <FormattedMessage\n                        id=\"buttonSaveExportMenu\"\n                        description=\"Text on the button to open the 'export save data' message box (only used on the web version)\"\n                        defaultMessage=\"Export Save Data\"\n                        />\n                </Button>\n                <Button onClick={() => this.messageBoxPush(this.createMessageSaveDataClear())}>\n                    <FormattedMessage\n                        id=\"buttonSaveClearMenu\"\n                        description=\"Text shown on the button to open the 'clear save data' message box (only used on the web version)\"\n                        defaultMessage=\"Clear Save Data\"\n                        />\n                </Button>\n                <br/>\n                <Button onClick={() => this.messageBoxPop()}>{Shared.resources.cancel}</Button>\n            </>,\n        };\n    }\n\n    private createMessageOptions(): MessageBoxContent {\n        return {\n            title: this.props.intl.formatMessage({\n                id: \"windowOptions\",\n                description: \"Window title for the general 'options' message box\",\n                defaultMessage: \"Options\",\n            }),\n            behavior: menuBehavior,\n            body: <>\n                <Button intent=\"showAchievements\" onClick={() => {\n                    this.messageBoxClear();\n                    this.messageBoxPush(this.createMessagePuzzleList(\"achievements\"));\n                }}>\n                    <FormattedMessage\n                        id=\"buttonAchievementsMenu\"\n                        description=\"Text shown on the button to open the achievements message box\"\n                        defaultMessage=\"Achievements\"\n                        />\n                </Button>\n                {Platform.disableUserNameUpload\n                    ? null\n                    : <Button intent=\"showUserSettings\" onClick={() => this.messageBoxPush(this.createMessageUserProfileEdit())}>\n                        <FormattedMessage\n                            id=\"buttonUserSettingsMenu\"\n                            description=\"Text shown on the button to open the 'user settings' menu (only used on the web version)\"\n                            defaultMessage=\"User Settings\"\n                            />\n                        </Button>}\n                {Platform.allowImportExport\n                    ? <Button intent=\"showManageSaveData\" onClick={() => this.messageBoxPush(this.createMessageSaveDataManage())}>\n                        <FormattedMessage\n                            id=\"buttonSaveMenu\"\n                            description=\"Text on the button to open the save data management menu (only used on the web version)\"\n                            defaultMessage=\"Manage Save Data\"\n                            />\n                        </Button>\n                    : null}\n                <Button intent=\"showPresentationSettings\" onClick={() => this.messageBoxPush(this.createMessagePresentationSettings())}>\n                    <FormattedMessage\n                        id=\"buttonPresentationSettings\"\n                        description=\"Text on the button to open the 'presentation settings' menu, for editing full-screen, sound, etc.\"\n                        defaultMessage=\"Presentation Settings\"\n                        />\n                </Button>\n                <br/>\n                <Button intent=\"showCredits\" onClick={() => this.messageBoxPush(this.createMessageCredits())}>\n                    <FormattedMessage\n                        id=\"buttonCredits\"\n                        description=\"Text shown on the button to open the credits message box\"\n                        defaultMessage=\"Credits\"\n                        />\n                </Button>\n            </>,\n        };\n    }\n\n    private createMessageHint(): MessageBoxContent {\n        return {\n            title: this.props.intl.formatMessage({\n                id: \"windowHint\",\n                description: \"Window title for the 'hint' message box\",\n                defaultMessage: \"Hint\",\n            }),\n            body: <>\n                <FormattedMessage\n                    id=\"textHint\"\n                    description=\"Text shown as a heading in the 'hint' message box\"\n                    defaultMessage=\"Hint for {task}:\"\n                    values={{ task: this.state.puzzle.title }}\n                    />\n                {this.state.puzzle.hint}\n            </>,\n        };\n    }\n\n    private createMessageHelp(): MessageBoxContent {\n        return {\n            title: this.props.intl.formatMessage({\n                id: \"windowHelp\",\n                description: \"Window title for the 'help' menu, which provides access to hints, manuals, etc.\",\n                defaultMessage: \"Help\",\n            }),\n            behavior: menuBehavior,\n            body: <>\n                <Button intent=\"showHint\" onClick={() => this.messageBoxPush(this.createMessageHint())}>\n                    <FormattedMessage\n                        id=\"buttonHint\"\n                        description=\"Text on the button to show a hint for the current task\"\n                        defaultMessage=\"Show Hint\"\n                        />\n                </Button>\n                <br/>\n                <Button onClick={() => this.openManualInGame()}>\n                    <FormattedMessage\n                        id=\"buttonManualAssembly\"\n                        description=\"Text on the button to open the SIC-1 Assembly manual\"\n                        defaultMessage=\"Open SIC-1 Assembly Manual\"\n                        />\n                </Button>\n                <Button onClick={() => this.openDevManualInGame()}>\n                    <FormattedMessage\n                        id=\"buttonManualDevEnv\"\n                        description=\"Text on the button to open the SIC-1 Development Environment manual\"\n                        defaultMessage=\"Open Dev. Environment Manual\"\n                        />\n                </Button>\n                <br/>\n                <Button onClick={() => this.openManualInNewWindow(true)}>\n                    <FormattedMessage\n                        id=\"buttonManualNewWindow\"\n                        description=\"Text on the button to open the combined manual in a new window\"\n                        defaultMessage=\"Open Assembly Manual Here\"\n                        />\n                </Button>\n            </>,\n        };\n    }\n\n    private createMessageMenu(): MessageBoxContent {\n        return {\n            title: this.props.intl.formatMessage({\n                id: \"windowMenu\",\n                description: \"Window title for the main menu\",\n                defaultMessage: \"Main Menu\",\n            }),\n            behavior: menuBehavior,\n            body: <>\n                <Button onClick={() => this.messageBoxReplace(this.createMessagePuzzleList(\"puzzle\", this.state.puzzle.title))}>\n                    <FormattedMessage\n                        id=\"buttonMenuTaskViewer\"\n                        description=\"Text on the button to open the task viewer/program inventory\"\n                        defaultMessage=\"Program Inventory\"\n                        />\n                </Button>\n                <Button onClick={() => this.messageBoxReplace(this.createMessageMailViewer())}>\n                    <FormattedMessage\n                        id=\"buttonMenuMailViewer\"\n                        description=\"Text on the button to open the mail viewer (using an antiquated term, if possible)\"\n                        defaultMessage=\"Electronic Mail\"\n                        />\n                </Button>\n                {Sic1DataManager.getData().solvedCount >= this.state.puzzleSandbox.minimumSolvedToUnlock\n                    ? <>\n                        <br/>\n                        <Button onClick={() => this.messageBoxReplace(this.createMessagePuzzleList(\"puzzle\", this.state.puzzleSandbox.title))}>\n                            <FormattedMessage\n                                id=\"buttonSandboxMenu\"\n                                description=\"Text on the button that opens the task viewer to the Sandbox Mode page\"\n                                defaultMessage=\"Sandbox Mode\"\n                                />\n                        </Button>\n                        </>\n                    : null}\n                {Sic1DataManager.getData().solvedCount >= Shared.avoisionSolvedCountRequired\n                    ? <Button onClick={() => this.messageBoxReplace(this.createMessagePuzzleList(\"avoision\"))}>\n                        <FormattedMessage\n                            id=\"buttonAvoisionPage\"\n                            description=\"Text on the button that opens the task viewer to the Avoision page\"\n                            defaultMessage=\"Avoision\"\n                            />\n                        </Button>\n                    : null}\n                <br/>\n                <Button intent=\"showHelp\" onClick={() => this.messageBoxPush(this.createMessageHelp())}>\n                    <FormattedMessage\n                            id=\"buttonHelpMenu\"\n                            description=\"Text on the button that opens the 'help' menu'\"\n                            defaultMessage=\"Help\"\n                            />\n                </Button>\n                <br/>\n                <Button intent=\"showOptions\" onClick={() => {this.messageBoxPush(this.createMessageOptions())}}>\n                    <FormattedMessage\n                            id=\"buttonOptionsMenu\"\n                            description=\"Text on the button that opens the options menu'\"\n                            defaultMessage=\"Options\"\n                            />\n                </Button>\n                {Platform.app\n                    ? <>\n                        <br/>\n                        <Button onClick={() => window.close()}>\n                        <FormattedMessage\n                            id=\"buttonExit\"\n                            description=\"Text on the button that exits the game (only used on the app version)\"\n                            defaultMessage=\"Exit SIC-1\"\n                            />\n                        </Button></>\n                    : null}\n            </>,\n        };\n    }\n\n    private createMessagePresentationSettings(): MessageBoxContent {\n        return {\n            title: this.props.intl.formatMessage({\n                id: \"windowTitlePresentationSettings\",\n                description: \"Window title for the 'presentation settings' message box, which allows toggling full-screen, adjusting volume, etc.\",\n                defaultMessage: \"Presentation\",\n            }),\n            behavior: menuBehavior,\n            body: <Sic1PresentationSettings {...this.props} />,\n        };\n    }\n\n    private createMessageLicenses(): MessageBoxContent {\n        return {\n            title: this.props.intl.formatMessage({\n                id: \"windowTitleLicenses\",\n                description: \"Window title for the 'third party licenses' message box, showing copyright notices, etc.\",\n                defaultMessage: \"Licenses\",\n            }),\n            width: \"wide\",\n            body: <>\n                <h2>\n                    <FormattedMessage\n                        id=\"textLicenses\"\n                        description=\"Text heading for the 'third party licenses' message box, showing copyright notices, etc.\"\n                        defaultMessage=\"Third Party Licenses\"\n                        />\n                </h2>\n                <pre className=\"licenses\">{licenses}</pre>\n            </>,\n        };\n    }\n\n    private createMessageCredits(): MessageBoxContent {\n        return {\n            title: this.props.intl.formatMessage({\n                id: \"windowTitleCredits\",\n                description: \"Window title for the 'credits' message box\",\n                defaultMessage: \"Credits\",\n            }),\n            body: <>\n                <div className=\"version\">v{packageJson.version}</div>\n                <h3 className=\"logo\">SIC-1</h3>\n                <p className=\"creditSubtitle\">by <Link title=\"Anti-Pattern Games\" link=\"https://www.antipatterngames.com/\"/></p>\n                <p>Thanks for playing! Hopefully you enjoyed it (or at least learned something in the process).</p>\n                <h3>Background</h3>\n                <p>I originally made this game because I was interested in single-instruction programming languages and I thought that the zachlike genre (originated by <Link title=\"Zachtronics\" link=\"https://www.zachtronics.com/\"/>) would be a fun way to explore the concept.</p>\n                <p>After seeing quite a few people charging up the leaderboards, I decided to add more puzzles and eventually turn this into a full-fledged game (including writing a narrative and some music--both things I hadn't really attempted before, as you can likely tell).</p>\n                <h3>Indieware</h3>\n                <p>Although I spent a ridiculous number of hours making this game, I decided to release it for free because it's more fun to have tons of scores on the leaderboards (and also because the target audience of people who like both esoteric programming languages <em>and</em> zachlikes is probably too small to be profitable).</p>\n                <p>Having said that, this game is officially released as <strong>indieware</strong> (a term I just made up), meaning:</p>\n                <p>If you enjoyed this game and are feeling generous, please take whatever amount of money you think would have been reasonable to pay for SIC-1 and go buy some other indie game you've been eyeing. I'm sure the authors will appreciate your support. Thanks!</p>\n                <p>&mdash; Jared Krinke (2022)</p>\n                <p className=\"creditFooter\">\n                    <FormattedMessage\n                        id=\"textCreditsFooter\"\n                        description=\"Text at the bottom of the 'credits' message box, with instructions for viewing third party licenses\"\n                        defaultMessage=\"To view third party licenses, {link}.\"\n                        values={{ link: <TextButton onClick={() => this.messageBoxPush(this.createMessageLicenses())}>\n                                <FormattedMessage\n                                    id=\"buttonLicenses\"\n                                    description=\"Text on the link to third party licenses\"\n                                    defaultMessage=\"click here\"\n                                    />\n                            </TextButton>,\n                        }}\n                        />\n                </p>\n            </>,\n        };\n    }\n\n    private createMessageMailViewer(initialMailId?: string): MessageBoxContent {\n        const nextPuzzle = this.getNextPuzzle();\n        return {\n            title: this.props.intl.formatMessage({\n                id: \"windowMail\",\n                description: \"Window title for mail viewer message box\",\n                defaultMessage: \"Electronic Mail\",\n            }),\n            width: \"none\",\n            body: <MailViewer\n                ref={this.mailViewer}\n                mails={Sic1DataManager.getData().inbox ?? []}\n                titleToClientPuzzle={this.state.titleToClientPuzzle}\n                puzzleSandbox={this.state.puzzleSandbox}\n                initialMailId={initialMailId}\n                currentPuzzleTitle={this.state.puzzle.title}\n                onClearMessageBoxRequested={() => this.messageBoxClear()}\n                onPuzzleListRequested={(type: PuzzleListTypes, title?: string) => this.messageBoxReplace(this.createMessagePuzzleList(type, title))}\n                onNextPuzzleRequested={nextPuzzle ? () => this.messageBoxReplace(this.createMessagePuzzleList(\"puzzle\", nextPuzzle.title)) : null}\n                onCreditsRequested={() => this.messageBoxPush(this.createMessageCredits())}\n                onManualInGameRequested={() => this.mailViewer?.current?.selectMail?.(Sic1Root.manualMailId)}\n                onManualInNewWindowRequested={() => this.openManualInNewWindow(false)}\n                onMailRead={id => {}}\n            />,\n        };\n    }\n\n    private createMessageCompilationError(error: CompilationError): MessageBoxContent {\n        const heading = this.props.intl.formatMessage({\n            id: \"headerCompilationError\",\n            description: \"Heading for 'compilation error' message box\",\n            defaultMessage: \"Compilation Error\",\n        });\n\n        return {\n            title: heading,\n            body: <>\n                <h3>{heading}</h3>\n                <p>{\n                ((errorType) => {\n                    switch (errorType) {\n                        case \"AddressLiteralRangeError\":\n                        case \"AddressReferenceRangeError\":\n                            return <FormattedMessage\n                            id=\"compilationErrorAddressRangeError\"\n                            description=\"Error message shown when the 'address range error' compilation error is encountered, indicating an address literal isn't within the valid range\"\n                            defaultMessage={`Invalid address argument: \"{argument}\" (must be an integer on the range [{rangeMin}, {rangeMax}])!`}\n                            values={{\n                                argument: error.context.text,\n                                rangeMin: error.context.rangeMin,\n                                rangeMax: error.context.rangeMax,\n                            }}\n                            />;\n\n                        case \"InvalidAddressExpressionError\": return <FormattedMessage\n                            id=\"compilationErrorInvalidAddressExpressionError\"\n                            description=\"Error message shown when the 'InvalidAddressExpressionError' compilation error is encountered, indicating an unexpected token was encountered where an address was expected\"\n                            defaultMessage={`Expected number literal or reference, but got: \"{token}\"!`}\n                            values={{\n                                token: error.context.text,\n                            }}\n                            />;\n\n                        case \"InvalidBreakpointError\": return <FormattedMessage\n                            id=\"compilationErrorInvalidBreakpointError\"\n                            description=\"Error message shown when the 'InvalidBreakpointError' compilation error is encountered, indicating a breakpoint was set somewhere other than a 'subleq' instruction\"\n                            defaultMessage=\"Breakpoints are only supported on subleq instructions!\"\n                            />;\n\n                        case \"InvalidCommandError\": return <FormattedMessage\n                            id=\"compilationErrorInvalidCommandError\"\n                            description=\"Error message shown when the 'InvalidCommandError' compilation error is encountered, indicating a command other than 'subleq' and '.data' was encountered\"\n                            defaultMessage={`Unknown command: \"{command}\" (valid commands are: \"subleq\" and \".data\")!`}\n                            values={{\n                                command: error.context.text,\n                            }}\n                            />;\n\n                        case \"InvalidDataArgumentCountError\": return <FormattedMessage\n                            id=\"compilationErrorInvalidDataArgumentCountError\"\n                            description=\"Error message shown when the 'InvalidDataArgumentCountError' compilation error is encountered, indicating no arguments were supplied for a '.data' directive\"\n                            defaultMessage={`Invalid number of arguments for \".data\": {count} (must have at least 1 argument)!`}\n                            values={{\n                                count: error.context.number,\n                            }}\n                            />;\n\n                        case \"InvalidEscapeCodeError\": return <FormattedMessage\n                            id=\"compilationErrorInvalidEscapeCodeError\"\n                            description=\"Error message shown when the 'InvalidEscapeCodeError' compilation error is encountered, indicating a character escape code was not valid, likely indicating an errant backslash\"\n                            defaultMessage={`Invalid escape code: \"{character}\"!`}\n                            values={{\n                                character: error.context.text,\n                            }}\n                            />;\n\n                        case \"InvalidSubleqArgumentCountError\": return <FormattedMessage\n                            id=\"compilationErrorInvalidSubleqArgumentCountError\"\n                            description=\"Error message shown when the 'InvalidSubleqArgumentCountError' compilation error is encountered, indicating a 'subleq' instruction didn't have 2 or 3 addresses specified for it\"\n                            defaultMessage={`Invalid number of arguments for \"subleq\": {count} (must be between {rangeMin} and {rangeMax}, inclusive)!`}\n                            values={{\n                                count: error.context.number,\n                                rangeMin: error.context.rangeMin,\n                                rangeMax: error.context.rangeMax,\n                            }}\n                            />;\n\n                        case \"InvalidTokenError\": return <FormattedMessage\n                            id=\"compilationErrorInvalidTokenError\"\n                            description=\"Error message shown when the 'InvalidTokenError' compilation error is encountered, indicating an unrecognized token was encountered when parsing\"\n                            defaultMessage={`Invalid token: \"{token}\"!`}\n                            values={{\n                                token: error.context.text,\n                            }}\n                            />;\n\n                        case \"InvalidValueExpressionError\": return <FormattedMessage\n                            id=\"compilationErrorInvalidValueExpressionError\"\n                            description=\"Error message shown when the 'InvalidValueExpressionError' compilation error is encountered, indicating an unrecognized value expression was encountered\"\n                            defaultMessage={`Expected number, character, string, or reference, but got: \"{token}\"!`}\n                            values={{\n                                token: error.context.text,\n                            }}\n                            />;\n\n                        case \"LabelAlreadyDefinedError\": return <FormattedMessage\n                            id=\"compilationErrorLabelAlreadyDefinedError\"\n                            description=\"Error message shown when the 'LabelAlreadyDefinedError' compilation error is encountered, indicating a label was defined more than once\"\n                            defaultMessage={`Label already defined: \"{label}\"!`}\n                            values={{\n                                label: error.context.text,\n                            }}\n                            />;\n\n                        case \"MissingCommaOrWhitespaceError\": return <FormattedMessage\n                            id=\"compilationErrorMissingCommaOrWhitespaceError\"\n                            description=\"Error message shown when the 'MissingCommaOrWhitespaceError' compilation error is encountered, indicating there wasn't whitespace or a comma between arguments\"\n                            defaultMessage={`Whitespace or comma required before argument: \"{argument}\"`}\n                            values={{\n                                argument: error.context.text,\n                            }}\n                            />;\n\n                        case \"MissingWhitespaceError\": return <FormattedMessage\n                            id=\"compilationErrorMissingWhitespaceError\"\n                            description=\"Error message shown when the 'MissingWhitespaceError' compilation error is encountered, indicating there was no whitespace after a 'subleq' or '.data' command\"\n                            defaultMessage={`Whitespace is required after \"{command}\"!`}\n                            values={{\n                                command: error.context.text,\n                            }}\n                            />;\n\n                        case \"ProgramTooLargeError\": return <FormattedMessage\n                            id=\"compilationErrorProgramTooLargeError\"\n                            description=\"Error message shown when the 'ProgramTooLargeError' compilation error is encountered, indicating the compiled program doesn't fit into 253 bytes\"\n                            defaultMessage={`Program is too long (maximum size: {rangeMax} bytes; program size: {bytes} bytes)!`}\n                            values={{\n                                bytes: error.context.number,\n                                rangeMax: error.context.rangeMax,\n                            }}\n                            />;\n\n                        case \"UndefinedReferenceError\": return <FormattedMessage\n                            id=\"compilationErrorUndefinedReferenceError\"\n                            description=\"Error message shown when the 'UndefinedReferenceError' compilation error is encountered, indicating a reference was made to an undeclared label\"\n                            defaultMessage={`Undefined reference: \"{label}\"!`}\n                            values={{\n                                label: error.context.text,\n                            }}\n                            />;\n\n                        case \"ValueRangeError\": return <FormattedMessage\n                            id=\"compilationErrorValueRangeError\"\n                            description=\"Error message shown when the 'ValueRangeError' compilation error is encountered, indicating a value didn't fit in a single signed byte\"\n                            defaultMessage={`Invalid value argument: {value} (must be an integer on the range [{rangeMin}, {rangeMax}])!`}\n                            values={{\n                                value: error.context.text,\n                                rangeMin: error.context.rangeMin,\n                                rangeMax: error.context.rangeMax,\n                            }}\n                            />;\n\n                        default: return <FormattedMessage\n                            id=\"compilationErrorInternal\"\n                            description=\"Error message shown when there was an unknown internal compiler error, indicating a bug in the compiler--this should never happen\"\n                            defaultMessage=\"Internal compiler error!\"\n                            />;\n                    }\n                })(error.errorType)\n                }</p>\n                {\n                    (error.context && (error.context.sourceLineNumber !== undefined) && (error.context.sourceLine !== undefined))\n                    ?\n                        <FormattedMessage\n                            id=\"textCompilationErrorContext\"\n                            description=\"Markup shown for the context of a compilation error, when a source line and line number are available\"\n                            defaultMessage=\"<p>On line {sourceLineNumber}:</p><p>{sourceLine}</p>\"\n                            values={{\n                                sourceLineNumber: error.context.sourceLineNumber,\n                                sourceLine: error.context.sourceLine,\n                            }}\n                            />\n                    : null\n                }\n            </>,\n        };\n    }\n\n    private createMessageHalt(expected: boolean): MessageBoxContent {\n        return {\n            title: this.props.intl.formatMessage({\n                id: \"windowTitleHalt\",\n                description: \"Window title for the message box that appears when a program halts\",\n                defaultMessage: \"Program Halted\",\n            }),\n            body: <>\n                <FormattedMessage\n                    id=\"contentHalt\"\n                    description=\"Markup that is shown when a program halts\"\n                    defaultMessage={`<h3>Program Halted</h3><p>The program halted itself by branching to \"@HALT\" (address 255).</p>`}\n                    />\n                {expected\n                    ? null\n                    : <p>\n                        <FormattedMessage\n                            id=\"textHaltUnexpected\"\n                            description=\"Clarification that halting is not expected for all assigned tasks\"\n                            defaultMessage=\"All of your assigned tasks require the program to repeat indefinitely, so this is an error that must be corrected.\"\n                            />\n                    </p>}\n            </>,\n        }\n    }\n\n    private createMessageNoProgram(): MessageBoxContent {\n        return {\n            title: this.props.intl.formatMessage({\n                id: \"windowTitleNoProgram\",\n                description: \"Window title for the message box that appears when attempting to run an empty program\",\n                defaultMessage: \"No Program\",\n            }),\n            body: <FormattedMessage\n                id=\"contentNoProgram\"\n                description=\"Markup that is shown when attempting to run an empty program\"\n                defaultMessage=\"<h3>No Program Loaded!</h3><p>Please compile and load a program.</p>\"\n                />,\n        }\n    }\n\n    private createMessageAvoision(): MessageBoxContent {\n        return {\n            title: this.props.intl.formatMessage({\n                id: \"windowTitleAvoision\",\n                description: \"Window title for the Avoision message box\",\n                defaultMessage: \"Avoision\",\n            }),\n            body: <>\n                <AvoisionUI\n                    colorScheme={this.props.colorScheme}\n                    onClosed={() => this.playPuzzleMusic()}\n                    onAchievement={() => this.ensureAchievement(\"AVOISION\")}\n                    />\n            </>,\n        };\n    }\n\n    private start() {\n        const initialPage = this.props.initialPage;\n\n        switch (initialPage) {\n            case \"presentationSettings\":\n                // This is a hack to launch straight into Presentation Settings when changing languages (which actually destroys and recreates everything)\n                this.messageBoxPush(this.createMessageMenu());\n                this.messageBoxPush(this.createMessageOptions());\n                this.messageBoxPush(this.createMessagePresentationSettings());\n                break;\n\n            default:\n                const data = Sic1DataManager.getData();\n                if (data.introCompleted) {\n                    this.messageBoxPush(this.createMessagePuzzleList(\"userStats\"));\n                } else {\n                    this.messageBoxPush(this.createMessageIntro());\n                }\n        \n                this.playPuzzleMusic();\n                break;\n        }\n    }\n\n    private createMessagePuzzleList(type: PuzzleListTypes, title?: string): MessageBoxContent {\n        return {\n            title: this.props.intl.formatMessage({\n                id: \"windowTasks\",\n                description: \"Window title for the 'program inventory' (shown when resuming and when selecting tasks)\",\n                defaultMessage: \"Program Inventory\",\n            }),\n            width: \"none\",\n            body: <PuzzleList\n                intl={this.props.intl}\n                clientPuzzlesGrouped={this.state.clientPuzzlesGrouped}\n                puzzleSandbox={this.state.puzzleSandbox}\n                initialItemType={type}\n                initialItemTitle={title}\n                onLoadPuzzleRequested={(puzzle, solutionName) => this.loadPuzzle(puzzle, solutionName)}\n                hasUnreadMessages={hasUnreadMail()}\n                onOpenMailViewerRequested={() => this.messageBoxReplace(this.createMessageMailViewer())}\n                currentPuzzleIsSolved={Sic1DataManager.getPuzzleData(this.state.puzzle.title).solved}\n                onClearMessageBoxRequested={() => this.messageBoxClear()}\n                onPlayAvoisionRequested={() => {\n                    Music.pause();\n                    this.messageBoxReplace(this.createMessagePuzzleList(\"avoision\"));\n                    this.messageBoxPush(this.createMessageAvoision());\n                }}\n                onShowMessageBox={(content) => this.messageBoxPush(content)}\n                onCloseMessageBox={() => this.messageBoxPop()}\n\n                nextPuzzle={this.getNextPuzzle()}\n            />\n        };\n    }\n\n    private messageBoxReplace(messageBoxContent: MessageBoxContent) {\n        this.setState(state => ({ messageBoxQueue: [messageBoxContent, ...state.messageBoxQueue.slice(1)] }));\n    }\n\n    private messageBoxPush(messageBoxContent: MessageBoxContent)  {\n        this.setState(state => ({\n            messageBoxQueue: [messageBoxContent, ...state.messageBoxQueue],\n            previousFocus: [\n                (document.activeElement\n                    ? (document.activeElement.id\n                        ? document.activeElement.id\n                        : document.activeElement)\n                    : undefined),\n                ...state.previousFocus\n            ],\n        }));\n    }\n\n    private messageBoxClear() {\n        this.setState(state => ({\n            messageBoxQueue: [],\n            previousFocus: [],\n        }));\n    }\n\n    private messageBoxPop() {\n        this.setState(state => ({\n            messageBoxQueue: state.messageBoxQueue.slice(1),\n            previousFocus: state.previousFocus.slice(1),\n        }));\n    }\n\n    private playPuzzleMusic(): void {\n        Music.play((this.state.puzzle.song ?? \"default\") as SongId);\n    }\n\n    public componentDidMount() {\n        window.addEventListener(\"keydown\", this.keyDownHandler);\n        window.addEventListener(\"beforeunload\", this.beforeUnloadHandler);\n        Platform.onClosing = () => this.saveProgress();\n        this.start();\n    }\n\n    public componentWillUnmount() {\n        window.removeEventListener(\"keydown\", this.keyDownHandler);\n        window.removeEventListener(\"beforeunload\", this.beforeUnloadHandler);\n        Platform.onClosing = undefined;\n    }\n\n    public componentDidUpdate(previousProps: Readonly<Sic1RootProps>, previousState: Readonly<Sic1RootState>, snapshot: any): void {\n        // Check to see if a message box was closed\n        if (previousState.messageBoxQueue.length > this.state.messageBoxQueue.length) {\n            const previousFocusIdOrElement = previousState.previousFocus[0];\n            const previousFocus = (typeof(previousFocusIdOrElement) === \"string\") ? document.getElementById(previousFocusIdOrElement) : previousFocusIdOrElement;\n    \n            if (previousFocus) {\n                if ((document.activeElement !== previousFocus) && document.body.contains(previousFocus) && previousFocus[\"focus\"]) {\n                    previousFocus[\"focus\"]();\n                }\n            }\n        }\n    }\n\n    public render() {\n        // If all dialogs have been dismissed, change the song, if needed\n        if (this.state.messageBoxQueue.length <= 0) {\n            this.playPuzzleMusic();\n        }\n\n        return <>\n            <Sic1Ide\n                ref={this.ide}\n                intl={this.props.intl}\n                puzzle={this.state.puzzle}\n                solutionName={this.state.solutionName}\n                defaultCode={this.state.defaultCode}\n\n                onCompilationError={(error) => {\n                    this.playSoundIncorrect();\n                    this.messageBoxClear();\n                    this.messageBoxPush(this.createMessageCompilationError(error));\n                }}\n                onHalt={() => {\n                    this.playSoundIncorrect();\n                    this.messageBoxClear();\n                    this.messageBoxPush(this.createMessageHalt(this.state.puzzle.title === \"Sandbox Mode\"));\n                }}\n                onNoProgram={() => {\n                    this.playSoundIncorrect();\n                    this.messageBoxClear();\n                    this.messageBoxPush(this.createMessageNoProgram());\n\n                    // Check for \"self-destruct\" achievement\n                    if (this.ide.current && !this.ide.current.hasError() && this.ide.current.hasReadInput()) {\n                        const programBytes = this.ide.current.getProgramBytes();\n                        if (programBytes && programBytes.length > 0) {\n                            for (const byte of programBytes) {\n                                if (byte !== 0) {\n                                    // Original program had non-zero content, but now program is empty: achieved!\n                                    this.ensureAchievement(\"ERASE\");\n                                    break;\n                                }\n                            }\n                        }\n                    }\n                }}\n                onMenuRequested={() => this.toggleMenu() }\n                onHelpRequested={() => this.messageBoxPush(this.createMessageHelp())}\n                onShowMessageBox={(content) => this.messageBoxPush(content)}\n                onCloseMessageBox={() => this.messageBoxPop()}\n                onPuzzleCompleted={(cycles, bytes, programBytes) => {\n                    this.playSoundCompleted();\n                    this.puzzleCompleted(cycles, bytes, programBytes);\n                }}\n                onSaveRequested={() => this.saveProgress()}\n\n                onOutputCorrect={() => this.playSoundCorrect()}\n                onOutputIncorrect={() => this.playSoundIncorrect()}\n                />\n            <Toaster ref={this.toaster} />\n            {\n                (() => {\n                    const contents: MessageBoxContent[] = [];\n                    const queue = this.state.messageBoxQueue;\n                    for (const content of queue) {\n                        contents.push(content);\n\n                        // Only continue if this message box is transparent\n                        if (!content.transparent) {\n                            break;\n                        }\n                    }\n\n                    return contents.map((content, index) => <MessageBox\n                        key={content.title}\n                        {...content}\n                        zIndex={50 - (10 * index)}\n                        onDismissed={() => this.messageBoxPop()}\n                        />);\n                })()\n            }\n        </>;\n    }\n}\n", "sic1/client/ts/ide-number-span.tsx": "import React from \"react\";\nimport { Assembler } from \"../../../lib/src/sic1asm\";\nimport { Shared } from \"./shared\";\n\nexport class NumberSpan extends React.Component<{ format: \"hex\" | \"decimal\", value: number }> {\n    public render(): React.ReactNode {\n        const n = this.props.value;\n        switch (this.props.format) {\n            case \"hex\":\n                return <span title={(n <= 127) ? `${n}` : `${Assembler.unsignedToSigned(n)} (${n})`}>{Shared.hexifyByte(n)}</span>;\n            \n            case \"decimal\":\n                return <span title={(n >= 0) ? `0x${Shared.hexifyByte(n)}` : `0x${Shared.hexifyByte(Assembler.signedToUnsigned(n))} (${Assembler.signedToUnsigned(n)})`}>{n}</span>;\n        }\n    }\n}\n", "sic1/client/ts/timer.tsx": "import React from \"react\";\n\ninterface TimerProperties {\n    timerInMS: number;\n    onTimerCompleted: () => void;\n}\n\nexport class Timer<P = {}, S = {}> extends React.Component<P & TimerProperties, S> {\n    private token?: number;\n\n    constructor(props) {\n        super(props);\n    }\n\n    public componentDidMount(): void {\n        this.token = setTimeout(() => {\n            this.token = undefined;\n            this.props.onTimerCompleted();\n        }, this.props.timerInMS);\n    }\n\n    public componentWillUnmount(): void {\n        if (this.token !== undefined) {\n            clearTimeout(this.token);\n            this.token = undefined;\n        }\n    }\n\n    public render() {\n        return null;\n    }\n}\n", "sic1/client/ts/boot-screen.tsx": "import React from \"react\";\nimport { Timer } from \"./timer\";\nimport { IntlShape } from \"react-intl\";\n\ninterface BootScreenState {\n    text: string;\n    dotCounter: number | null;\n    memoryPrefix?: string;\n    memoryCounter: number | null;\n    cursorCounter: number;\n    cursorVisible: boolean;\n}\n\nfunction padNumber(n: number, digits: number, pad: string): string {\n    const str = n.toString();\n    if (str.length < digits) {\n        return pad.repeat(digits - str.length) + str;\n    }\n    return str;\n}\n\nexport class GlobalKeyboardShortcut extends React.Component<{ onKeyDown: (event: KeyboardEvent) => void }> {\n    // Note: Store this function here because this.props.onKeyDown can change between componentDidMount and componentWillUnmount!\n    private onKeyDown: (event: KeyboardEvent) => void;\n\n    constructor(props) {\n        super(props);\n        this.onKeyDown = this.props.onKeyDown;\n    }\n\n    public componentDidMount(): void {\n        window.addEventListener(\"keydown\", this.onKeyDown);\n    }\n\n    public componentWillUnmount(): void {\n        window.removeEventListener(\"keydown\", this.onKeyDown);\n    }\n\n    public render() {\n        return <></>;\n    }\n}\n\ninterface BootScreenProps {\n    intl: IntlShape;\n    onCompleted: () => void;\n}\n\nexport class BootScreen extends React.Component<BootScreenProps, BootScreenState> {\n    private static bootTimeoutInMS = 4000;\n    private static framePeriodInMS = 1000 / 30;\n    private static ticksPerFrame = 12;\n    private static ticksPerDot = 24;\n    private static cursorBlinkPeriodInFrames = 6;\n\n    private session: string;\n    private initialSession: string;\n    private intervalToken?: number;\n\n    constructor(props) {\n        super(props);\n        this.session = this.props.intl.formatMessage({\n            id: \"bootMessage\",\n            description: \"Text of the boot screen, shown when launching the game; notes: use spaces for alignment, the '█' character is used for an ASCII art logo, and '...' and '###/256B ' have special meaning and should be preserved\",\n            defaultMessage:\n`\n ████  █████   ████\n██       █    ██\n ███     █    █      SYSTEMS (TM)\n   ██    █    ██\n████   █████   ████\n\n     \"Synergy, simply.\"\n\n(C) 1980 SIC Systems, Inc.\n\nSIC-1 emulator - 50 Hz          ... OK\nChecking SIC-1 memory      ###/256B OK\nSimulating SIC-1 8-bit I/O port ... OK\n\nLoading SIC-1 Development Environment v120279...\n\nStarting hi-res, tri-color graphical session... `\n        });\n\n        this.initialSession = BootScreen.getInitialText(this.session);\n        this.state = {\n            text: \"\",\n            dotCounter: null,\n            memoryCounter: null,\n            cursorCounter: 0,\n            cursorVisible: false,\n        };\n    }\n\n    private frame(): void {\n        this.setState((oldState) => {\n            const state = { ...oldState };\n            for (let i = 0; i < BootScreen.ticksPerFrame && state.text.length < this.initialSession.length; i++) {\n                if (state.dotCounter !== null) {\n                    state.dotCounter += 1;\n                    if ((state.dotCounter % BootScreen.ticksPerDot) === 0) {\n                        if (state.text.substring(state.text.length - 3) === \"...\") {\n                            state.dotCounter = null;\n                        } else {\n                            state.dotCounter = 0;\n                            state.text += \".\";\n                        }\n                    }\n                } else if (state.memoryCounter !== null) {\n                    state.text = state.memoryPrefix + `${padNumber(state.memoryCounter, 3, \" \")}/256B `;\n                    if (state.memoryCounter >= 256) {\n                        state.memoryCounter = null;\n                    } else {\n                        state.memoryCounter += 8;\n                    }\n                    break; // Only update once per frame\n                } else {\n                    // Skip newlines\n                    while (this.session[state.text.length] === \"\\n\") {\n                        state.text += \"\\n\";\n                    }\n\n                    const position = state.text.length;\n                    if (this.session.substring(position, position + 3) === \"...\") {\n                        state.dotCounter = 0;\n                    } else if (this.session.substring(position, position + 9) === \"###/256B \") {\n                        state.memoryPrefix = state.text;\n                        state.memoryCounter = 0;\n                        state.text += \"  0/256B \";\n                    } else {\n                        state.text += this.session[position];\n                    }\n                }\n            }\n\n            if (state.cursorCounter === BootScreen.cursorBlinkPeriodInFrames) {\n                state.cursorVisible = !state.cursorVisible;\n                state.cursorCounter = 0;\n            }\n            state.cursorCounter += 1;\n\n            return state;\n        });\n    }\n\n    private static getInitialText(session: string): string {\n        return session.replace(/[^\\n]/g, \" \");\n    }\n\n    public componentDidMount(): void {\n        this.intervalToken = setInterval(() => this.frame(), BootScreen.framePeriodInMS);\n    }\n\n    public componentWillUnmount(): void {\n        if (this.intervalToken !== undefined) {\n            clearInterval(this.intervalToken);\n            this.intervalToken = undefined;\n        }\n    }\n\n    public render() {\n        const { text, cursorVisible } = this.state;\n        return <>\n            <Timer timerInMS={BootScreen.bootTimeoutInMS} onTimerCompleted={this.props.onCompleted} />\n            <GlobalKeyboardShortcut onKeyDown={(event) => {\n                if (event.key === \"Escape\") {\n                    this.props.onCompleted();\n                }\n            }} />\n            <div className=\"centerContainer\">\n                <div className=\"bootScreen\" onDoubleClick={this.props.onCompleted}>\n                    <pre>{text.substring(0, text.length - 1)}{cursorVisible ? \"█\" : text.substring(text.length - 1, text.length)}{this.initialSession.substring(text.length)}</pre>\n                </div>\n            </div>\n        </>;\n    }\n}\n\n", "sic1/client/ts/sound-effects.ts": "export type SoundEffectId = 'click'|'completed'|'correct'|'incorrect'|'avoisionScore'|'avoisionGameOver';\nexport class SoundEffects {\n private static enabled=false;private static volume=1;private static context?:AudioContext;\n static setEnabled(enabled:boolean){this.enabled=enabled;}\n static setVolume(volume:number){this.volume=volume;}\n static play(name:SoundEffectId,volumeOverride?:number){if(!this.enabled)return;try{const c=this.context??(this.context=new AudioContext());if(c.state==='suspended')void c.resume();const o=c.createOscillator(),g=c.createGain();o.type='sine';o.frequency.value=({click:440,completed:880,correct:660,incorrect:180,avoisionScore:740,avoisionGameOver:140})[name];g.gain.setValueAtTime(Math.max(0.001,(volumeOverride??this.volume)*0.12),c.currentTime);g.gain.exponentialRampToValueAtTime(0.001,c.currentTime+0.12);o.connect(g);g.connect(c.destination);o.start();o.stop(c.currentTime+0.13);}catch{}}\n static stop(name:SoundEffectId){}\n}\n", "sic1/client/ts/language-data.ts": "// Automatically generated by build-language-data.ts\nimport en from \"content/messages-compiled/en.json\";\n\nexport const localeToHrefOrMessages = {\n    en,\n\n} as const;\n\nexport const localeToLanguageName = {\n    \"en\": \"English\",\n} as const;\n\nexport const localeToManualHref = { en: \"\" };\n", "sic1/client/ts/avoision-ui.tsx": "import React from \"react\";\nimport { Avoision } from \"./avoision\";\nimport { ColorScheme } from \"./colors\";\nimport { Sic1DataManager } from \"./data-manager\";\nimport { Music } from \"./music\";\nimport { Platform } from \"./platform\";\nimport { SoundEffects } from \"./sound-effects\";\nimport { FormattedMessage } from \"react-intl\";\n\ninterface AvoisionUIProps {\n    colorScheme: ColorScheme;\n    onClosed: () => void;\n    onAchievement: () => void;\n}\n\ninterface AvoisionUIState {\n    message?: React.ReactNode;\n    points?: number;\n    score?: number;\n    saved: boolean;\n}\n\nexport class AvoisionUI extends React.Component<AvoisionUIProps, AvoisionUIState> {\n    private static readonly achievementScore = 250;\n\n    private avoision = React.createRef<Avoision>();\n\n    public constructor(props) {\n        super(props);\n        this.state = { saved: false };\n    }\n\n    /** Returns true if this was a new high score. */\n    private saveScoreIfNeeded(score: number): boolean {\n        if (score > 0) {\n            const data = Sic1DataManager.getAvoisionData();\n            if (!data.score || score > data.score) {\n                data.score = score;                \n                Sic1DataManager.saveAvoisionData();\n\n                // Update Steam friend leaderboard, if needed\n                if (Platform.service.tryUpdateFriendLeaderboardAsync) {\n                    Platform.service.tryUpdateFriendLeaderboardAsync(\"Avoision\", score);\n                }\n\n                if (score >= AvoisionUI.achievementScore) {\n                    this.props.onAchievement();\n                }\n\n                return true;\n            }\n        }\n        return false;\n    }\n\n    public componentWillUnmount(): void {\n        if (this.state.score && !this.state.saved) {\n            this.saveScoreIfNeeded(this.state.score);\n        }\n\n        this.props.onClosed();\n    }\n\n    public render(): React.ReactNode {\n        return <>\n            <div className=\"avoisionHeader\">\n                <div className=\"avoisionPoints\">\n                    <FormattedMessage\n                        id=\"avoisionPoints\"\n                        description=\"In-game display of points for Avoision\"\n                        defaultMessage=\"Points: {value}\"\n                        values={{ value: (this.state.points !== undefined) ? `${this.state.points}` : \"\" }}\n                        />\n                </div>\n                <div className=\"avoisionScore\">\n                    <FormattedMessage\n                        id=\"avoisionScore\"\n                        description=\"In-game display of score for Avoision\"\n                        defaultMessage=\"Score: {value}\"\n                        values={{ value: (this.state.score !== undefined) ? `${this.state.score}` : \"\" }}\n                        />\n                </div>\n            </div>\n            <div className=\"avoisionBox\">\n                {this.state.message ? <p className=\"avoisionOverlay fadeIn\">{this.state.message}</p> : null}\n                <Avoision\n                    ref={this.avoision}\n                    colorScheme={this.props.colorScheme}\n                    onStarted={() => Music.play(\"avoision\")}\n                    onPointsUpdated={points => this.setState({ points })}\n\n                    onScoreUpdated={score => {\n                        this.setState({ score, saved: false });\n                        if (score > 0) {\n                            SoundEffects.play(\"avoisionScore\");\n                        }\n                    }}\n\n                    onGameOver={score => {\n                        const newHighScore = this.saveScoreIfNeeded(score);\n                        this.setState({\n                            score,\n                            saved: true,\n                            message: newHighScore\n                                ? <FormattedMessage\n                                    id=\"avoisionNewHigh\"\n                                    description=\"Message shown when a new high score is achieved in Avoision\"\n                                    defaultMessage=\"New High Score!\"\n                                    />\n                                : <FormattedMessage\n                                    id=\"avoisionGameOver\"\n                                    description=\"Message shown when a round of Avoision ends without a new high score\"\n                                    defaultMessage=\"Game Over\"\n                                    />,\n                        });\n                        Music.pause();\n                        SoundEffects.play(\"avoisionGameOver\");\n                    }}\n                    />\n            </div>\n        </>;\n    }\n}\n", "sic1/client/ts/friend-leaderboard.tsx": "import React from \"react\";\nimport { Sic1DataManager } from \"./data-manager\";\nimport { FriendLeaderboardEntry } from \"./service\";\n\nenum State {\n    loading,\n    loaded,\n    loadFailed,\n}\n\ninterface FriendLeaderboardProperties {\n    title: React.ReactNode;\n    promise: Promise<FriendLeaderboardEntry[]>;\n}\n\ninterface FriendLeaderboardState {\n    state: State;\n    data?: FriendLeaderboardEntry[];\n}\n\nexport class FriendLeaderboard extends React.Component<FriendLeaderboardProperties, FriendLeaderboardState> {\n    constructor(props: FriendLeaderboardProperties) {\n        super(props);\n        this.state = { state: State.loading };\n    }\n\n    public async componentDidMount() {\n        try {\n            const data = await this.props.promise;\n            this.setState({\n                state: State.loaded,\n                data,\n            });\n        } catch (error) {\n            this.setState({ state: State.loadFailed });\n        }\n    }\n\n    public render() {\n        let body: React.ReactNode = null;\n        switch (this.state.state) {\n            case State.loading:\n                body = <tr><td colSpan={2} className=\"center\">Loading...</td></tr>\n                break;\n\n            case State.loaded:\n                if (this.state.data!.length > 0) {\n                    body = this.state.data!.map((row, index) => <tr key={index}>\n                        <td className={\"text\" + ((row.name === Sic1DataManager.getData().name) ? \"\" : \" deemphasize\")}>{row.name}</td>\n                        <td>{row.score}</td>\n                    </tr>);\n                } else {\n                    body = <tr><td colSpan={2} className=\"center\">(empty)</td></tr>\n                }\n                break;\n\n            case State.loadFailed:\n                body = <tr><td colSpan={2} className=\"center\">Load Failed</td></tr>\n                break;\n        }\n\n        return <table className=\"stats\">\n            <thead><tr><th colSpan={2}>{this.props.title}</th></tr></thead>\n            <tbody>{body}</tbody>\n        </table>;\n    }\n}\n", "sic1/client/ts/button.tsx": "import React from \"react\";\nimport { SoundEffects } from \"./sound-effects\";\n\nexport type ButtonProps = React.ButtonHTMLAttributes<HTMLButtonElement> & {\n    intent?: string; // Note that this can be used to support restoring focus for a button in a message box down the stack\n    focusOnMount?: boolean;\n    enableDelayMS?: number;\n};\n\nexport class Button extends React.Component<ButtonProps, { disabledOverride?: boolean }> {\n    private button = React.createRef<HTMLButtonElement>();\n\n    constructor(props) {\n        super(props);\n        this.state = {\n            disabledOverride: this.props.enableDelayMS ? true : undefined,\n        };\n    }\n\n    public componentDidMount(): void {\n        if (this.props.enableDelayMS) {\n            setTimeout(() => {\n                if (this?.button?.current) {\n                    this.setState({ disabledOverride: false });\n                }\n            }, this.props.enableDelayMS);\n        } else if (this.props.focusOnMount) {\n            this.button.current?.focus?.();\n        }\n    }\n\n    public render(): React.ReactNode {\n        const { children, intent, onClick, enableDelayMS, focusOnMount, ...rest } = this.props;\n        return <button\n            {...rest}\n            id={intent}\n            ref={this.button}\n            disabled={enableDelayMS ? this.state.disabledOverride : this.props.disabled}\n            onKeyDown={(event) => {\n                if (event.key === \"Enter\" && !event.ctrlKey && !event.metaKey) {\n                    event.stopPropagation();\n                }\n            }}\n            onClick={event => {\n                SoundEffects.play(\"click\");\n                onClick.call(event.target, event);\n            }}\n            >{children}</button>;\n    }\n}\n", "sic1/client/ts/chart-model.ts": "import * as Contract from \"../../server/contract/contract\";\n\nexport interface HistogramBucketDetail {\n    value: number;\n    count: number;\n}\n\nexport type HistogramBucketWithDetails = (Contract.HistogramDataBucket & {\n    details: HistogramBucketDetail[];\n});\n\nexport interface HistogramDetail {\n    buckets: HistogramBucketWithDetails[];\n    outliers?: HistogramBucketDetail[];\n}\n\nexport interface ChartData {\n    histogram: HistogramDetail;\n    highlightedValue?: number;\n}\n", "sic1/client/ts/browser.tsx": "import React from \"react\";\nimport { Button } from \"./button\";\nimport { Shared } from \"./shared\";\n\nexport interface BrowserItemButton {\n    title: React.ReactNode;\n    intent: string;\n    onClick: () => void;\n}\n\nexport interface BrowserItem {\n    key: string;\n    title: React.ReactNode;\n    subtitle?: React.ReactNode;\n    onDoubleClick?: () => void;\n    buttons?: BrowserItemButton[];\n    unimportant?: boolean;\n}\n\nexport interface BrowserGroup {\n    key: string;\n    title: React.ReactNode;\n    items: BrowserItem[];\n}\n\nexport interface BrowserIndices {\n    groupIndex: number;\n    itemIndex: number;\n}\n\nexport interface BrowserProperties {\n    children?: React.ReactNode;\n    groups: BrowserGroup[];\n    selection: BrowserIndices;\n    className: string;\n    onSelectionChanged: (selection: BrowserIndices) => void;\n}\n\nexport class Browser extends React.Component<BrowserProperties> {\n    private initialSelection = React.createRef<HTMLDivElement>();\n\n    constructor(props) {\n        super(props);\n    }\n\n    public onClick(gi: number, ii: number): void {\n        this.props.onSelectionChanged({ groupIndex: gi, itemIndex: ii });\n    }\n\n    public componentDidMount() {\n        Shared.scrollElementIntoView(this.initialSelection.current, \"center\", true);\n        document.querySelector<HTMLButtonElement>(\".browserContent\")?.focus?.();\n    }\n\n    public render(): React.ReactNode {\n        const { groups } = this.props;\n        const { groupIndex, itemIndex } = this.props.selection;\n        const item = this.props.groups[groupIndex].items[itemIndex];\n\n        return <div className={`browser ${this.props.className}`}>\n            <div\n                className=\"browserList\"\n                tabIndex={0}\n                onKeyDown={(event) => {\n                    const offset = Shared.keyToVerticalOffset[event.key];\n                    if (offset) {\n                        let { groupIndex, itemIndex } = this.props.selection;\n\n                        itemIndex += offset;\n                        if (itemIndex < 0) {\n                            itemIndex = Infinity;\n                            groupIndex--;\n                        } else if (itemIndex >= this.props.groups[groupIndex].items.length) {\n                            itemIndex = 0;\n                            groupIndex++;\n                        }\n\n                        if (groupIndex >= 0 && groupIndex < this.props.groups.length) {\n                            itemIndex = Math.min(this.props.groups[groupIndex].items.length - 1, itemIndex);\n                            this.props.onSelectionChanged({ groupIndex, itemIndex });\n                            event.preventDefault();\n                        }\n                    } else if (event.key === \"Enter\") {\n                        let { groupIndex, itemIndex } = this.props.selection;\n                        this.props.groups[groupIndex]?.items?.[itemIndex]?.onDoubleClick?.();\n                        event.preventDefault();\n                    }\n                }}\n                >{groups.map((g, gi) => <React.Fragment key={g.key}>\n                <p>{g.title}</p>\n                <div>\n                    {g.items.map((i, ii) =>\n                    <p\n                        key={i.key}\n                        ref={(groupIndex === gi && itemIndex === ii) ? this.initialSelection : null}\n                        className={((groupIndex === gi && itemIndex === ii) ? \"selected\" : \"\") + (i.unimportant ? \" sub\" : \"\")}\n                        onDoubleClick={i.onDoubleClick}\n                        onClick={() => this.onClick(gi, ii)}\n                        tabIndex={-1}\n                    >\n                        {i.title}\n                        {i.subtitle ? <><br/><span className=\"sub\">{i.subtitle}</span></> : null}\n                    </p>)}\n                </div>\n            </React.Fragment>)}</div>\n            <div className=\"browserView\">\n                <div className=\"browserContent\" tabIndex={0}>{this.props.children}</div>\n                {\n                    item.buttons\n                        ? item.buttons.map(({ title, intent, ...rest }) => <Button key={intent} intent={intent} {...rest}>{title}</Button>)\n                        : null\n                }\n            </div>\n        </div>;\n    }\n}\n", "sic1/client/ts/ide.tsx": "import { Assembler, Emulator, CompilationError, Constants, Variable, Command } from \"../../../lib/src/sic1asm\";\nimport { Format } from \"./puzzles\";\nimport { PuzzleTest, generatePuzzleTest, PuzzleTestSet } from \"../../shared/puzzles\";\nimport React from \"react\";\nimport { Button } from \"./button\";\nimport { ClientPuzzle, hasCustomInput } from \"./puzzles\";\nimport { MessageBoxContent } from \"./message-box\";\nimport { formatNameToFormat, formatToName, Sic1DataManager } from \"./data-manager\";\nimport { Sic1Memory } from \"./ide-memory\";\nimport { Sic1Watch } from \"./ide-watch\";\nimport { parseValues, Sic1InputEditor } from \"./ide-input-editor\";\nimport { Shared } from \"./shared\";\nimport { Sic1CodeView } from \"./ide-code-view\";\nimport { FormattedMessage, IntlShape } from \"react-intl\";\n\n// State management\nenum StateFlags {\n    none = 0x0,\n    running = 0x1,\n    error = 0x2,\n    done = 0x4,\n}\n\nfunction tryParseValues(intl: IntlShape, text: string): number[] | undefined {\n    try {\n        return parseValues(intl, text);\n    } catch (e) {\n        return undefined;\n    }\n}\n\ninterface Sic1IdeProperties {\n    intl: IntlShape;\n    puzzle: ClientPuzzle;\n    solutionName: string;\n    defaultCode: string;\n\n    onCompilationError: (error: CompilationError) => void;\n    onHalt: () => void;\n    onNoProgram: () => void;\n    onMenuRequested: () => void;\n    onHelpRequested: () => void;\n    onPuzzleCompleted: (cyclesExecuted: number, memoryBytesAccessed: number, programBytes: number[]) => void;\n    onSaveRequested: () => void;\n\n    onShowMessageBox: (content: MessageBoxContent) => void;\n    onCloseMessageBox: () => void;\n\n    // For sound effects\n    onOutputCorrect: () => void;\n    onOutputIncorrect: () => void;\n}\n\ntype PuzzleTestWithoutExpectedOutput = Omit<PuzzleTest, \"testSets\"> & { testSets: Omit<PuzzleTestSet, \"output\">[] };\n\n/** IDE state for a single puzzle that persists across compile and run cycles (but not across sessions) */\ninterface Sic1IdePuzzleState {\n    watchedAddresses: Set<number>;\n}\n\n/** IDE state that lasts for only a single compile and run cycle */\ninterface Sic1IdeTransientState {\n    stateLabel: React.ReactNode;\n    cyclesExecuted: number;\n    memoryBytesAccessed: number;\n    sourceLines: string[];\n\n    test: PuzzleTest | PuzzleTestWithoutExpectedOutput;\n    actualOutputBytes: number[];\n    inputFormat: Format;\n    outputFormat: Format;\n\n    currentSourceLine?: number;\n    currentAddress: number | null;\n    currentInputIndex: number | null;\n    currentOutputIndex: number | null;\n    unexpectedOutputIndexes: { [index: number]: boolean };\n    variables: Variable[];\n    variableToAddress: { [label: string]: number };\n    sourceLineToBreakpointState: { [lineNumber: number]: boolean };\n\n    // Memory\n    [index: number]: number;\n    highlightAddress?: number;\n\n    // For achievement tracking\n    hasReadInput: boolean;\n\n    // Custom input\n    customInputString?: string;\n}\n\ninterface Sic1IdeEditorModeState {\n    tabInsertMode: boolean;\n    autoIndentMode: boolean;\n}\n\ninterface Sic1IdeState extends Sic1IdePuzzleState, Sic1IdeTransientState, Sic1IdeEditorModeState {\n    executing: boolean;\n}\n\nexport class Sic1Ide extends React.Component<Sic1IdeProperties, Sic1IdeState> {\n    private static readonly stateStatusStopped = <FormattedMessage\n        id=\"stateStatusStopped\"\n        description=\"Text shown for the simulation 'state' shown in the lower-left, when stopped\"\n        defaultMessage=\"Stopped\"\n        />;\n\n    private static readonly stateStatusRunning = <FormattedMessage\n        id=\"stateStatusRunning\"\n        description=\"Text shown for the simulation 'state' shown in the lower-left, when running\"\n        defaultMessage=\"Running\"\n        />;\n\n    private static readonly headerIOExpected = <FormattedMessage\n        id=\"headerInputExpected\"\n        description=\"Column heading for the IO table, for expected output (note: this string should be as short as possible)\"\n        defaultMessage=\"Expected\"\n        />;\n\n    private static readonly headerIOActual = <FormattedMessage\n        id=\"headerInputActual\"\n        description=\"Column heading for the IO table, for actual output (note: this string should be as short as possible)\"\n        defaultMessage=\"Actual\"\n        />;\n\n    private static readonly stepRates = [\n        {\n            rate: 50,\n            label: <FormattedMessage\n                id=\"buttonStepRateDefault\"\n                description=\"Text on the 'run' button when going to the default step rate (speed)\"\n                defaultMessage=\"Run\"\n                />,\n        },\n        {\n            rate: 200,\n            label: <FormattedMessage\n                id=\"buttonStepRate4x\"\n                description=\"Text on the 'run' button for increasing to 4x speed\"\n                defaultMessage=\"Turbo (4x)\"\n                />,\n        },\n        {\n            rate: 2500,\n            label: <FormattedMessage\n                id=\"buttonStepRate50x\"\n                description=\"Text on the 'run' button for increasing to 50x speed\"\n                defaultMessage=\"Turbo (50x)\"\n                />,\n        },\n    ];\n\n    private codeView = React.createRef<Sic1CodeView>();\n\n    private stateFlags = StateFlags.none;\n    private stepRateIndex: number | undefined = undefined;\n    private stepsPerInterval = 1;\n    private resetRequired = false; // True if the current/last step incremented the testSetIndex, necessitating a post-step reset\n    private runToken?: number;\n    private memoryMap: number[][];\n    private programBytes: number[];\n    private emulator: Emulator;\n    private testSetIndex: number;\n    private solutionCyclesExecuted?: number;\n    private solutionMemoryBytesAccessed?: number;\n\n    constructor(props: Sic1IdeProperties) {\n        super(props);\n\n        const memoryMap: number[][] = [];\n        for (let i = 0; i < 16; i++) {\n            let row: number[] = [];\n            for (let j = 0; j < 16; j++) {\n                row.push(16 * i + j);\n            }\n            memoryMap.push(row);\n        }\n        this.memoryMap = memoryMap;\n\n        const data = Sic1DataManager.getData();\n        let state: Sic1IdeState = {\n            executing: false,\n            tabInsertMode: !!data.tabInsertMode,\n            autoIndentMode: !!data.autoIndentMode,\n            ...Sic1Ide.createEmptyPuzzleState(),\n            ...Sic1Ide.createEmptyTransientState(props.intl, props.puzzle, props.solutionName),\n        };\n\n        this.state = state;\n        this.testSetIndex = 0;\n    }\n\n    private static createEmptyPuzzleState(): Sic1IdePuzzleState {\n        let state: Sic1IdePuzzleState = {\n            watchedAddresses: new Set(),\n        };\n        return state;\n    }\n\n    private static createEmptyTransientState(intl: IntlShape, puzzle: ClientPuzzle, solutionName: string): Sic1IdeTransientState {\n        const { solution } = Sic1DataManager.getPuzzleDataAndSolution(puzzle.title, solutionName, true);\n        const { customInput: customInputString, customInputFormat, customOutputFormat } = solution;\n        let state: Sic1IdeTransientState = {\n            stateLabel: Sic1Ide.stateStatusStopped,\n            currentAddress: null,\n            currentInputIndex: null,\n            currentOutputIndex: null,\n            cyclesExecuted: 0,\n            memoryBytesAccessed: 0,\n            sourceLines: [],\n            actualOutputBytes: [],\n            unexpectedOutputIndexes: {},\n            variables: [],\n            variableToAddress: {},\n            sourceLineToBreakpointState: {},\n            hasReadInput: false,\n\n            // Load input from puzzle definition by default, but use saved input for sandbox mode\n            customInputString,\n            test: hasCustomInput(puzzle)\n                ? { testSets: [{ input: tryParseValues(intl, customInputString) ?? [] }] }\n                : generatePuzzleTest(puzzle),\n            \n            inputFormat: customInputFormat ? formatNameToFormat[customInputFormat] : puzzle.inputFormat,\n            outputFormat: customOutputFormat ? formatNameToFormat[customOutputFormat] : puzzle.outputFormat,\n        };\n\n        // Initialize memory\n        for (let i = 0; i < 256; i++) {\n            state[i] = 0;\n        }\n\n        return state;\n    }\n\n    private static rateToIntervalParameters(stepsPerSecond: number): { periodMS: number, stepsPerPeriod: number } {\n        const minimumPeriodMS = 16;\n        let periodMS = Math.round(1000 / stepsPerSecond);\n        let stepsPerPeriod = 1;\n        if (periodMS < minimumPeriodMS) {\n            periodMS = minimumPeriodMS;\n            stepsPerPeriod = Math.ceil(stepsPerSecond / (1000 / periodMS));\n        }\n\n        return {\n            periodMS,\n            stepsPerPeriod,\n        };\n    }\n\n    private getLongestIOTable(): number[] {\n        const a = this.state.test.testSets[this.testSetIndex].input;\n\n        // Use expected output length, if available; otherwise, use actual output length\n        const b = this.state.test.testSets[this.testSetIndex][\"output\"] ?? this.state.actualOutputBytes;\n\n        return (a.length >= b.length) ? a : b;\n    }\n\n    private setStepRateIndex(index: number | undefined): void {\n        if (index !== this.stepRateIndex) {\n            if (this.runToken !== undefined) {\n                window.clearInterval(this.runToken);\n                this.runToken = undefined;\n            }\n\n            const executing = (index !== undefined);\n            if (executing) {\n                const { periodMS, stepsPerPeriod } = Sic1Ide.rateToIntervalParameters(Sic1Ide.stepRates[index].rate);\n                this.stepsPerInterval = stepsPerPeriod;\n                this.runToken = window.setInterval(this.runCallback, periodMS);\n            }\n\n            this.stepRateIndex = index;\n            this.setState({ executing });\n        }\n    }\n\n    private setStateFlags(newStateFlags: StateFlags): void {\n        this.stateFlags = newStateFlags;\n\n        const running = !!(newStateFlags & StateFlags.running);\n        let success = false;\n        let stateLabel = Sic1Ide.stateStatusStopped;\n        const error = !!(newStateFlags & StateFlags.error);\n        if ((newStateFlags & StateFlags.done) && !error) {\n            success = true;\n        } else if (running) {\n            stateLabel = Sic1Ide.stateStatusRunning;\n        }\n\n        this.setState({ stateLabel });\n\n        if (success) {\n            // Show message box\n            this.props.onPuzzleCompleted(this.solutionCyclesExecuted, this.solutionMemoryBytesAccessed, this.programBytes);\n            this.stop();\n        } else if (error) {\n            this.props.onOutputIncorrect();\n        }\n\n        if (!running || success || error) {\n            this.setStepRateIndex(undefined);\n        }\n    }\n\n    private setStateFlag(flag: StateFlags, on: boolean = true): void {\n        if (on === false) {\n            this.setStateFlags(this.stateFlags & ~flag);\n        } else {\n            this.setStateFlags(this.stateFlags | flag);\n        }\n    }\n\n    private updateMemory(address: number, value: number): void {\n        this.setState({ [address]: value });\n    }\n\n    private load(): boolean {\n        try {\n            const sourceLines = this.codeView.current.getCode().split(\"\\n\");\n            this.setState({ sourceLines });\n\n            this.emulator = null;\n            this.setStateFlags(StateFlags.none);\n\n            let inputIndex = 0;\n            let outputIndex = 0;\n            let done = false;\n            let readInput = false;\n            const assembledProgram = Assembler.assemble(sourceLines);\n            const breakpointSet = new Set(assembledProgram.breakpoints);\n\n            const sourceLineToBreakpointState = Object.fromEntries(Object.entries(assembledProgram.sourceMap)\n                .filter(([address, sme]) => (sme && sme.command === Command.subleqInstruction))\n                .map(([address, sme]) => [sme.lineNumber, breakpointSet.has(parseInt(address))]));\n\n            this.setState({\n                variableToAddress: Object.fromEntries(assembledProgram.variables.map(({label, address}) => [label, address])),\n                sourceLineToBreakpointState,\n            });\n\n            this.programBytes = assembledProgram.bytes.slice();\n            this.emulator = new Emulator(assembledProgram, {\n                readInput: () => {\n                    // Get next input, or zero if past the end\n                    const inputBytes = this.state.test.testSets[this.testSetIndex].input;\n                    var value = (inputIndex < inputBytes.length) ? inputBytes[inputIndex] : 0;\n                    inputIndex++;\n                    readInput = true;\n\n                    return value;\n                },\n\n                writeOutput: (value) => {\n                    const expectedOutputBytes = this.state.test.testSets[this.testSetIndex][\"output\"];\n                    if (expectedOutputBytes) {\n                        if (outputIndex < expectedOutputBytes.length) {\n                            this.setState(state => ({ actualOutputBytes: [...state.actualOutputBytes, value] }));\n    \n                            if (value !== expectedOutputBytes[outputIndex]) {\n                                this.setStateFlag(StateFlags.error);\n                                const index = outputIndex;\n                                this.setState(state => {\n                                    const unexpectedOutputIndexes = {};\n                                    for (let key in state.unexpectedOutputIndexes) {\n                                        unexpectedOutputIndexes[key] = state.unexpectedOutputIndexes[key];\n                                    }\n                                    unexpectedOutputIndexes[index] = true;\n                                    return { unexpectedOutputIndexes };\n                                });\n                            }\n    \n                            this.props.onOutputCorrect();\n                            ++outputIndex;\n                        }\n                    } else {\n                        this.setState(state => ({ actualOutputBytes: [...state.actualOutputBytes, value] }));\n                    }\n                },\n\n                onWriteMemory: (address, value) => {\n                    this.updateMemory(address, value);\n                },\n\n                onStateUpdated: (data) => {\n                    // Check for program\n                    if (this.emulator && this.emulator.isEmpty()) {\n                        this.props.onNoProgram();\n                        this.setStateFlag(StateFlags.error);\n                    }\n\n                    // Check for breakpoint\n                    if (this.state.sourceLineToBreakpointState[data.sourceLineNumber]) {\n                        this.setStepRateIndex(undefined);\n                    }\n\n                    // Check for completion, or a need to advance to the next test set\n                    const expectedOutputBytes = this.state.test.testSets[this.testSetIndex][\"output\"];\n                    if (expectedOutputBytes) {\n                        if (this.emulator && this.emulator.isRunning() && outputIndex == expectedOutputBytes.length && !this.hasError()) {\n                            if (this.testSetIndex === 0) {\n                                // Record stats from the first test set\n                                this.solutionCyclesExecuted = this.emulator.getCyclesExecuted();\n                                this.solutionMemoryBytesAccessed = this.emulator.getMemoryBytesAccessed();\n                            }\n    \n                            if (this.testSetIndex === this.state.test.testSets.length - 1) {\n                                done = true;\n                            } else {\n                                this.testSetIndex++;\n                                inputIndex = 0;\n                                outputIndex = 0;\n                                this.setState({ actualOutputBytes: [] });\n                                this.resetRequired = true;\n                            }\n                        }\n                    }\n\n                    // Note: Halt is treated as \"still running\" so that memory, etc. can be inspected\n                    this.setStateFlag(StateFlags.running, data.running || data.ip > Constants.addressInstructionMax);\n                    this.setState(state => ({\n                        cyclesExecuted: data.cyclesExecuted,\n                        memoryBytesAccessed: data.memoryBytesAccessed,\n                        currentSourceLine: (data.ip <= Constants.addressUserMax) ? data.sourceLineNumber : undefined,\n                        currentAddress: data.ip,\n                        currentInputIndex: (inputIndex < this.state.test.testSets[this.testSetIndex].input.length) ? inputIndex : null,\n                        currentOutputIndex: (outputIndex < this.state.test.testSets[this.testSetIndex][\"output\"]?.length) ? outputIndex : null,\n                        variables: data.variables,\n                        hasReadInput: state.hasReadInput || readInput,\n                    }));\n\n                    if (done) {\n                        this.setStateFlag(StateFlags.done);\n                    }\n                },\n            });\n\n            return true;\n        } catch (error) {\n            if (error instanceof CompilationError) {\n                this.props.onCompilationError(error);\n                if (error.context && (error.context.sourceLineNumber !== undefined) && (error.context.sourceLine !== undefined)) {\n                    if (this.codeView.current) {\n                        this.codeView.current.selectLine?.(error.context.sourceLineNumber, error.context.sourceLine);\n                        this.codeView.current.focusIfNeeded();\n                    }\n                }\n            } else {\n                throw error;\n            }\n        }\n        return false;\n    }\n\n    private stepInternal() {\n        if (this.emulator && !this.isDone()) {\n            this.emulator.step();\n            if (!this.emulator.isRunning()) {\n                // Execution halted\n                this.setStepRateIndex(undefined);\n                this.props.onHalt();\n            } else if (this.resetRequired) {\n                this.resetRequired = false;\n                this.emulator.reset();\n            }\n        }\n    }\n\n    private step = () => {\n        this.setStepRateIndex(undefined);\n        if (this.hasStarted()) {\n            this.stepInternal();\n        } else {\n            this.load();\n        }\n    }\n\n    private runCallback = () => {\n        for (let i = 0; (i < this.stepsPerInterval) && (this.stepRateIndex !== undefined); i++) {\n            this.stepInternal();\n        }\n    }\n\n    private run = () => {\n        let loaded = this.hasStarted() ? true : this.load();\n        if (loaded && !this.isDone()) {\n            this.setStepRateIndex(0);\n        }\n    }\n\n    private increaseSpeed = () => {\n        if (this.stepRateIndex >= 0 && this.stepRateIndex < (Sic1Ide.stepRates.length - 1)) {\n            this.setStepRateIndex(this.stepRateIndex + 1);\n        }\n    }\n\n    private menu = () => {\n        this.setStepRateIndex(undefined);\n        this.props.onMenuRequested();\n    }\n\n    private help = () => {\n        this.setStepRateIndex(undefined);\n        this.props.onHelpRequested();\n    }\n\n    private keyDownHandler = (event: KeyboardEvent): void => {\n        if (event.ctrlKey || event.metaKey) {\n            if (event.shiftKey) {\n                if (event.key === \"Enter\") {\n                    if (this.stepRateIndex !== undefined) {\n                        this.pause();\n                    } else {\n                        this.stop();\n                    }\n                }\n            } else {\n                if (event.key === \"Enter\") {\n                    if (this.stepRateIndex !== undefined) {\n                        this.increaseSpeed();\n                    } else if (!this.hasError()) {\n                        this.run();\n                    }\n                } else if (event.key === \".\") {\n                    this.step();\n                } else if (event.key === \"z\" || event.key === \"y\") {\n\n                    // This is an annoying, but apparently necessary hack. While running, if the user hits Ctrl+Z, the\n                    // (hidden) textarea's value is *not* modified, but the position in the undo/redo stack *is*\n                    // changed. So if the user types Ctrl+Z or Ctrl+Y while running, and then again afterwards, the\n                    // undo/redo history gets confused and corrupts the text in the textarea.\n                    //\n                    // Unfortunately, marking the textarea as hidden/disabled/readonly doesn't avoid this problem, so\n                    // my hacky solution here is to just trap Ctrl+Z and Ctrl+Y when running.\n\n                    if (this.hasStarted()) {\n                        event.preventDefault();\n                    }\n                }\n            }\n        }\n\n        if (event.key === \"F1\") {\n            this.menu();\n            event.preventDefault();\n        }\n    }\n\n    private formatCharacter(byte: number): string {\n        if (byte === 0 /* Null terminator */) {\n            return \"'\\\\0'\";\n        } else if (byte === 10 /* New line */) {\n            return \"'\\\\n'\";\n        } else if (byte === 39 /* apostrophe */ || byte === 92 /* backslash */) {\n            return `'\\\\${String.fromCharCode(byte)}'`\n        } else if (byte >= 32 && byte <= 126) {\n            return `'${String.fromCharCode(byte)}'`\n        } else {\n            return \"\\u25A1\";\n        }\n    }\n\n    private formatByte(byte: number, format?: Format): string | number {\n        switch (format) {\n            case Format.characters:\n                return this.formatCharacter(byte);\n\n            default:\n                return byte;\n        }\n    }\n\n    private formatStringCharacter(byte: number): string {\n        if ((byte >= 32 && byte <= 126) || byte === 10) {\n            const character = String.fromCharCode(byte);\n            if (character === '\"' || character === \"\\\\\") {\n                return \"\\\\\" + character;\n            }\n            return character;\n        } else {\n            return \"\\u25A1\";\n        }\n    }\n\n    private formatAndMarkString(numbers: number[], markIndex?: number, showTerminators?: boolean): (React.ReactNode)[] {\n        let parts: string[];\n        if (markIndex !== undefined) {\n            // Split string (and insert \"\\n\" to indicate a newline, if that's the current character)\n            parts = [\n                numbers.slice(0, markIndex).reduce((acc, value) => acc + this.formatStringCharacter(value), \"\"),\n                (markIndex < numbers.length)\n                    ? ((numbers[markIndex] === 10)\n                        ? \"\\\\n\\n\"\n                        : this.formatStringCharacter(numbers[markIndex]))\n                    : ((markIndex === numbers.length && showTerminators === true)\n                        ? \"\\\\0\"\n                        : \"\"),\n                numbers.slice(markIndex + 1).reduce((acc, value) => acc + this.formatStringCharacter(value), \"\"),\n            ];\n        } else {\n            parts = [numbers.reduce((acc, value) => acc + this.formatStringCharacter(value), \"\")];\n        }\n\n        // Convert newline characters to br elements\n        return parts.map(part => {\n            const lines = part.split(\"\\n\");\n            const result: React.ReactNode[] = [lines[0]];\n            for (let i = 1; i < lines.length; i++) {\n                result.push(<br key={`br${i}`} />, lines[i]);\n            }\n            return result;\n        });\n    }\n\n    private splitStrings(numbers: number[]): number[][] {\n        const split: number[][] = [];\n        let startIndex = 0;\n        let zeroIndex: number;\n        while ((zeroIndex = numbers.indexOf(0, startIndex)) >= 0) {\n            split.push(numbers.slice(startIndex, zeroIndex));\n            startIndex = zeroIndex + 1;\n        }\n        if (numbers[numbers.length - 1] !== 0) {\n            split.push(numbers.slice(startIndex));\n        }\n        return split;\n    }\n\n    private toggleEditorMode(mode: keyof Sic1IdeEditorModeState): void {\n        this.setState((state) => ({ [mode]: !state[mode] } as Pick<Sic1IdeState, keyof Sic1IdeEditorModeState>));\n    }\n\n    private saveEditorMode(mode: keyof Sic1IdeEditorModeState): void {\n        const data = Sic1DataManager.getData();\n        data[mode] = this.state[mode];\n        Sic1DataManager.saveData();\n    }\n\n    public getProgramBytes(): number[] | undefined {\n        return this.programBytes;\n    }\n\n    public hasStarted(): boolean {\n        return !!(this.stateFlags & StateFlags.running);\n    }\n\n    public isDone(): boolean {\n        return !!(this.stateFlags & StateFlags.done);\n    }\n\n    public hasError(): boolean {\n        return !!(this.stateFlags & StateFlags.error);\n    }\n\n    public hasReadInput(): boolean {\n        return this.state.hasReadInput;\n    }\n\n    public pauseOrStop(): boolean {\n        let handled = false;\n        if (this.state.executing) {\n            this.setStepRateIndex(undefined);\n            handled = true;\n        } else if (this.hasStarted()) {\n            this.stop();\n            handled = true;\n        }\n        return handled;\n    }\n\n    public reset(puzzle: ClientPuzzle, solutionName: string) {\n        this.setState(Sic1Ide.createEmptyTransientState(this.props.intl, puzzle, solutionName));\n        this.setStateFlags(StateFlags.none);\n        this.testSetIndex = 0;\n        this.solutionCyclesExecuted = undefined;\n        this.solutionMemoryBytesAccessed = undefined;\n\n        if (this.codeView.current) {\n            this.codeView.current.reset();\n            this.codeView.current.focusIfNeeded();\n        }\n    }\n\n    public getCode(): string {\n        return this.codeView.current.getCode();\n    }\n\n    public pause = () => {\n        this.setStepRateIndex(undefined);\n    }\n\n    public stop = () => {\n        this.setStepRateIndex(undefined);\n        this.reset(this.props.puzzle, this.props.solutionName);\n        this.setStateFlags(StateFlags.none);\n    }\n\n    public componentDidMount() {\n        window.addEventListener(\"keydown\", this.keyDownHandler);\n    }\n\n    public componentWillUnmount() {\n        this.setStepRateIndex(undefined);\n        window.removeEventListener(\"keydown\", this.keyDownHandler);\n    }\n\n    public componentDidUpdate(previousProps: Readonly<Sic1IdeProperties>, previousState: Readonly<Sic1IdeState>, snapshot: any): void {\n        for (const mode of [\"tabInsertMode\", \"autoIndentMode\"] as const) {\n            if (previousState[mode] !== this.state[mode]) {\n                this.saveEditorMode(mode);\n            }\n        }\n\n        // Reset state that persists within a puzzle if the puzzle changed\n        if (previousProps.puzzle !== this.props.puzzle) {\n            this.setState(Sic1Ide.createEmptyPuzzleState());\n        }\n    }\n\n    public render() {\n        const inputBytes = this.state.test.testSets[this.testSetIndex].input;\n\n        const renderStrings = (splitStrings: number[][], rows: number, colSpan: number, showTerminators: boolean, currentIndex: number | null, unexpectedOutputIndexes?: {[index: number]: boolean}) => {\n            let elements: React.JSX.Element[] = [];\n            let renderIndex = 0;\n            for (let i = 0; i < rows; i++) {\n                const numbers = (i < splitStrings.length) ? splitStrings[i] : null;\n                let body: React.ReactNode;\n                let highlightRow: boolean;\n\n                let errorInRow = false;\n                if (numbers) {\n                    // Check for error\n                    if (unexpectedOutputIndexes) {\n                        // Note: <= length to include zero terminator\n                        for (let j = 0; j <= numbers.length; j++) {\n                            if (unexpectedOutputIndexes[renderIndex++]) {\n                                errorInRow = true;\n                            }\n                        }\n                    }\n\n                    // Highlight current index\n                    highlightRow = (currentIndex !== null && currentIndex >= 0 && currentIndex <= numbers.length);\n                    if (highlightRow) {\n                        const parts = this.formatAndMarkString(numbers, currentIndex, showTerminators);\n                        body = <>\"{parts[0]}<span className=\"mark\">{parts[1]}</span>{parts[2]}\"</>\n                    } else {\n                        body = <>\"{this.formatAndMarkString(numbers)[0]}\"</>\n                    }\n                } else {\n                    highlightRow = (currentIndex === 0);\n                    body = <>&nbsp;</>\n                    currentIndex = null;\n                }\n\n                elements.push(<td colSpan={colSpan} className={\"text \" + (errorInRow ? \"attention\" : (highlightRow ? \"emphasize\" : \"\"))}>\n                    {body}\n                </td>);\n\n                if (currentIndex !== null && numbers) {\n                    currentIndex -= (numbers.length + 1);\n                }\n            }\n            return elements;\n        };\n\n        // IO table data; first determine number of columns to span\n        const colSpan = (this.state.inputFormat === Format.strings && this.state.outputFormat !== Format.strings) ? 2 : 1;\n\n        let inputFragments: React.JSX.Element[];\n        if (this.state.inputFormat === Format.strings) {\n            const splitStrings = this.splitStrings(inputBytes);\n            inputFragments = renderStrings(splitStrings, splitStrings.length, colSpan, true, this.state.currentInputIndex);\n        } else {\n            const baseClassName = (this.state.inputFormat === Format.characters) ? \"center \" : \"\";\n            inputFragments = inputBytes.map((x, index) =>\n                <td key={`input${index}`} colSpan={colSpan} className={baseClassName + (this.state.currentInputIndex === index ? \"emphasize\" : \"\")}>\n                    {(index < inputBytes.length)\n                    ? this.formatByte(inputBytes[index], this.state.inputFormat)\n                    : null}\n                </td>);\n        }\n\n        const expectedOutputBytes = this.state.test.testSets[this.testSetIndex][\"output\"];\n        const hasExpectedOutput = !!expectedOutputBytes;\n        let expectedFragments: React.ReactNode[];\n        let actualFragments: React.ReactNode[];\n        if (this.state.outputFormat === Format.strings) {\n            let expectedSplitStrings: number[][];\n            if (hasExpectedOutput) {\n                expectedSplitStrings = this.splitStrings(expectedOutputBytes);\n                expectedFragments = renderStrings(expectedSplitStrings, expectedSplitStrings.length, 1, true, this.state.currentOutputIndex, this.state.unexpectedOutputIndexes);\n            }\n\n            actualFragments = renderStrings(\n                this.splitStrings(this.state.actualOutputBytes),\n                hasExpectedOutput\n                    ? expectedSplitStrings.length\n                    : this.state.actualOutputBytes.filter(x => (x === 0)).length + 1,\n                1,\n                false,\n                this.state.currentOutputIndex,\n                this.state.unexpectedOutputIndexes,\n            );\n        } else {\n            const baseClassName = (this.state.outputFormat === Format.characters) ? \"center \" : \"\";\n            if (hasExpectedOutput) {\n                expectedFragments = expectedOutputBytes.map((x, index) =>\n                    <td key={`expected${index}`} className={baseClassName + (this.state.unexpectedOutputIndexes[index] ? \"attention\" : (this.state.currentOutputIndex === index ? \"emphasize\" : \"\"))}>\n                        {(index < expectedOutputBytes.length)\n                        ? this.formatByte(expectedOutputBytes[index], this.state.outputFormat)\n                        : null}\n                    </td>\n                );\n                actualFragments = expectedOutputBytes.map((x, index) =>\n                    <td key={`actual${index}`} className={baseClassName + (this.state.unexpectedOutputIndexes[index] ? \"attention\" : (this.state.currentOutputIndex === index ? \"emphasize\" : \"\"))}>\n                        {(index < this.state.actualOutputBytes.length)\n                        ? this.formatByte(this.state.actualOutputBytes[index], this.state.outputFormat)\n                        : <>&nbsp;</>}\n                    </td>\n                );\n            } else {\n                actualFragments = this.state.actualOutputBytes.map((x, index) => <td key={`actual${index}`}>{\n                    this.formatByte(this.state.actualOutputBytes[index], this.state.outputFormat)\n                }</td>)\n            }\n        }\n\n        // IO table\n        let columns: number;\n        let ioFragment: React.ReactNode;\n        if (this.state.inputFormat === Format.strings && this.state.outputFormat !== Format.strings) {\n            // Two columns (or 1 for sandbox) for expected/actual output, one column for input, input stacked above output\n            columns = 2;\n\n            ioFragment = <>\n                <tbody>\n                    <tr><th colSpan={hasExpectedOutput ? 2 : 1}>{Shared.resources.headerIOIn}</th></tr>\n                    {inputFragments.map((fragment, index) => <tr key={`input${index}`}>{fragment}</tr>)}\n                    <tr>{hasExpectedOutput ? <th>{Sic1Ide.headerIOExpected}</th> : null}<th>{hasExpectedOutput ? Sic1Ide.headerIOActual : Shared.resources.headerIOOut}</th></tr>\n                    {hasExpectedOutput\n                        ? expectedOutputBytes.map((x, index) => <tr key={`expected${index}`}>\n                                {(index < expectedFragments.length) ? expectedFragments[index] : <td></td>}\n                                {(index < actualFragments.length) ? actualFragments[index] : <td></td>}\n                            </tr>)\n                        : actualFragments.map((td, index) => <tr key={`actual${index}`}>{td}</tr>)\n                    }\n                </tbody>\n            </>;\n        } else if (this.state.inputFormat === Format.strings || this.state.outputFormat === Format.strings) {\n            // Single column to accommodate strings\n            columns = 1;\n            ioFragment = <>\n                <tbody>\n                    <tr><th>{Shared.resources.headerIOIn}</th></tr>\n                    {inputFragments.map((fragment, index) => <tr key={`input${index}`}>{fragment}</tr>)}\n                    {hasExpectedOutput ? <>\n                        <tr><th>{Sic1Ide.headerIOExpected}</th></tr>\n                        {expectedFragments.map((fragment, index) => <tr key={`expected${index}`}>{fragment}</tr>)}\n                    </> : null}\n                    <tr><th>{Sic1Ide.headerIOActual}</th></tr>\n                    {actualFragments.map((fragment, index) => <tr key={`actual${index}`}>{fragment}</tr>)}\n                </tbody>\n            </>;\n        } else {\n            // Three (or two, for sandbox) columns\n            columns = hasExpectedOutput ? 3 : 2;\n            ioFragment = <>\n                <tbody>\n                <tr><th>{Shared.resources.headerIOIn}</th>{hasExpectedOutput ? <th>{Sic1Ide.headerIOExpected}</th> : null}<th>{hasExpectedOutput ? Sic1Ide.headerIOActual : Shared.resources.headerIOOut}</th></tr>\n                {\n                    this.getLongestIOTable().map((x, index) => <tr key={index}>\n                        {(index < inputFragments.length) ? inputFragments[index] : <td></td>}\n                        {hasExpectedOutput ? ((index < expectedFragments.length) ? expectedFragments[index] : <td></td>) : null}\n                        {(index < actualFragments.length) ? actualFragments[index] : <td></td>}\n                    </tr>)\n                }\n                </tbody>\n            </>;\n        }\n\n        return <div className=\"ide\">\n            <div className=\"controls\">\n                <table>\n                    <tbody>\n                        <tr><th>{this.props.puzzle.displayTitle}</th></tr>\n                        <tr><td className=\"text\">{this.props.puzzle.description}</td></tr>\n                    </tbody>\n                </table>\n                <br />\n                {hasCustomInput(this.props.puzzle) ? <>\n                    <Button\n                        className=\"normal\"\n                        disabled={this.hasStarted()}\n                        onClick={() => this.props.onShowMessageBox({\n                            title: this.props.intl.formatMessage({\n                                id: \"windowConfigureInput\",\n                                description: \"Window title for configuring input in Sandbox Mode\",\n                                defaultMessage: \"Configure Input\",\n                            }),\n                            width: \"narrowByDefault\",\n                            body: <Sic1InputEditor\n                                intl={this.props.intl}\n                                defaultInputString={this.state.customInputString}\n                                defaultInputFormat={this.state.inputFormat}\n                                defaultOutputFormat={this.state.outputFormat}\n                                onApply={({ input, text: customInputString, inputFormat, outputFormat }) => {\n                                    this.setState({\n                                        customInputString,\n                                        inputFormat,\n                                        outputFormat,\n                                        test: { testSets: [{ input }] },\n                                    });\n\n                                    // Save\n                                    const { title } = this.props.puzzle;\n                                    const { solutionName } = this.props;\n                                    const { solution } = Sic1DataManager.getPuzzleDataAndSolution(title, solutionName, false);\n                                    if (solution) {\n                                        solution.customInput = customInputString;\n                                        solution.customInputFormat = formatToName[inputFormat];\n                                        solution.customOutputFormat = formatToName[outputFormat];\n                                        Sic1DataManager.savePuzzleData(title);\n                                    }\n                                }}\n                                onClose={() => this.props.onCloseMessageBox()}\n                                />,\n                        })}\n                    >\n                        <FormattedMessage\n                            id=\"buttonConfigureInput\"\n                            description=\"Text on the 'configure input' button, which supports editing input for Sandbox Mode\"\n                            defaultMessage=\"Configure Input\"\n                            />\n                    </Button>\n                    <br/>\n                </> : null}\n                <div className=\"ioBox\">\n                    <table>\n                        <thead><tr><th colSpan={columns}>\n                            <FormattedMessage\n                                id=\"headerTestSet\"\n                                description=\"Header for the IO table, indicating which test set is running\"\n                                defaultMessage=\"Test {number}\"\n                                values={{ number: this.testSetIndex + 1 }}\n                                />\n                        </th></tr></thead>\n                        {ioFragment}\n                    </table>\n                </div>\n                <br />\n                <table>\n                    <tbody>\n                        <tr>\n                            <th className=\"horizontal\">\n                                <FormattedMessage\n                                    id=\"labelStateRunning\"\n                                    description=\"Label in the 'state' table for running vs. stopped (note: this string should be as short as possible)\"\n                                    defaultMessage=\"State\"\n                                    />\n                            </th>\n                            <td>{this.state.stateLabel}</td>\n                        </tr>\n                        <tr>\n                            <th className=\"horizontal\">\n                                <FormattedMessage\n                                    id=\"labelStateCycles\"\n                                    description=\"Label in the 'state' table for cycle count (note: this string should be as short as possible)\"\n                                    defaultMessage=\"Cycles\"\n                                    />\n                            </th>\n                            <td>{this.state.cyclesExecuted}</td>\n                        </tr>\n                        <tr>\n                            <th className=\"horizontal\">\n                                <FormattedMessage\n                                        id=\"labelStateBytes\"\n                                        description=\"Label in the 'state' table for byte count (note: this string should be as short as possible)\"\n                                        defaultMessage=\"Bytes\"\n                                        />\n                            </th>\n                            <td>{this.state.memoryBytesAccessed}</td>\n                        </tr>\n                    </tbody>\n                </table>\n                <br />\n                <Button\n                    onClick={this.state.executing ? this.pause : this.stop}\n                    disabled={!this.hasStarted()}\n                    title={this.props.intl.formatMessage({\n                            id: \"tooltipStop\",\n                            description: \"Tooltip for the 'pause/stop' button, indicating keyboard shortcut\",\n                            defaultMessage: \"Esc or Ctrl+Shift+Enter\",\n                        })}\n                    >\n                        {this.state.executing\n                            ? <FormattedMessage\n                                id=\"buttonPause\"\n                                description=\"Text on 'pause' button that pauses a running program\"\n                                defaultMessage=\"Pause\"\n                                />\n                            : <FormattedMessage\n                                id=\"buttonStop\"\n                                description=\"Text on the 'stop' button that stops a running program\"\n                                defaultMessage=\"Stop\"\n                                />}\n                </Button>\n                <Button\n                    onClick={this.step}\n                    disabled={this.isDone()}\n                    title={this.props.intl.formatMessage({\n                        id: \"tooltipStep\",\n                        description: \"Tooltip for the 'step/compile' button, indicating keyboard shortcut\",\n                        defaultMessage: \"Ctrl+.\",\n                    })}\n                    >\n                        {this.hasStarted()\n                            ? <FormattedMessage\n                                id=\"buttonStep\"\n                                description=\"Text on the 'step' button, for advancing the debugger one instruction\"\n                                defaultMessage=\"Step\"\n                                />\n                            : <FormattedMessage\n                                id=\"buttonCompile\"\n                                description=\"Text on the 'compile' button, for compiling a program and loading it into the debugger\"\n                                defaultMessage=\"Compile\"\n                                />}\n                </Button>\n                <Button\n                    onClick={this.state.executing ? this.increaseSpeed : this.run}\n                    disabled={this.isDone() || this.hasError() || (this.stepRateIndex >= Sic1Ide.stepRates.length - 1)}\n                    title={this.props.intl.formatMessage({\n                        id: \"tooltipStepRate\",\n                        description: \"Tooltip for the 'run/turbo' button, which adjusts the program execution speed\",\n                        defaultMessage: \"Ctrl+Enter\",\n                    })}\n                    >\n                    {Sic1Ide.stepRates[Math.min(Sic1Ide.stepRates.length - 1, (this.stepRateIndex ?? -1) + 1)].label}\n                </Button>\n                <Button onClick={this.help}>\n                    <FormattedMessage\n                        id=\"buttonHelp\"\n                        description=\"Text on the 'help' button, which displays the help menu, providing hints and a link to the manual\"\n                        defaultMessage=\"Help\"\n                        />\n                </Button>\n                <Button\n                    onClick={this.menu}\n                    title={this.props.intl.formatMessage({\n                        id: \"tooltipMenu\",\n                        description: \"Tooltip for the 'menu' button, which opens the main menu\",\n                        defaultMessage: \"Esc or F1\",\n                    })}\n                    >\n                        <FormattedMessage\n                        id=\"buttonMenu\"\n                        description=\"Text on the 'menu' button, which opens the main menu\"\n                        defaultMessage=\"Menu\"\n                        />\n                </Button>\n                <div className=\"controlFooter\"></div>\n            </div>\n            <Sic1CodeView\n                ref={this.codeView}\n                key={`${this.props.puzzle.title}:${this.props.solutionName}`}\n\n                puzzle={this.props.puzzle}\n                solutionName={this.props.solutionName}\n                defaultCode={this.props.defaultCode}\n\n                tabInsertMode={this.state.tabInsertMode}\n                autoIndentMode={this.state.autoIndentMode}\n\n                hasStarted={this.hasStarted()}\n                sourceLines={this.state.sourceLines}\n                sourceLineToBreakpointState={this.state.sourceLineToBreakpointState}\n                currentAddress={this.state.currentAddress}\n                currentSourceLine={this.state.currentSourceLine}\n\n                onSave={() => this.props.onSaveRequested()}\n                onToggleBreakpoint={(lineNumber) => this.setState(state => ({ sourceLineToBreakpointState: { ...state.sourceLineToBreakpointState, [lineNumber]: !state.sourceLineToBreakpointState[lineNumber] } }))}\n                onToggleTabInsertMode={() => this.toggleEditorMode(\"tabInsertMode\")}\n                />\n            <div className=\"state\">\n                <Sic1Memory\n                    hasStarted={this.hasStarted()}\n                    currentAddress={this.state.currentAddress}\n                    memoryMap={this.memoryMap}\n                    memory={this.state}\n                    watchedAddresses={this.state.watchedAddresses}\n                    highlightAddress={this.state.highlightAddress}\n                    onSetHighlightAddress={(highlightAddress) => this.setState({ highlightAddress })}\n                    onToggleWatch={(address) => this.setState((state) => ({ watchedAddresses: Shared.toggleSetValue(state.watchedAddresses, address) }))}\n                    />\n                <br />\n                {this.hasStarted()\n                    ? <Sic1Watch\n                        hasStarted={this.stateFlags !== StateFlags.none}\n                        memory={this.state}\n                        variables={this.state.variables}\n                        variableToAddress={this.state.variableToAddress}\n                        watchedAddresses={this.state.watchedAddresses}\n                        highlightAddress={this.state.highlightAddress}\n                        onSetHighlightAddress={(highlightAddress) => this.setState({ highlightAddress })}\n                        />\n                    : <>\n                        <table>\n                            <thead><tr><th>\n                                <FormattedMessage\n                                    id=\"headingEditing\"\n                                    description=\"Heading for the 'editing tools' panel, which contains buttons for modifying program text\"\n                                    defaultMessage=\"Editing Tools\"\n                                    />\n                            </th></tr></thead>\n                            <tbody><tr><td>\n                                <div className=\"controls controlGroup\">\n                                    <Button\n                                        onClick={() => this.codeView.current.blockComment()}\n                                        title={this.props.intl.formatMessage({\n                                            id: \"tooltipCommentBlock\",\n                                            description: \"Tooltip for the 'comment block' button, which comments out the selected lines of program text\",\n                                            defaultMessage: \"Ctrl+K Ctrl+C\",\n                                        })}\n                                        >\n                                            <FormattedMessage\n                                                id=\"buttonCommentBlock\"\n                                                description=\"Text on the 'comment block' button, which comments out the selected lines of program text\"\n                                                defaultMessage=\"Comment Block\"\n                                                />\n                                    </Button>\n                                    <Button\n                                        onClick={() => this.codeView.current.blockUncomment()}\n                                        title={this.props.intl.formatMessage({\n                                            id: \"tooltipUncommentBlock\",\n                                            description: \"Tooltip for the 'uncomment block' button, which uncomments the selected lines of program text\",\n                                            defaultMessage: \"Ctrl+K Ctrl+U\",\n                                        })}\n                                        >\n                                            <FormattedMessage\n                                                id=\"buttonUncommentBlock\"\n                                                description=\"Text on the 'uncomment block' button, which comments the selected lines of program text\"\n                                                defaultMessage=\"Uncomment Block\"\n                                                />\n                                    </Button>\n                                </div>\n                                <div className=\"controls controlGroup\">\n                                    <Button\n                                        onClick={() => this.codeView.current.indentLines()}\n                                        title={this.props.intl.formatMessage({\n                                            id: \"tooltipIndentBlock\",\n                                            description: \"Tooltip for the 'indent block' button, which prepends one level of indentation to the selected lines of program text (note: the shortcut key is only supported when Tab Insert Mode is enabled)\",\n                                            defaultMessage: \"Tab (in Tab Insert Mode only)\",\n                                        })}\n                                        >\n                                            <FormattedMessage\n                                                id=\"buttonIndentBlock\"\n                                                description=\"Tooltip for the 'indent block' button, which prepends one level of indentation to the selected lines of program text\"\n                                                defaultMessage=\"Indent Block\"\n                                                />\n                                    </Button>\n                                    <Button\n                                        onClick={() => this.codeView.current.unindentLines()}\n                                        title={this.props.intl.formatMessage({\n                                            id: \"tooltipUnindentBlock\",\n                                            description: \"Tooltip for the 'unindent block' button, which removes one level of indentation from the selected lines of program text (note: the shortcut key is only supported when Tab Insert Mode is enabled)\",\n                                            defaultMessage: \"Shift+Tab (in Tab Insert Mode only)\",\n                                        })}\n                                        >\n                                            <FormattedMessage\n                                                id=\"buttonUnindentBlock\"\n                                                description=\"Text on the 'unindent block' button, which removes one level of indentation from the selected lines of program text\"\n                                                defaultMessage=\"Unindent Block\"\n                                                />\n                                    </Button>\n                                </div>\n                                <div className=\"controls controlGroup\">\n                                    <Button\n                                        onClick={() => this.toggleEditorMode(\"tabInsertMode\")}\n                                        title={this.props.intl.formatMessage({\n                                            id: \"tooltipTabInsertMode\",\n                                            description: \"Tooltip for the 'tab insert mode' toggle button, indicating keyboard shortcut\",\n                                            defaultMessage: \"Ctrl+M\",\n                                        })}\n                                        >\n                                            {this.state.tabInsertMode\n                                                ? <FormattedMessage\n                                                    id=\"buttonDisableTabInsertMode\"\n                                                    description=\"Text on the 'disable tab insert mode' button, which toggles the ability for the tab key to insert a tab character instead of the browser-default behavior of advancing keyboard focus to the next element\"\n                                                    defaultMessage=\"Disable Tab Insert Mode\"\n                                                    />\n                                                : <FormattedMessage\n                                                    id=\"buttonEnableTabInsertMode\"\n                                                    description=\"Text on the 'enable tab insert mode' button, which toggles the ability for the tab key to insert a tab character instead of the browser-default behavior of advancing keyboard focus to the next element\"\n                                                    defaultMessage=\"Enable Tab Insert Mode\"\n                                                />}\n                                    </Button>\n                                    <Button onClick={() => this.toggleEditorMode(\"autoIndentMode\")}>\n                                        {this.state.autoIndentMode\n                                            ? <FormattedMessage\n                                                id=\"buttonDisableAutoIndent\"\n                                                description=\"Text on the 'disable auto-indent mode' button, which toggles automatic insertion of indentation when adding a new line to the program text\"\n                                                defaultMessage=\"Disable Auto-Indent Mode\"\n                                                />\n                                            : <FormattedMessage\n                                                id=\"buttonEnableAutoIndent\"\n                                                description=\"Text on the 'enable auto-indent mode' button, which toggles automatic insertion of indentation when adding a new line to the program text\"\n                                                defaultMessage=\"Enable Auto-Indent Mode\"\n                                                />}\n                                    </Button>\n                                </div>\n                            </td></tr></tbody>\n                        </table>\n                    </>\n                }\n                \n            </div>\n        </div>;\n    }\n}\n", "sic1/client/ts/service.ts": "import * as Contract from \"../../server/contract/contract\";\nimport { Shared } from \"./shared\";\nimport { ChartData, HistogramBucketDetail, HistogramBucketWithDetails, HistogramDetail } from \"./chart-model\";\nimport { steamStatsCache, webStatsCache } from \"./stats-cache\";\nimport { FriendLeaderboardEntry, SteamApi } from \"./steam-api\";\nimport { suppressUpload } from \"./setup\";\nimport { puzzleCount } from \"../../shared/puzzles\";\n\nexport { FriendLeaderboardEntry } from \"./steam-api\";\n\nexport type LeaderboardEntry = Contract.LeaderboardEntry;\ntype Focus = \"cycles\" | \"bytes\";\n\nexport interface ScoreChange {\n    improved: boolean;\n    oldScore: number;\n    newScore: number;\n}\n\nexport interface StatChanges {\n    solvedCount: ScoreChange;\n    cycles: ScoreChange;\n    bytes: ScoreChange;\n}\n\nexport interface PuzzleFriendLeaderboardPromises {\n    cycles: Promise<FriendLeaderboardEntry[]>;\n    bytes: Promise<FriendLeaderboardEntry[]>;\n}\n\nexport interface Sic1Service {\n    updateUserProfileAsync(userId: string, name: string): Promise<void>;\n    getPuzzleStatsAsync(puzzleTitle: string, cycles: number, bytes: number): Promise<{ cycles: ChartData, bytes: ChartData }>;\n    getUserStatsAsync(userId: string, solvedCount: number): Promise<ChartData>;\n\n    updateStatsIfNeededAsync(userId: string, puzzleTitle: string, programBytes: number[], changes: StatChanges): PuzzleFriendLeaderboardPromises | undefined;\n\n    // Steam leaderboards\n    getFriendLeaderboardAsync?: (leaderboardName: string) => Promise<FriendLeaderboardEntry[]>;\n    getPuzzleFriendLeaderboardAsync?: (puzzleTitle: string, focus: Focus) => Promise<FriendLeaderboardEntry[]>;\n\n    /** Attempts to update a Steam friend leaderboard. Note that due to rate-limiting, this may immediately return null instead of a promise. */\n    tryUpdateFriendLeaderboardAsync?: (leaderboardName: string, score: number, details?: number[]) => Promise<void> | null;\n}\n\nconst identity = <T extends unknown>(x: T) => x;\n\ntype ParameterList<T> = {[K in keyof T]: string | number | boolean | undefined | null};\n\ninterface HistogramBounds {\n    min: number;\n    max: number;\n    bucketSize: number;\n}\n\nconst puzzleBucketCount = 20;\nconst userBucketCount = puzzleCount;\n\nfunction calculateBounds(min: number, max: number, bucketCount: number): HistogramBounds {\n    // Center the results if they're not spread out very much\n    if ((max - min) < bucketCount) {\n        min = Math.max(1, min - (bucketCount / 2));\n    }\n\n    return {\n        min,\n        max,\n        bucketSize: Math.max(1, Math.ceil((max - min + 1) / bucketCount)),\n    }\n}\n\nexport function sortAndNormalizeHistogramData(data: Contract.HistogramData, bucketCount: number, highlightedValue?: number, removeOutliers = false): HistogramDetail {\n    let outliers: HistogramBucketDetail[] | undefined = undefined;\n\n    if (removeOutliers) {\n        // Remove upper-end outliers, if necessary\n        const dataCount = data.reduce((count, bucket) => (count + bucket.count), 0);\n        if (dataCount > 4) {\n            // First, sort\n            data = data.slice().sort((a, b) => (a.bucketMax - b.bucketMax));\n\n            // Find inter-quartile range\n            const firstQuarterIndex = Math.ceil(dataCount * 1 / 4);\n            const thirdQuarterIndex = Math.ceil(dataCount * 3 / 4);\n            let firstQuarter: number | undefined = undefined;\n            let thirdQuarter: number | undefined = undefined;\n            let i = 0;\n            for (const { bucketMax, count } of data) {\n                i += count;\n                if (firstQuarter === undefined && i >= firstQuarterIndex) {\n                    firstQuarter = bucketMax;\n                }\n                if (thirdQuarter === undefined && i >= thirdQuarterIndex) {\n                    thirdQuarter = bucketMax;\n                    break;\n                }\n            }\n\n            // Consider anything more than 3 * IQR above 75th percentile an outlier\n            const k = 3;\n            const cutoff = thirdQuarter + k * (thirdQuarter - firstQuarter);\n\n            // Clamp to highlighted value, if provided\n            const max = (highlightedValue === undefined) ? cutoff : Math.max(highlightedValue, cutoff);\n            const firstOutlierIndex = data.findIndex(({ bucketMax }) => (bucketMax > max));\n            if (firstOutlierIndex >= 0) {\n                outliers = data.slice(firstOutlierIndex).map(({ bucketMax, count }) => ({ value: bucketMax, count }));\n                data = data.slice(0, firstOutlierIndex);\n            }\n        }\n    }\n\n    let min = 0;\n    let max = 0;\n    if (data.length > 0) {\n        min = data[0].bucketMax;\n        max = data[0].bucketMax;\n        for (const item of data) {\n            min = Math.min(min, item.bucketMax);\n            max = Math.max(max, item.bucketMax);\n        }\n    }\n\n    const bounds = calculateBounds(min, max, bucketCount);\n\n    // Initialize\n    const bucketed: { [bucket: number]: {\n        count: number,\n        details: { [score: number]: number },\n    } } = {};\n\n    for (let i = 0; i < bucketCount; i++) {\n        const bucket = bounds.min + (bounds.bucketSize * i);\n        bucketed[bucket] = {\n            count: 0,\n            details: {},\n        };\n    }\n\n    // Aggregate\n    for (let i = 0; i < data.length; i++) {\n        const score = data[i].bucketMax;\n        const bucket = Math.floor((score - bounds.min) / bounds.bucketSize) * bounds.bucketSize + bounds.min;\n        const bucketData = bucketed[bucket];\n        const count = data[i].count;\n        bucketData.count += count;\n\n        if (count) {\n            bucketData.details[score] = (bucketData.details[score] ?? 0) + count;\n        }\n    }\n\n    // Project\n    const buckets: HistogramBucketWithDetails[] = [];\n    for (const bucketMax in bucketed) {\n        const bucketData = bucketed[bucketMax];\n        buckets.push({\n            bucketMax: parseInt(bucketMax),\n            count: bucketData.count,\n            details: Object.keys(bucketData.details).sort().map(n => ({ value: parseInt(n), count: bucketData.details[n] })),\n        });\n    }\n\n    return {\n        buckets,\n        outliers,\n    };\n}\n\nfunction enrichAndAggregatePuzzleStats(data: Contract.PuzzleStatsResponse[], cycles: number, bytes: number): { cycles: ChartData, bytes: ChartData } {\n    // Merge and normalize data\n    const cyclesHistogram = sortAndNormalizeHistogramData([].concat(\n        [{ bucketMax: cycles, count: 1 }],\n        ...data.map(d => (d?.cyclesExecutedBySolution ?? [])),\n    ), puzzleBucketCount, cycles, true);\n\n    const bytesHistogram = sortAndNormalizeHistogramData([].concat(\n        [{ bucketMax: bytes, count: 1 }],\n        ...data.map(d => (d?.memoryBytesAccessedBySolution ?? [])),\n    ), puzzleBucketCount, bytes, true);\n\n    return {\n        cycles: {\n            histogram: cyclesHistogram,\n            highlightedValue: cycles,\n        },\n        bytes: {\n            histogram: bytesHistogram,\n            highlightedValue: bytes,\n        },\n    };\n}\n\nfunction enrichAndAggregateUserStats(data: Contract.UserStatsResponse[], solvedCount: number): ChartData {\n    const histogram = sortAndNormalizeHistogramData([].concat(\n        [{ bucketMax: solvedCount, count: 1 }],\n        ...data.map(d => d.solutionsByUser),\n    ), userBucketCount);\n\n    // Highlight whatever solvedCount is expected locally. This is currently needed for Steam users (who\n    // never upload solutions), but is arguably more user-friendly anyway.\n    return {\n        histogram: histogram,\n        highlightedValue: solvedCount,\n    };\n}\n\nexport class Sic1WebService implements Sic1Service {\n    public static readonly userNameMaxLength = Contract.UserNameMaxLength;\n\n    public async updateUserProfileAsync(userId: string, name: string): Promise<void> {}\n\n    public async getPuzzleStatsAsync(puzzleTitle: string, cycles: number, bytes: number): Promise<{ cycles: ChartData, bytes: ChartData }> {\n        // Start with cached Steam stats, then use live web stats (falling back to the cache on failure), and finally add the new stats\n        const data = [\n            steamStatsCache.puzzleStats[puzzleTitle],\n            webStatsCache.puzzleStats[puzzleTitle],\n        ];\n\n        return enrichAndAggregatePuzzleStats(data, cycles, bytes);\n    }\n\n    public async getUserStatsAsync(userId: string, solvedCount: number): Promise<ChartData> {\n        // Start with cached Steam stats, then use live web stats (falling back to the cache on failure), and finally add the new stats\n        const data = [\n            steamStatsCache.userStats,\n            webStatsCache.userStats,\n        ];\n\n        return enrichAndAggregateUserStats(data, solvedCount);\n    }\n\n    public updateStatsIfNeededAsync(userId: string, puzzleTitle: string, programBytes: number[], changes: StatChanges): PuzzleFriendLeaderboardPromises | undefined { return undefined; }\n}\n\nexport class Sic1SteamService implements Sic1Service {\n    public static solvedCountLeaderboardName = \"Solved Count\";\n\n    private steamApi: SteamApi;\n\n    constructor(steamApi: SteamApi) {\n        this.steamApi = steamApi;\n    }\n\n    private static getLeaderboardName(puzzleTitle: string, focus: Focus): string {\n        return `${puzzleTitle}_${focus}`;\n    }\n\n    private async updateAndGetPuzzleFriendLeaderboard(puzzleTitle: string, focus: Focus, score: number, programBytes: number[]): Promise<FriendLeaderboardEntry[]> {\n        const promiseOrNull = this.tryUpdateFriendLeaderboardAsync(Sic1SteamService.getLeaderboardName(puzzleTitle, focus), score, programBytes);\n        if (promiseOrNull !== null) {\n            await promiseOrNull;\n        }\n        return await this.getPuzzleFriendLeaderboardAsync(puzzleTitle, focus);\n    }\n\n    public async updateUserProfileAsync(userId: string, name: string): Promise<void> {\n        // User profile updates are not supported on Steam\n    }\n\n    public getPuzzleStatsAsync(puzzleTitle: string, cycles: number, bytes: number): Promise<{ cycles: ChartData; bytes: ChartData; }> {\n        // Use bundled stats cache (obviously, this won't always be up to date, but it removes any Steam dependency on the web service)\n        return Promise.resolve(enrichAndAggregatePuzzleStats([steamStatsCache.puzzleStats[puzzleTitle], webStatsCache.puzzleStats[puzzleTitle]], cycles, bytes));\n    }\n\n    public getUserStatsAsync(userId: string, solvedCount: number): Promise<ChartData> {\n        // Use bundled stats cache\n        return Promise.resolve(enrichAndAggregateUserStats([steamStatsCache.userStats, webStatsCache.userStats], solvedCount));\n    }\n\n    public updateStatsIfNeededAsync(userId: string, puzzleTitle: string, programBytes: number[], changes: StatChanges): PuzzleFriendLeaderboardPromises {\n        // For Steam leaderboards, we need to update and *then* retrieve the friend leaderboard\n        const promises: Partial<PuzzleFriendLeaderboardPromises> = {};\n        for (const key of [\"cycles\", \"bytes\"]) {\n            const focus = key as Focus;\n            promises[focus] = changes[focus].improved\n                ? this.updateAndGetPuzzleFriendLeaderboard(puzzleTitle, focus, changes[focus].newScore, programBytes)\n                : this.getPuzzleFriendLeaderboardAsync(puzzleTitle, focus);\n        }\n\n        // Also update the \"solved count\" leaderboard, if needed (after a delay)\n        if (changes.solvedCount.improved) {\n            const updateSolvedCountDelayMS = 1000;\n            setTimeout(() => {\n                // Ignore errors since we're not using the result here\n                this.tryUpdateFriendLeaderboardAsync(Sic1SteamService.solvedCountLeaderboardName, changes.solvedCount.newScore);\n            }, updateSolvedCountDelayMS);\n        }\n\n        return promises as PuzzleFriendLeaderboardPromises;\n    }\n\n    public tryUpdateFriendLeaderboardAsync(leaderboardName: string, score: number, details?: number[]): Promise<void> | null {\n        return this.steamApi.updateLeaderboardEntryAsync(leaderboardName, score, details);\n    }\n\n    public getFriendLeaderboardAsync(leaderboardName: string): Promise<FriendLeaderboardEntry[]> {\n        return this.steamApi.getFriendLeaderboardAsync(leaderboardName);\n    }\n\n    public getPuzzleFriendLeaderboardAsync(puzzleTitle: string, focus: Focus): Promise<FriendLeaderboardEntry[]> {\n        return this.steamApi.getFriendLeaderboardAsync(Sic1SteamService.getLeaderboardName(puzzleTitle, focus));\n    }\n}\n", "sic1/client/ts/contacts.tsx": "import React from \"react\";\nimport { FormattedMessage } from \"react-intl\";\n\nexport interface Contact {\n    name: React.ReactNode;\n    title?: React.ReactNode;\n}\n\nexport function formatContactWithoutTitle(contact: Contact): React.ReactNode {\n    return contact.name;\n}\n\nexport function formatContact(contact: Contact): React.ReactNode {\n    if (contact.title) {\n        return <FormattedMessage\n            id=\"contactWithTitle\"\n            description=\"Display string for a contact when a job title should be shown along with the contact's name\"\n            defaultMessage=\"{name} ({title})\"\n            values={{\n                name: formatContactWithoutTitle(contact),\n                title: contact.title,\n            }}\n            />;\n    } else {\n        return contact.name;\n    }\n}\n\nexport const Contacts = {\n    onboarding: {\n        name: <FormattedMessage\n            id=\"contact_onboardingName\"\n            description=\"Name for the 'onboarding' contact in the story\"\n            defaultMessage=\"SIC Systems Onboarding\"\n            />,\n    },\n    taskManagement: {\n        name: <FormattedMessage\n            id=\"contact_taskManagementName\"\n            description=\"Name for the 'taskManagement' contact in the story\"\n            defaultMessage=\"Automated Task Management\"\n            />,\n    },\n\n    all: {\n        name: <FormattedMessage\n            id=\"contact_allName\"\n            description=\"Name for the 'all' contact in the story\"\n            defaultMessage=\"All Engineering\"\n            />,\n    },\n\n    badManager: {\n        name: <FormattedMessage\n            id=\"contact_badManagerName\"\n            description=\"Name for the 'badManager' contact in the story\"\n            defaultMessage=\"Don Cooper\"\n            />,\n        title: <FormattedMessage\n            id=\"contact_badManagerTitle\"\n            description=\"Job title for the 'badManager' contact in the story\"\n            defaultMessage=\"Senior Engineering Lead\"\n            />,\n    },\n    badManager2: {\n        name: <FormattedMessage\n            id=\"contact_badManager2Name\"\n            description=\"Name for the 'badManager2' contact in the story\"\n            defaultMessage=\"Don Cooper\"\n            />,\n        title: <FormattedMessage\n            id=\"contact_badManager2Title\"\n            description=\"Job title for the 'badManager2' contact in the story\"\n            defaultMessage=\"Principal Engineering Lead\"\n            />,\n    },\n    badManagerTeam: {\n        name: <FormattedMessage\n            id=\"contact_badManagerTeamName\"\n            description=\"Name for the 'badManagerTeam' contact in the story\"\n            defaultMessage=\"Don's Team\"\n            />,\n    },\n    goodManager: {\n        name: <FormattedMessage\n            id=\"contact_goodManagerName\"\n            description=\"Name for the 'goodManager' contact in the story\"\n            defaultMessage=\"Pat Miller\"\n            />,\n        title: <FormattedMessage\n            id=\"contact_goodManagerTitle\"\n            description=\"Job title for the 'goodManager' contact in the story\"\n            defaultMessage=\"Senior Engineering Lead\"\n            />,\n    },\n    goodManager2: {\n        name: <FormattedMessage\n            id=\"contact_goodManager2Name\"\n            description=\"Name for the 'goodManager2' contact in the story\"\n            defaultMessage=\"Pat Miller\"\n            />,\n    },\n    goodManagerTeam: {\n        name: <FormattedMessage\n            id=\"contact_goodManagerTeamName\"\n            description=\"Name for the 'goodManagerTeam' contact in the story\"\n            defaultMessage=\"Pat's Team\"\n            />,\n    },\n    skip: {\n        name: <FormattedMessage\n            id=\"contact_skipName\"\n            description=\"Name for the 'skip' contact in the story\"\n            defaultMessage=\"Rick Wagner\"\n            />,\n        title: <FormattedMessage\n            id=\"contact_skipTitle\"\n            description=\"Job title for the 'skip' contact in the story\"\n            defaultMessage=\"Partner Engineering Manager\"\n            />,\n    },\n    otherSkip: {\n        name: <FormattedMessage\n            id=\"contact_otherSkipName\"\n            description=\"Name for the 'otherSkip' contact in the story\"\n            defaultMessage=\"Jerin Kransky\"\n            />,\n        title: <FormattedMessage\n            id=\"contact_otherSkipTitle\"\n            description=\"Job title for the 'otherSkip' contact in the story\"\n            defaultMessage=\"Partner Engineering Manager\"\n            />,\n    },\n    hr: {\n        name: <FormattedMessage\n            id=\"contact_hrName\"\n            description=\"Name for the 'hr' contact in the story\"\n            defaultMessage=\"Mary Townsend\"\n            />,\n        title: <FormattedMessage\n            id=\"contact_hrTitle\"\n            description=\"Job title for the 'hr' contact in the story\"\n            defaultMessage=\"Human Resources\"\n            />,\n    },\n    flunky: {\n        name: <FormattedMessage\n            id=\"contact_flunkyName\"\n            description=\"Name for the 'flunky' contact in the story\"\n            defaultMessage=\"Ted Philips\"\n            />,\n        title: <FormattedMessage\n            id=\"contact_flunkyTitle\"\n            description=\"Job title for the 'flunky' contact in the story\"\n            defaultMessage=\"Trainee\"\n            />,\n    },\n    flunky1: {\n        name: <FormattedMessage\n            id=\"contact_flunky1Name\"\n            description=\"Name for the 'flunky1' contact in the story\"\n            defaultMessage=\"Ted Philips\"\n            />,\n        title: <FormattedMessage\n            id=\"contact_flunky1Title\"\n            description=\"Job title for the 'flunky1' contact in the story\"\n            defaultMessage=\"Engineer\"\n            />,\n    },\n    mentor: {\n        name: <FormattedMessage\n            id=\"contact_mentorName\"\n            description=\"Name for the 'mentor' contact in the story\"\n            defaultMessage=\"Feng Lee\"\n            />,\n        title: <FormattedMessage\n            id=\"contact_mentorTitle\"\n            description=\"Job title for the 'mentor' contact in the story\"\n            defaultMessage=\"Senior Engineer\"\n            />,\n    },\n    assistant: {\n        name: <FormattedMessage\n            id=\"contact_assistantName\"\n            description=\"Name for the 'assistant' contact in the story\"\n            defaultMessage=\"Jeffrey Young\"\n            />,\n        title: <FormattedMessage\n            id=\"contact_assistantTitle\"\n            description=\"Job title for the 'assistant' contact in the story\"\n            defaultMessage=\"Executive Assistant\"\n            />,\n    },\n    owner: {\n        name: <FormattedMessage\n            id=\"contact_ownerName\"\n            description=\"Name for the 'owner' contact in the story\"\n            defaultMessage=\"Ilano Moscato\"\n            />,\n        title: <FormattedMessage\n            id=\"contact_ownerTitle\"\n            description=\"Job title for the 'owner' contact in the story\"\n            defaultMessage=\"Benevolent Dictator for Life\"\n            />,\n    },\n}\n", "sic1/client/content/messages/en.json": "{\n  \"achievementDescriptionAVOISION\": {\n    \"defaultMessage\": \"Score at least 250 points in Avoision.\",\n    \"description\": \"Description of the AVOISION achievement\"\n  },\n  \"achievementDescriptionERASE\": {\n    \"defaultMessage\": \"Write a program that reads a single input and then deletes itself (sets all memory to zero), without producing output.\",\n    \"description\": \"Description of the ERASE achievement\"\n  },\n  \"achievementDescriptionJOB_TITLE_1\": {\n    \"defaultMessage\": \"Get promoted to Engineer.\",\n    \"description\": \"Description of the JOB_TITLE_1 achievement\"\n  },\n  \"achievementDescriptionJOB_TITLE_2\": {\n    \"defaultMessage\": \"Get promoted to Engineer II.\",\n    \"description\": \"Description of the JOB_TITLE_2 achievement\"\n  },\n  \"achievementDescriptionJOB_TITLE_3\": {\n    \"defaultMessage\": \"Get promoted to Senior Engineer.\",\n    \"description\": \"Description of the JOB_TITLE_3 achievement\"\n  },\n  \"achievementDescriptionJOB_TITLE_4\": {\n    \"defaultMessage\": \"Get promoted to Principal Engineer.\",\n    \"description\": \"Description of the JOB_TITLE_4 achievement\"\n  },\n  \"achievementDescriptionJOB_TITLE_5\": {\n    \"defaultMessage\": \"Get promoted to Partner Engineer.\",\n    \"description\": \"Description of the JOB_TITLE_5 achievement\"\n  },\n  \"achievementDescriptionJOB_TITLE_6\": {\n    \"defaultMessage\": \"Get promoted to Distinguished Engineer.\",\n    \"description\": \"Description of the JOB_TITLE_6 achievement\"\n  },\n  \"achievementDescriptionJOB_TITLE_7\": {\n    \"defaultMessage\": \"Get a new job title made just for you.\",\n    \"description\": \"Description of the JOB_TITLE_7 achievement\"\n  },\n  \"achievementDescriptionJOB_TITLE_8\": {\n    \"defaultMessage\": \"Obtain the final promotion.\",\n    \"description\": \"Description of the JOB_TITLE_8 achievement\"\n  },\n  \"achievementDescriptionNEW_END\": {\n    \"defaultMessage\": \"Share a true self-hosting program with an old friend.\",\n    \"description\": \"Description of the NEW_END achievement\"\n  },\n  \"achievementDescriptionOMIT_SUBLEQ\": {\n    \"defaultMessage\": \"Solve \\\"Addition\\\" without typing \\\"subleq\\\".\",\n    \"description\": \"Description of the OMIT_SUBLEQ achievement\"\n  },\n  \"achievementDescriptionTIME_EARLY\": {\n    \"defaultMessage\": \"Complete a task before 6am (06:00) local time.\",\n    \"description\": \"Description of the TIME_EARLY achievement\"\n  },\n  \"achievementDescriptionTIME_LATE\": {\n    \"defaultMessage\": \"Complete a task after 9pm (21:00) local time.\",\n    \"description\": \"Description of the TIME_LATE achievement\"\n  },\n  \"achievementNameAVOISION\": {\n    \"defaultMessage\": \"Master Avoider\",\n    \"description\": \"Display name for the AVOISION achievement\"\n  },\n  \"achievementNameERASE\": {\n    \"defaultMessage\": \"Self-Destruct\",\n    \"description\": \"Display name for the ERASE achievement\"\n  },\n  \"achievementNameJOB_TITLE_1\": {\n    \"defaultMessage\": \"Engineer\",\n    \"description\": \"Display name for the JOB_TITLE_1 achievement\"\n  },\n  \"achievementNameJOB_TITLE_2\": {\n    \"defaultMessage\": \"Engineer II\",\n    \"description\": \"Display name for the JOB_TITLE_2 achievement\"\n  },\n  \"achievementNameJOB_TITLE_3\": {\n    \"defaultMessage\": \"Senior Engineer\",\n    \"description\": \"Display name for the JOB_TITLE_3 achievement\"\n  },\n  \"achievementNameJOB_TITLE_4\": {\n    \"defaultMessage\": \"Principal Engineer\",\n    \"description\": \"Display name for the JOB_TITLE_4 achievement\"\n  },\n  \"achievementNameJOB_TITLE_5\": {\n    \"defaultMessage\": \"Partner Engineer\",\n    \"description\": \"Display name for the JOB_TITLE_5 achievement\"\n  },\n  \"achievementNameJOB_TITLE_6\": {\n    \"defaultMessage\": \"Distinguished Engineer\",\n    \"description\": \"Display name for the JOB_TITLE_6 achievement\"\n  },\n  \"achievementNameJOB_TITLE_7\": {\n    \"defaultMessage\": \"Special Promotion\",\n    \"description\": \"Display name for the JOB_TITLE_7 achievement\"\n  },\n  \"achievementNameJOB_TITLE_8\": {\n    \"defaultMessage\": \"Terminal Promotion\",\n    \"description\": \"Display name for the JOB_TITLE_8 achievement\"\n  },\n  \"achievementNameNEW_END\": {\n    \"defaultMessage\": \"To Be Continued\",\n    \"description\": \"Display name for the NEW_END achievement\"\n  },\n  \"achievementNameOMIT_SUBLEQ\": {\n    \"defaultMessage\": \"Zero Instruction Computer\",\n    \"description\": \"Display name for the OMIT_SUBLEQ achievement\"\n  },\n  \"achievementNameTIME_EARLY\": {\n    \"defaultMessage\": \"Up and at 'Em\",\n    \"description\": \"Display name for the TIME_EARLY achievement\"\n  },\n  \"achievementNameTIME_LATE\": {\n    \"defaultMessage\": \"Workin' Hard\",\n    \"description\": \"Display name for the TIME_LATE achievement\"\n  },\n  \"achievementPopUpTitle\": {\n    \"defaultMessage\": \"Achievement Unlocked\",\n    \"description\": \"Title of the 'achievement unlocked' pop-up message\"\n  },\n  \"achievementProgressDetail\": {\n    \"defaultMessage\": \"{achievedCount} of {achievementCount} ({percent})\",\n    \"description\": \"Achievement progress expressed numerically\"\n  },\n  \"achievementProgressLine\": {\n    \"defaultMessage\": \"Achievement Progress: {summary}\",\n    \"description\": \"Line of text summarizing achievement progress\"\n  },\n  \"avoisionDefaultScore1\": {\n    \"defaultMessage\": \"Jerin\",\n    \"description\": \"Name of the top scorer for the default scores in Avoision\"\n  },\n  \"avoisionDefaultScore2\": {\n    \"defaultMessage\": \"Pat\",\n    \"description\": \"Name of the second-to-top scorer for the default scores in Avoision\"\n  },\n  \"avoisionDefaultScore3\": {\n    \"defaultMessage\": \"Ted\",\n    \"description\": \"Name of the third-to-top scorer for the default scores in Avoision\"\n  },\n  \"avoisionGameOver\": {\n    \"defaultMessage\": \"Game Over\",\n    \"description\": \"Message shown when a round of Avoision ends without a new high score\"\n  },\n  \"avoisionNewHigh\": {\n    \"defaultMessage\": \"New High Score!\",\n    \"description\": \"Message shown when a new high score is achieved in Avoision\"\n  },\n  \"avoisionPoints\": {\n    \"defaultMessage\": \"Points: {value}\",\n    \"description\": \"In-game display of points for Avoision\"\n  },\n  \"avoisionScore\": {\n    \"defaultMessage\": \"Score: {value}\",\n    \"description\": \"In-game display of score for Avoision\"\n  },\n  \"bootMessage\": {\n    \"defaultMessage\": \"\\n \\u2588\\u2588\\u2588\\u2588  \\u2588\\u2588\\u2588\\u2588\\u2588   \\u2588\\u2588\\u2588\\u2588\\n\\u2588\\u2588       \\u2588    \\u2588\\u2588\\n \\u2588\\u2588\\u2588     \\u2588    \\u2588      SYSTEMS (TM)\\n   \\u2588\\u2588    \\u2588    \\u2588\\u2588\\n\\u2588\\u2588\\u2588\\u2588   \\u2588\\u2588\\u2588\\u2588\\u2588   \\u2588\\u2588\\u2588\\u2588\\n\\n     \\\"Synergy, simply.\\\"\\n\\n(C) 1980 SIC Systems, Inc.\\n\\nSIC-1 emulator - 50 Hz          ... OK\\nChecking SIC-1 memory      ###/256B OK\\nSimulating SIC-1 8-bit I/O port ... OK\\n\\nLoading SIC-1 Development Environment v120279...\\n\\nStarting hi-res, tri-color graphical session... \",\n    \"description\": \"Text of the boot screen, shown when launching the game; notes: use spaces for alignment, the '\\u2588' character is used for an ASCII art logo, and '...' and '###/256B ' have special meaning and should be preserved\"\n  },\n  \"buttonAchievementsMenu\": {\n    \"defaultMessage\": \"Achievements\",\n    \"description\": \"Text shown on the button to open the achievements message box\"\n  },\n  \"buttonAvoisionPage\": {\n    \"defaultMessage\": \"Avoision\",\n    \"description\": \"Text on the button that opens the task viewer to the Avoision page\"\n  },\n  \"buttonCancel\": {\n    \"defaultMessage\": \"Cancel\",\n    \"description\": \"Text shown on various 'cancel' buttons when discarding changes to settings\"\n  },\n  \"buttonCommentBlock\": {\n    \"defaultMessage\": \"Comment Block\",\n    \"description\": \"Text on the 'comment block' button, which comments out the selected lines of program text\"\n  },\n  \"buttonCompile\": {\n    \"defaultMessage\": \"Compile\",\n    \"description\": \"Text on the 'compile' button, for compiling a program and loading it into the debugger\"\n  },\n  \"buttonConfigureInput\": {\n    \"defaultMessage\": \"Configure Input\",\n    \"description\": \"Text on the 'configure input' button, which supports editing input for Sandbox Mode\"\n  },\n  \"buttonCopyToClipboard\": {\n    \"defaultMessage\": \"Copy to Clipboard\",\n    \"description\": \"Text shown on the 'copy text to clipboard' button (only used on the web version)\"\n  },\n  \"buttonCredits\": {\n    \"defaultMessage\": \"Credits\",\n    \"description\": \"Text shown on the button to open the credits message box\"\n  },\n  \"buttonDisableAutoIndent\": {\n    \"defaultMessage\": \"Disable Auto-Indent Mode\",\n    \"description\": \"Text on the 'disable auto-indent mode' button, which toggles automatic insertion of indentation when adding a new line to the program text\"\n  },\n  \"buttonDisableTabInsertMode\": {\n    \"defaultMessage\": \"Disable Tab Insert Mode\",\n    \"description\": \"Text on the 'disable tab insert mode' button, which toggles the ability for the tab key to insert a tab character instead of the browser-default behavior of advancing keyboard focus to the next element\"\n  },\n  \"buttonEnableAutoIndent\": {\n    \"defaultMessage\": \"Enable Auto-Indent Mode\",\n    \"description\": \"Text on the 'enable auto-indent mode' button, which toggles automatic insertion of indentation when adding a new line to the program text\"\n  },\n  \"buttonEnableTabInsertMode\": {\n    \"defaultMessage\": \"Enable Tab Insert Mode\",\n    \"description\": \"Text on the 'enable tab insert mode' button, which toggles the ability for the tab key to insert a tab character instead of the browser-default behavior of advancing keyboard focus to the next element\"\n  },\n  \"buttonExit\": {\n    \"defaultMessage\": \"Exit SIC-1\",\n    \"description\": \"Text on the button that exits the game (only used on the app version)\"\n  },\n  \"buttonHelp\": {\n    \"defaultMessage\": \"Help\",\n    \"description\": \"Text on the 'help' button, which displays the help menu, providing hints and a link to the manual\"\n  },\n  \"buttonHelpMenu\": {\n    \"defaultMessage\": \"Help\",\n    \"description\": \"Text on the button that opens the 'help' menu'\"\n  },\n  \"buttonHint\": {\n    \"defaultMessage\": \"Show Hint\",\n    \"description\": \"Text on the button to show a hint for the current task\"\n  },\n  \"buttonIndentBlock\": {\n    \"defaultMessage\": \"Indent Block\",\n    \"description\": \"Tooltip for the 'indent block' button, which prepends one level of indentation to the selected lines of program text\"\n  },\n  \"buttonLicenses\": {\n    \"defaultMessage\": \"click here\",\n    \"description\": \"Text on the link to third party licenses\"\n  },\n  \"buttonManualAssembly\": {\n    \"defaultMessage\": \"Open SIC-1 Assembly Manual\",\n    \"description\": \"Text on the button to open the SIC-1 Assembly manual\"\n  },\n  \"buttonManualDevEnv\": {\n    \"defaultMessage\": \"Open Dev. Environment Manual\",\n    \"description\": \"Text on the button to open the SIC-1 Development Environment manual\"\n  },\n  \"buttonManualNewWindow\": {\n    \"defaultMessage\": \"Open Assembly Manual Here\",\n    \"description\": \"Text on the button to open the combined manual in a new window\"\n  },\n  \"buttonMenu\": {\n    \"defaultMessage\": \"Menu\",\n    \"description\": \"Text on the 'menu' button, which opens the main menu\"\n  },\n  \"buttonMenuMailViewer\": {\n    \"defaultMessage\": \"Electronic Mail\",\n    \"description\": \"Text on the button to open the mail viewer (using an antiquated term, if possible)\"\n  },\n  \"buttonMenuTaskViewer\": {\n    \"defaultMessage\": \"Program Inventory\",\n    \"description\": \"Text on the button to open the task viewer/program inventory\"\n  },\n  \"buttonOptionsMenu\": {\n    \"defaultMessage\": \"Options\",\n    \"description\": \"Text on the button that opens the options menu'\"\n  },\n  \"buttonPause\": {\n    \"defaultMessage\": \"Pause\",\n    \"description\": \"Text on 'pause' button that pauses a running program\"\n  },\n  \"buttonPresentationSettings\": {\n    \"defaultMessage\": \"Presentation Settings\",\n    \"description\": \"Text on the button to open the 'presentation settings' menu, for editing full-screen, sound, etc.\"\n  },\n  \"buttonSandboxMenu\": {\n    \"defaultMessage\": \"Sandbox Mode\",\n    \"description\": \"Text on the button that opens the task viewer to the Sandbox Mode page\"\n  },\n  \"buttonSaveChanges\": {\n    \"defaultMessage\": \"Save Changes\",\n    \"description\": \"Text shown on multiple 'save changes' buttons when editing settings\"\n  },\n  \"buttonSaveClear\": {\n    \"defaultMessage\": \"Clear Data\",\n    \"description\": \"Text shown on the initial 'clear save data' button (only used on the web version)\"\n  },\n  \"buttonSaveClearCancel\": {\n    \"defaultMessage\": \"No, Keep My Save Data\",\n    \"description\": \"Text shown on the 'delete save data' cancellation button (only used on the web version)\"\n  },\n  \"buttonSaveClearConfirm\": {\n    \"defaultMessage\": \"Yes, Delete My Save Data\",\n    \"description\": \"Text shown on the 'delete save data' confirmation button (only used on the web version)\"\n  },\n  \"buttonSaveClearMenu\": {\n    \"defaultMessage\": \"Clear Save Data\",\n    \"description\": \"Text shown on the button to open the 'clear save data' message box (only used on the web version)\"\n  },\n  \"buttonSaveDataImport\": {\n    \"defaultMessage\": \"Import Save Data\",\n    \"description\": \"Text shown on the 'import save data' button\"\n  },\n  \"buttonSaveExportMenu\": {\n    \"defaultMessage\": \"Export Save Data\",\n    \"description\": \"Text on the button to open the 'export save data' message box (only used on the web version)\"\n  },\n  \"buttonSaveImportMenu\": {\n    \"defaultMessage\": \"Import Save Data\",\n    \"description\": \"Text on the button to open the 'import save data' message box (only used on the web version)\"\n  },\n  \"buttonSaveMenu\": {\n    \"defaultMessage\": \"Manage Save Data\",\n    \"description\": \"Text on the button to open the save data management menu (only used on the web version)\"\n  },\n  \"buttonSaveOverwriteConfirm\": {\n    \"defaultMessage\": \"Yes, Overwrite My Save Data\",\n    \"description\": \"Text shown on the 'yes, overwrite save data' confirmation button when importing save data (only used on the web version)\"\n  },\n  \"buttonStep\": {\n    \"defaultMessage\": \"Step\",\n    \"description\": \"Text on the 'step' button, for advancing the debugger one instruction\"\n  },\n  \"buttonStepRate4x\": {\n    \"defaultMessage\": \"Turbo (4x)\",\n    \"description\": \"Text on the 'run' button for increasing to 4x speed\"\n  },\n  \"buttonStepRate50x\": {\n    \"defaultMessage\": \"Turbo (50x)\",\n    \"description\": \"Text on the 'run' button for increasing to 50x speed\"\n  },\n  \"buttonStepRateDefault\": {\n    \"defaultMessage\": \"Run\",\n    \"description\": \"Text on the 'run' button when going to the default step rate (speed)\"\n  },\n  \"buttonStop\": {\n    \"defaultMessage\": \"Stop\",\n    \"description\": \"Text on the 'stop' button that stops a running program\"\n  },\n  \"buttonUncommentBlock\": {\n    \"defaultMessage\": \"Uncomment Block\",\n    \"description\": \"Text on the 'uncomment block' button, which comments the selected lines of program text\"\n  },\n  \"buttonUnindentBlock\": {\n    \"defaultMessage\": \"Unindent Block\",\n    \"description\": \"Text on the 'unindent block' button, which removes one level of indentation from the selected lines of program text\"\n  },\n  \"buttonUserSettingsMenu\": {\n    \"defaultMessage\": \"User Settings\",\n    \"description\": \"Text shown on the button to open the 'user settings' menu (only used on the web version)\"\n  },\n  \"chartFriendAvoision\": {\n    \"defaultMessage\": \"Avoision High Scores\",\n    \"description\": \"Title of friend leaderboard chart for Avoision high scores\"\n  },\n  \"chartFriendBytes\": {\n    \"defaultMessage\": \"Bytes Read (Friends)\",\n    \"description\": \"Title of friend leaderboard for 'bytes read'\"\n  },\n  \"chartFriendCycles\": {\n    \"defaultMessage\": \"Cycles Executed (Friends)\",\n    \"description\": \"Title of friend leaderboard for 'cycles executed'\"\n  },\n  \"chartFriendTasks\": {\n    \"defaultMessage\": \"Completed Tasks (Friends)\",\n    \"description\": \"Title of friend leaderboard chart for 'tasks completed'\"\n  },\n  \"chartTitleBytes\": {\n    \"defaultMessage\": \"Bytes Read: {bytes}\",\n    \"description\": \"Title for a 'bytes read' chart\"\n  },\n  \"chartTitleCycles\": {\n    \"defaultMessage\": \"Cycles Executed: {cycles}\",\n    \"description\": \"Title for a 'cycles executed' chart\"\n  },\n  \"chartTitleTasks\": {\n    \"defaultMessage\": \"Completed Tasks\",\n    \"description\": \"Title for the 'tasks completed' chart\"\n  },\n  \"checkboxFullscreen\": {\n    \"defaultMessage\": \"Full screen:\",\n    \"description\": \"Label for the 'full screen' checkbox toggle\"\n  },\n  \"checkboxMusicAfter\": {\n    \"defaultMessage\": \"Enable music\",\n    \"description\": \"Label for the music checkbox, when appearing after the checkbox\"\n  },\n  \"checkboxMusicBefore\": {\n    \"defaultMessage\": \"Music\",\n    \"description\": \"Label for music checkbox, when appearing before the checkbox\"\n  },\n  \"checkboxShareName\": {\n    \"defaultMessage\": \"Show my name in public leaderboards (if unchecked, your statistics will be shown without a name)\",\n    \"description\": \"Explanatory text for checkbox that opts into showing the player's name in public leaderboards\"\n  },\n  \"checkboxSoundEffectsAfter\": {\n    \"defaultMessage\": \"Enable sound effects\",\n    \"description\": \"Label for the sound effects checkbox, when appearing after the checkbox\"\n  },\n  \"checkboxSoundEffectsBefore\": {\n    \"defaultMessage\": \"Sound effects\",\n    \"description\": \"Label for sound effects checkbox, when appearing before the checkbox\"\n  },\n  \"colorSchemeAmber Phosphor\": {\n    \"defaultMessage\": \"Amber Phosphor\",\n    \"description\": \"Display name for the 'Amber Phosphor' color scheme\"\n  },\n  \"colorSchemeBlack on White\": {\n    \"defaultMessage\": \"Black on White\",\n    \"description\": \"Display name for the 'Black on White' color scheme\"\n  },\n  \"colorSchemeDefault\": {\n    \"defaultMessage\": \"Default\",\n    \"description\": \"Display name for the 'Default' color scheme\"\n  },\n  \"colorSchemeGreen Phosphor\": {\n    \"defaultMessage\": \"Green Phosphor\",\n    \"description\": \"Display name for the 'Green Phosphor' color scheme\"\n  },\n  \"colorSchemeWhite on Black\": {\n    \"defaultMessage\": \"White on Black\",\n    \"description\": \"Display name for the 'White on Black' color scheme\"\n  },\n  \"compilationErrorAddressRangeError\": {\n    \"defaultMessage\": \"Invalid address argument: \\\"{argument}\\\" (must be an integer on the range [{rangeMin}, {rangeMax}])!\",\n    \"description\": \"Error message shown when the 'address range error' compilation error is encountered, indicating an address literal isn't within the valid range\"\n  },\n  \"compilationErrorInternal\": {\n    \"defaultMessage\": \"Internal compiler error!\",\n    \"description\": \"Error message shown when there was an unknown internal compiler error, indicating a bug in the compiler--this should never happen\"\n  },\n  \"compilationErrorInvalidAddressExpressionError\": {\n    \"defaultMessage\": \"Expected number literal or reference, but got: \\\"{token}\\\"!\",\n    \"description\": \"Error message shown when the 'InvalidAddressExpressionError' compilation error is encountered, indicating an unexpected token was encountered where an address was expected\"\n  },\n  \"compilationErrorInvalidBreakpointError\": {\n    \"defaultMessage\": \"Breakpoints are only supported on subleq instructions!\",\n    \"description\": \"Error message shown when the 'InvalidBreakpointError' compilation error is encountered, indicating a breakpoint was set somewhere other than a 'subleq' instruction\"\n  },\n  \"compilationErrorInvalidCommandError\": {\n    \"defaultMessage\": \"Unknown command: \\\"{command}\\\" (valid commands are: \\\"subleq\\\" and \\\".data\\\")!\",\n    \"description\": \"Error message shown when the 'InvalidCommandError' compilation error is encountered, indicating a command other than 'subleq' and '.data' was encountered\"\n  },\n  \"compilationErrorInvalidDataArgumentCountError\": {\n    \"defaultMessage\": \"Invalid number of arguments for \\\".data\\\": {count} (must have at least 1 argument)!\",\n    \"description\": \"Error message shown when the 'InvalidDataArgumentCountError' compilation error is encountered, indicating no arguments were supplied for a '.data' directive\"\n  },\n  \"compilationErrorInvalidEscapeCodeError\": {\n    \"defaultMessage\": \"Invalid escape code: \\\"{character}\\\"!\",\n    \"description\": \"Error message shown when the 'InvalidEscapeCodeError' compilation error is encountered, indicating a character escape code was not valid, likely indicating an errant backslash\"\n  },\n  \"compilationErrorInvalidSubleqArgumentCountError\": {\n    \"defaultMessage\": \"Invalid number of arguments for \\\"subleq\\\": {count} (must be between {rangeMin} and {rangeMax}, inclusive)!\",\n    \"description\": \"Error message shown when the 'InvalidSubleqArgumentCountError' compilation error is encountered, indicating a 'subleq' instruction didn't have 2 or 3 addresses specified for it\"\n  },\n  \"compilationErrorInvalidTokenError\": {\n    \"defaultMessage\": \"Invalid token: \\\"{token}\\\"!\",\n    \"description\": \"Error message shown when the 'InvalidTokenError' compilation error is encountered, indicating an unrecognized token was encountered when parsing\"\n  },\n  \"compilationErrorInvalidValueExpressionError\": {\n    \"defaultMessage\": \"Expected number, character, string, or reference, but got: \\\"{token}\\\"!\",\n    \"description\": \"Error message shown when the 'InvalidValueExpressionError' compilation error is encountered, indicating an unrecognized value expression was encountered\"\n  },\n  \"compilationErrorLabelAlreadyDefinedError\": {\n    \"defaultMessage\": \"Label already defined: \\\"{label}\\\"!\",\n    \"description\": \"Error message shown when the 'LabelAlreadyDefinedError' compilation error is encountered, indicating a label was defined more than once\"\n  },\n  \"compilationErrorMissingCommaOrWhitespaceError\": {\n    \"defaultMessage\": \"Whitespace or comma required before argument: \\\"{argument}\\\"\",\n    \"description\": \"Error message shown when the 'MissingCommaOrWhitespaceError' compilation error is encountered, indicating there wasn't whitespace or a comma between arguments\"\n  },\n  \"compilationErrorMissingWhitespaceError\": {\n    \"defaultMessage\": \"Whitespace is required after \\\"{command}\\\"!\",\n    \"description\": \"Error message shown when the 'MissingWhitespaceError' compilation error is encountered, indicating there was no whitespace after a 'subleq' or '.data' command\"\n  },\n  \"compilationErrorProgramTooLargeError\": {\n    \"defaultMessage\": \"Program is too long (maximum size: {rangeMax} bytes; program size: {bytes} bytes)!\",\n    \"description\": \"Error message shown when the 'ProgramTooLargeError' compilation error is encountered, indicating the compiled program doesn't fit into 253 bytes\"\n  },\n  \"compilationErrorUndefinedReferenceError\": {\n    \"defaultMessage\": \"Undefined reference: \\\"{label}\\\"!\",\n    \"description\": \"Error message shown when the 'UndefinedReferenceError' compilation error is encountered, indicating a reference was made to an undeclared label\"\n  },\n  \"compilationErrorValueRangeError\": {\n    \"defaultMessage\": \"Invalid value argument: {value} (must be an integer on the range [{rangeMin}, {rangeMax}])!\",\n    \"description\": \"Error message shown when the 'ValueRangeError' compilation error is encountered, indicating a value didn't fit in a single signed byte\"\n  },\n  \"contactWithTitle\": {\n    \"defaultMessage\": \"{name} ({title})\",\n    \"description\": \"Display string for a contact when a job title should be shown along with the contact's name\"\n  },\n  \"contact_allName\": {\n    \"defaultMessage\": \"All Engineering\",\n    \"description\": \"Name for the 'all' contact in the story\"\n  },\n  \"contact_assistantName\": {\n    \"defaultMessage\": \"Jeffrey Young\",\n    \"description\": \"Name for the 'assistant' contact in the story\"\n  },\n  \"contact_assistantTitle\": {\n    \"defaultMessage\": \"Executive Assistant\",\n    \"description\": \"Job title for the 'assistant' contact in the story\"\n  },\n  \"contact_badManager2Name\": {\n    \"defaultMessage\": \"Don Cooper\",\n    \"description\": \"Name for the 'badManager2' contact in the story\"\n  },\n  \"contact_badManager2Title\": {\n    \"defaultMessage\": \"Principal Engineering Lead\",\n    \"description\": \"Job title for the 'badManager2' contact in the story\"\n  },\n  \"contact_badManagerName\": {\n    \"defaultMessage\": \"Don Cooper\",\n    \"description\": \"Name for the 'badManager' contact in the story\"\n  },\n  \"contact_badManagerTeamName\": {\n    \"defaultMessage\": \"Don's Team\",\n    \"description\": \"Name for the 'badManagerTeam' contact in the story\"\n  },\n  \"contact_badManagerTitle\": {\n    \"defaultMessage\": \"Senior Engineering Lead\",\n    \"description\": \"Job title for the 'badManager' contact in the story\"\n  },\n  \"contact_flunky1Name\": {\n    \"defaultMessage\": \"Ted Philips\",\n    \"description\": \"Name for the 'flunky1' contact in the story\"\n  },\n  \"contact_flunky1Title\": {\n    \"defaultMessage\": \"Engineer\",\n    \"description\": \"Job title for the 'flunky1' contact in the story\"\n  },\n  \"contact_flunkyName\": {\n    \"defaultMessage\": \"Ted Philips\",\n    \"description\": \"Name for the 'flunky' contact in the story\"\n  },\n  \"contact_flunkyTitle\": {\n    \"defaultMessage\": \"Trainee\",\n    \"description\": \"Job title for the 'flunky' contact in the story\"\n  },\n  \"contact_goodManager2Name\": {\n    \"defaultMessage\": \"Pat Miller\",\n    \"description\": \"Name for the 'goodManager2' contact in the story\"\n  },\n  \"contact_goodManagerName\": {\n    \"defaultMessage\": \"Pat Miller\",\n    \"description\": \"Name for the 'goodManager' contact in the story\"\n  },\n  \"contact_goodManagerTeamName\": {\n    \"defaultMessage\": \"Pat's Team\",\n    \"description\": \"Name for the 'goodManagerTeam' contact in the story\"\n  },\n  \"contact_goodManagerTitle\": {\n    \"defaultMessage\": \"Senior Engineering Lead\",\n    \"description\": \"Job title for the 'goodManager' contact in the story\"\n  },\n  \"contact_hrName\": {\n    \"defaultMessage\": \"Mary Townsend\",\n    \"description\": \"Name for the 'hr' contact in the story\"\n  },\n  \"contact_hrTitle\": {\n    \"defaultMessage\": \"Human Resources\",\n    \"description\": \"Job title for the 'hr' contact in the story\"\n  },\n  \"contact_mentorName\": {\n    \"defaultMessage\": \"Feng Lee\",\n    \"description\": \"Name for the 'mentor' contact in the story\"\n  },\n  \"contact_mentorTitle\": {\n    \"defaultMessage\": \"Senior Engineer\",\n    \"description\": \"Job title for the 'mentor' contact in the story\"\n  },\n  \"contact_onboardingName\": {\n    \"defaultMessage\": \"SIC Systems Onboarding\",\n    \"description\": \"Name for the 'onboarding' contact in the story\"\n  },\n  \"contact_otherSkipName\": {\n    \"defaultMessage\": \"Jerin Kransky\",\n    \"description\": \"Name for the 'otherSkip' contact in the story\"\n  },\n  \"contact_otherSkipTitle\": {\n    \"defaultMessage\": \"Partner Engineering Manager\",\n    \"description\": \"Job title for the 'otherSkip' contact in the story\"\n  },\n  \"contact_ownerName\": {\n    \"defaultMessage\": \"Ilano Moscato\",\n    \"description\": \"Name for the 'owner' contact in the story\"\n  },\n  \"contact_ownerTitle\": {\n    \"defaultMessage\": \"Benevolent Dictator for Life\",\n    \"description\": \"Job title for the 'owner' contact in the story\"\n  },\n  \"contact_skipName\": {\n    \"defaultMessage\": \"Rick Wagner\",\n    \"description\": \"Name for the 'skip' contact in the story\"\n  },\n  \"contact_skipTitle\": {\n    \"defaultMessage\": \"Partner Engineering Manager\",\n    \"description\": \"Job title for the 'skip' contact in the story\"\n  },\n  \"contact_taskManagementName\": {\n    \"defaultMessage\": \"Automated Task Management\",\n    \"description\": \"Name for the 'taskManagement' contact in the story\"\n  },\n  \"contentEditProfile\": {\n    \"defaultMessage\": \"<p>Update your user profile as needed:</p>{form}<p>Note: if you would like to have all of your leaderboard data deleted, send an email to {email} with \\\"{userId}\\\" (your randomly-generated user id) in the subject.</p>\",\n    \"description\": \"Markup shown when editing the user profile (only used on the web version)\"\n  },\n  \"contentHalt\": {\n    \"defaultMessage\": \"<h3>Program Halted</h3><p>The program halted itself by branching to \\\"@HALT\\\" (address 255).</p>\",\n    \"description\": \"Markup that is shown when a program halts\"\n  },\n  \"contentInputEditor\": {\n    \"defaultMessage\": \"<h3>Instructions</h3><p>For input, use the same syntax as in a <code>.data</code> directive (examples: <code>-7</code>, <code>''A''</code>, <code>-\\\"Negated string\\\"</code>).</p>\",\n    \"description\": \"Markup shown at the beginning of the 'input editor' of Sandbox Mode\"\n  },\n  \"contentNoProgram\": {\n    \"defaultMessage\": \"<h3>No Program Loaded!</h3><p>Please compile and load a program.</p>\",\n    \"description\": \"Markup that is shown when attempting to run an empty program\"\n  },\n  \"contentSaveClearConfirm\": {\n    \"defaultMessage\": \"<h3>WARNING</h3><p>This will delete ALL of your save data! All of your solutions, your user name, and achievements will be lost!</p><p>Are you sure you want to delete all of your data?</p>\",\n    \"description\": \"Markup shown in the 'clear save data' confirmation message box (only used on the web version)\"\n  },\n  \"contentSaveOverwrite\": {\n    \"defaultMessage\": \"<h3>WARNING</h3><p>This will overwrite ALL of your current save data with the imported save data!</p><p>Are you sure you want to overwrite any existing save data?</p>\",\n    \"description\": \"Markup shown as a warning when overwriting save data during an import (only used on web version)\"\n  },\n  \"defaultName\": {\n    \"defaultMessage\": \"Bill\",\n    \"description\": \"Default user name (only used in web version)\"\n  },\n  \"errorInputParsing\": {\n    \"defaultMessage\": \"Unexpected token: \\\"{token}\\\"!\",\n    \"description\": \"Error text shown in Sandbox Mode when there's a parsing error for custom input\"\n  },\n  \"errorNameExists\": {\n    \"defaultMessage\": \"A solution named \\\"{name}\\\" already exists.\",\n    \"description\": \"Error message for 'name already exists' error\"\n  },\n  \"errorNameInvalid\": {\n    \"defaultMessage\": \"Solution names must be at most {maxLength} characters long, and only a single line.\",\n    \"description\": \"Error message for 'invalid name' error\"\n  },\n  \"headerCompilationError\": {\n    \"defaultMessage\": \"Compilation Error\",\n    \"description\": \"Heading for 'compilation error' message box\"\n  },\n  \"headerIOOutput\": {\n    \"defaultMessage\": \"Out\",\n    \"description\": \"Column heading for the IO table, for output, when no expected output is prescribed, i.e. in Sandbox Mode (note: this string should be as short as possible)\"\n  },\n  \"headerInputActual\": {\n    \"defaultMessage\": \"Actual\",\n    \"description\": \"Column heading for the IO table, for actual output (note: this string should be as short as possible)\"\n  },\n  \"headerInputExpected\": {\n    \"defaultMessage\": \"Expected\",\n    \"description\": \"Column heading for the IO table, for expected output (note: this string should be as short as possible)\"\n  },\n  \"headerInputIn\": {\n    \"defaultMessage\": \"In\",\n    \"description\": \"Column heading for the IO table, for input (note: this string should be as short as possible)\"\n  },\n  \"headerStateMemory\": {\n    \"defaultMessage\": \"Memory\",\n    \"description\": \"Header for the 'memory' table, which shows the hexadecimal values of all 256 bytes of the emulator's memory\"\n  },\n  \"headerTestSet\": {\n    \"defaultMessage\": \"Test {number}\",\n    \"description\": \"Header for the IO table, indicating which test set is running\"\n  },\n  \"headerVariableLabel\": {\n    \"defaultMessage\": \"Label (Address)\",\n    \"description\": \"Header for the 'label' column of the variable/watch table, showing name/label and memory address of variables while debugging\"\n  },\n  \"headerVariableValue\": {\n    \"defaultMessage\": \"Value\",\n    \"description\": \"Header for the 'value' column of the variable/watch table, showing the value of variables while debugging\"\n  },\n  \"headingEditing\": {\n    \"defaultMessage\": \"Editing Tools\",\n    \"description\": \"Heading for the 'editing tools' panel, which contains buttons for modifying program text\"\n  },\n  \"headingInputEditor\": {\n    \"defaultMessage\": \"Input values\",\n    \"description\": \"Heading for the 'input values' section of Sandbox Mode's input editor\"\n  },\n  \"headingInputFormats\": {\n    \"defaultMessage\": \"Display formats\",\n    \"description\": \"Heading for the 'display formats' section of Sandbox Mode's editor\"\n  },\n  \"headingProgress\": {\n    \"defaultMessage\": \"Employee Statistics\",\n    \"description\": \"Heading for 'task progress' and 'achievements' group in the program inventory/task selector window\"\n  },\n  \"intro\": {\n    \"defaultMessage\": \"<h3>Job Description:</h3>\\r\\n<p>SIC Systems is looking for experienced programmers to join our team!</p>\\r\\n<p>As an engineer at SIC Systems, you'll produce highly efficient programs for our flagship product: the Single Instruction Computer Mark 1 (SIC-1). You will be competing against other engineers to produce the fastest and smallest programs.</p>\\r\\n<p>This is a full-time salaried role. The ideal candidate for this job will have a PhD and 15 - 20 years (or more) of industry experience, along with a relentless attention to detail and exemplary interpersonal skills. Scheduling flexibility is a plus, as we push toward our worldwide launch.</p>\\r\\n<h3>About SIC Systems:</h3>\\r\\n<p>SIC Systems is the world leader in single-instruction computing. Our mission is to simplify computation, and thus simplify the world. We are innovative, trustworthy, and ethical.</p>\",\n    \"description\": \"HTML content shown in the introductory message box ('job application')\"\n  },\n  \"introApplyButton\": {\n    \"defaultMessage\": \"Apply for the Job\",\n    \"description\": \"Button text for the 'apply' button in the introductory form\"\n  },\n  \"introApplyInvitation\": {\n    \"defaultMessage\": \"After completing the form above, click the button below to submit your job application:\",\n    \"description\": \"Invitation to click the 'apply' button in the introductory form\"\n  },\n  \"introApplyLabel\": {\n    \"defaultMessage\": \"Click the button below to submit your job application:\",\n    \"description\": \"Label for the 'apply for the job' button on the introductory form\"\n  },\n  \"introHeaderJobApplication\": {\n    \"defaultMessage\": \"Job Application:\",\n    \"description\": \"Header text for the 'job application' form\"\n  },\n  \"introLabelName\": {\n    \"defaultMessage\": \"Name:\",\n    \"description\": \"Label for user name on the introductory form\"\n  },\n  \"ioTypeCharacters\": {\n    \"defaultMessage\": \"Characters\",\n    \"description\": \"Label for the 'character' type, for task input/output in Sandbox Mode\"\n  },\n  \"ioTypeNumbers\": {\n    \"defaultMessage\": \"Numbers\",\n    \"description\": \"Label for the 'number' type, for task input/output in Sandbox Mode\"\n  },\n  \"ioTypeStrings\": {\n    \"defaultMessage\": \"Strings\",\n    \"description\": \"Label for the 'string' type, for task input/output in Sandbox Mode\"\n  },\n  \"jobTitle0\": {\n    \"defaultMessage\": \"Trainee\",\n    \"description\": \"Starting job title (during training/tutorial)\"\n  },\n  \"jobTitle1\": {\n    \"defaultMessage\": \"Engineer\",\n    \"description\": \"Initial engineering job title (after completing training/tutorial)\"\n  },\n  \"jobTitle2\": {\n    \"defaultMessage\": \"Engineer II\",\n    \"description\": \"Second engineering job title\"\n  },\n  \"jobTitle3\": {\n    \"defaultMessage\": \"Senior Engineer\",\n    \"description\": \"Third engineering job title\"\n  },\n  \"jobTitle4\": {\n    \"defaultMessage\": \"Principal Engineer\",\n    \"description\": \"Fourth engineering job title\"\n  },\n  \"jobTitle5\": {\n    \"defaultMessage\": \"Partner Engineer\",\n    \"description\": \"Fifth engineering job title\"\n  },\n  \"jobTitle6\": {\n    \"defaultMessage\": \"Distinguished Engineer\",\n    \"description\": \"Sixth engineering job title (noting distinguished accomplishments)\"\n  },\n  \"jobTitle7\": {\n    \"defaultMessage\": \"Technical Fellow\",\n    \"description\": \"Top engineering job title\"\n  },\n  \"jobTitle8\": {\n    \"defaultMessage\": \"Technical Fellow Emeritus\",\n    \"description\": \"Final job title (implying the person left the company after achieving the pinnacle of success)\"\n  },\n  \"labelStateBytes\": {\n    \"defaultMessage\": \"Bytes\",\n    \"description\": \"Label in the 'state' table for byte count (note: this string should be as short as possible)\"\n  },\n  \"labelStateCycles\": {\n    \"defaultMessage\": \"Cycles\",\n    \"description\": \"Label in the 'state' table for cycle count (note: this string should be as short as possible)\"\n  },\n  \"labelStateRunning\": {\n    \"defaultMessage\": \"State\",\n    \"description\": \"Label in the 'state' table for running vs. stopped (note: this string should be as short as possible)\"\n  },\n  \"labelWatchedAddress\": {\n    \"defaultMessage\": \"Address {address}\",\n    \"description\": \"Text shown in the 'variables' table for a manually watched address, i.e. an address the user manually highlighted\"\n  },\n  \"languageDefault\": {\n    \"defaultMessage\": \"Default ({defaultLanguage})\",\n    \"description\": \"Text shown in the language selector for the default language\"\n  },\n  \"languageName\": {\n    \"defaultMessage\": \"English\",\n    \"description\": \"The name of the language being translated, in that language (using Title Case where appropriate), used for the language selection dropdown--but note that a full rebuild of the game is required for this string (only) to take effect\"\n  },\n  \"languageOption\": {\n    \"defaultMessage\": \"{name} ({locale})\",\n    \"description\": \"Text shown in the language selector for each language, using its native name (e.g. 'English') and locale string (e.g. 'en')\"\n  },\n  \"loadFailed\": {\n    \"defaultMessage\": \"(load failed)\",\n    \"description\": \"Text to show when an asynchronous load of a UI component failed\"\n  },\n  \"loading\": {\n    \"defaultMessage\": \"(loading...)\",\n    \"description\": \"Text to show while a portion of the UI is loading\"\n  },\n  \"mailViewerButtonContinueEditing\": {\n    \"defaultMessage\": \"Continue Editing Current Program\",\n    \"description\": \"Button text for the 'continue editing' button in the mail viewer\"\n  },\n  \"mailViewerButtonCredits\": {\n    \"defaultMessage\": \"View Credits\",\n    \"description\": \"Button text for the 'view credits' button in the mail viewer\"\n  },\n  \"mailViewerButtonNextTask\": {\n    \"defaultMessage\": \"View Next Task\",\n    \"description\": \"Button text for the 'view next task' button in the mail viewer\"\n  },\n  \"mailViewerButtonOpenManual\": {\n    \"defaultMessage\": \"Open Manual In-Game\",\n    \"description\": \"Button text for the 'open manual in-game' button in the mail viewer\"\n  },\n  \"mailViewerButtonOpenManualNewWindow\": {\n    \"defaultMessage\": \"Open Manual Here\",\n    \"description\": \"Button text for the 'open manual in new window' button in the mail viewer\"\n  },\n  \"mailViewerButtonSandbox\": {\n    \"defaultMessage\": \"View Sandbox Mode\",\n    \"description\": \"Button text for the 'view sandbox mode' button in the mail viewer\"\n  },\n  \"mailViewerButtonViewTask\": {\n    \"defaultMessage\": \"View {taskName}\",\n    \"description\": \"Button text for the 'view a specific task' button in the mail viewer\"\n  },\n  \"mailViewerExtraToLineIndent\": {\n    \"defaultMessage\": \"{nbsp}{nbsp}{nbsp}{nbsp}{nbsp} \",\n    \"description\": \"Optional indent using {nbsp} non-breaking spaces to line up with 'from' line\"\n  },\n  \"mailViewerGroupUnread\": {\n    \"defaultMessage\": \"Unread Mail\",\n    \"description\": \"Group heading for 'unread mail' in the mail viewer\"\n  },\n  \"mailViewerHeadingRead\": {\n    \"defaultMessage\": \"Read Mail\",\n    \"description\": \"Mail viewer heading for mail that has already been read\"\n  },\n  \"mailViewerHeadingUnread\": {\n    \"defaultMessage\": \"Inbox\",\n    \"description\": \"Mail viewer heading for unread mail\"\n  },\n  \"mailViewerMailHeading\": {\n    \"defaultMessage\": \"<cap>To</cap>:{nbsp}{nbsp} {to}{newline}<cap>From</cap>: {from}{newline}{newline}<cap>Subject</cap>: {subject}{newline}\",\n    \"description\": \"Heading content markup shown in the mail viewer for a particular mail (optionally use {nbsp} non-breaking spaces to line up 'to' and 'from' lines); use {newline} at the end of each line\"\n  },\n  \"mailViewerTaskCompleted\": {\n    \"defaultMessage\": \"Well done! Your program produced the correct output. Thanks for your contribution to SIC Systems!\",\n    \"description\": \"Markup shown for a 'task completed successfully' mail, indicating the program was correct\"\n  },\n  \"mailViewerTaskSubject\": {\n    \"defaultMessage\": \"RE: {taskName}\",\n    \"description\": \"Subject line for task completion mails\"\n  },\n  \"mailViewerViewNextUnread\": {\n    \"defaultMessage\": \"View Next Unread Mail\",\n    \"description\": \"Button text for the 'view next unread mail' button in the mail viewer\"\n  },\n  \"mails0_0Content\": {\n    \"defaultMessage\": \"<h3>Single Instruction Computer Mark 1 (SIC-1)</h3>\\n<p>The Single Instruction Computer Mark 1 (SIC-1) is an 8-bit computer with 256 bytes of memory. Programs for the SIC-1 are written in SIC-1 Assembly Language, as described below.</p>\\n<h3><code>subleq</code> instruction</h3>\\n<p>Each <code>subleq</code> instruction is 3 bytes, specified as follows:</p>\\n<pre><code>subleq A B [C]\\n</code></pre>\\n<p><code>A</code>, <code>B</code>, and <code>C</code> are memory addresses (0 - 255) or labels.</p>\\n<p><code>subleq</code> subtracts the value at address <code>B</code> from the value at address <code>A</code> and stores the result at address <code>A</code> (i.e. <code>mem[A]</code> is set to <code>mem[A] - mem[B]</code>).</p>\\n<p>If the result is \\u2264 0, execution branches to address <code>C</code>.</p>\\n<p>Note that if <code>C</code> is not specified, the address of the next instruction is automatically added by the assembler (in effect, this means that taking the branch is no different from advancing to the next instruction).</p>\\n<h3>Built-in addresses</h3>\\n<p>For convenience, addresses can be specified using labels. The following predefined labels are always available:</p>\\n<ul>\\n<li><code>@MAX</code> (252): Maximum user-modifiable address</li>\\n<li><code>@IN</code> (253): Reads a value from input (writes are ignored)</li>\\n<li><code>@OUT</code> (254): Writes a result to output (reads as zero)</li>\\n<li><code>@HALT</code> (255): Terminates the program when accessed (reads and write are ignored)</li>\\n</ul>\\n<h3><code>subleq</code> example</h3>\\n<p>Below is a very simple SIC-1 program that negates one input value and writes it out.</p>\\n<p>E.g. if the input value from <code>@IN</code> is 3, it subtracts 3 from <code>@OUT</code> (which reads as zero), and the result of 0 - 3 = -3 is written out.</p>\\n<pre><code>subleq @OUT, @IN\\n</code></pre>\\n<h3>Comments</h3>\\n<p>Any text following a semicolon is considered a comment. Comments are ignored by the assembler, but may be helpful to humans attempting to decipher existing programs. For example, here''s the previous line of assembly with an explanatory comment:</p>\\n<pre><code>subleq @OUT, @IN ; Negates an input and writes it out\\n</code></pre>\\n<h3>Labels</h3>\\n<p>Custom labels are defined with the syntax <code>@name:</code>, e.g.:</p>\\n<pre><code>@loop: subleq 1, 2\\n</code></pre>\\n<p>Label names cannot include punctuation, symbols, or whitespace.</p>\\n<h3><code>.data</code> directive</h3>\\n<p>In addition to <code>subleq</code>, there is an assembler directive <code>.data</code> that sets one or more bytes of memory to specific values at compile time (note: this is not an instruction!):</p>\\n<pre><code>.data X\\n</code></pre>\\n<p>In the simplest case, <code>X</code> is a signed byte between -128 and 127 (inclusive).</p>\\n<p>Multiple values can also be provided (separated by whitespace and, optionally, commas):</p>\\n<pre><code>.data 1, -2, 3\\n</code></pre>\\n<p>Note: labels (with optional offsets), characters, and strings--along with negations of these--can also be supplied. Examples of these appear in subsequent sections.</p>\\n<h3>Constants and variables</h3>\\n<p>Combining labels and the <code>.data</code> directive allows you to develop a system of constants and variables. For example, here a byte is set to zero, and the label <code>@zero</code> points to that value:</p>\\n<pre><code>@zero: .data 0\\n</code></pre>\\n<h3>Unconditional jumps</h3>\\n<p>Variables can be used for implementing an unconditional jump:</p>\\n<pre><code>subleq @zero, @zero, @next\\n</code></pre>\\n<p>This will set <code>@zero</code> to zero minus zero (still zero) and, since the result is always \\u2264 0, execution always branches to the label <code>@next</code>.</p>\\n<h3>Loop example</h3>\\n<p>Below is an updated negation program that repeatedly negates input values and writes them out in a loop.</p>\\n<pre><code>@loop:\\nsubleq @OUT, @IN           ; Negate an input and write it out\\nsubleq @zero, @zero, @loop ; Unconditional jump to @loop\\n\\n@zero: .data 0             ; Always zero\\n</code></pre>\\n<h3>Label offsets</h3>\\n<p>Label expressions can include an optional offset. For example, <code>@loop+1</code> refers to the <em>second</em> byte of the instruction pointed to by <code>@loop</code>:</p>\\n<pre><code>@loop:\\nsubleq @loop+1, @one\\n</code></pre>\\n<p>Note: in certain cases (usually involving self-modifying code), it is useful to store the address associated with a label (possibly with an offset) in a byte of memory. Here is an example of how to set a byte of memory to the address of <code>@loop+1</code> (i.e. the <em>second</em> byte of the instruction at <code>@loop</code>):</p>\\n<pre><code>; Address of the second byte of @loop\\n@loop_plus_one: .data @loop+1\\n</code></pre>\\n<p>It is possible to negate labels as well by prefixing them with a minus sign. Keep in mind that this only negates the label''s address itself, so if a label with an offset needs to be negated, both the label <em>and the offset</em> should be negated. Here''s the negation of the previous example:</p>\\n<pre><code>; Negation of @loop+1\\n@n_loop_plus_one: .data -@loop-1\\n</code></pre>\\n<h3>Inline labels</h3>\\n<p>As an alternative to offsets, labels can be defined inline. For example <code>@source</code> refers to the <em>second</em> byte of the following instruction:</p>\\n<pre><code>subleq 0, @source:1\\n</code></pre>\\n<h3>Reflection example</h3>\\n<p>Label offsets and inline labels are useful in self-modifying code. Remember, each <code>subleq</code> instruction is stored as 3 consecutive addresses: <code>ABC</code> (for <code>mem[A] \\u2190 mem[A] - mem[B]</code>, with a branch to <code>C</code> if the result is less than or equal to zero).</p>\\n<p>The sample program below reads its own compiled code and outputs it by incrementing the second address of the instruction at <code>@loop</code> (i.e. modifying address <code>@loop+1</code>).</p>\\n<pre><code>@loop:\\nsubleq @tmp, 0           ; Second address (initially zero) will be incremented below\\nsubleq @OUT, @tmp        ; Output the value\\nsubleq @loop+1, @n_one   ; Here is where the increment is performed\\nsubleq @tmp, @tmp, @loop ; Reset @tmp to zero and unconditionally jump to @loop\\n\\n@tmp: .data 0            ; @tmp is initialized to zero\\n@n_one: .data -1\\n</code></pre>\\n<p>The third instruction is an example of self-modifying code because it actually modifies the first instruction. Specifically, it increments the first instruction''s second address (<code>@loop+1</code>). This causes the <em>next</em> loop iteration''s first instruction to read the <em>next</em> byte of memory (0, 1, 2, 3, ...).</p>\\n<p>The program above used a label with an offset, but it could have just as easily been written using an inline label (e.g. defining a <em>new</em> label, <code>subleq @tmp, @source:0</code>, and referring to <code>@source</code> instead of <code>@loop+1</code>). Both approaches compile down to the same sequence of bytes.</p>\\n<p>Note: When running a program in the SIC-1 Development Environment, the original (unmodified) source code is always shown. If the program modifies itself, the changes are reflected in the memory table in the top right, but <em>not</em> in the source code viewer.</p>\\n<h3>Stack example</h3>\\n<p>This program implements a last-in, first-out stack by modifying the read and write addresses of the instructions that interact with the stack.</p>\\n<p>The program pushes 3 (defined by <code>@count</code>) input values onto the stack and then pops them off (outputting them in reverse order).</p>\\n<pre><code>; The first address of this instruction (which starts\\n; pointing to @stack) will be incremented with each\\n; write to the stack\\n@stack_push:\\nsubleq @stack, @IN\\nsubleq @count, @one, @prepare_to_pop\\n\\n; Modify the instruction at @stack_push (increment\\n; target address)\\nsubleq @stack_push, @n_one\\nsubleq @tmp, @tmp, @stack_push\\n\\n; Prepare to start popping values off of the stack by\\n; copying the current stack position to @stack_pop+1\\n@prepare_to_pop:\\nsubleq @tmp, @stack_push\\nsubleq @stack_pop+1, @tmp\\n\\n; Read a value from the stack (note: the second address\\n; of this instruction is repeatedly decremented)\\n@stack_pop:\\nsubleq @OUT, 0\\n\\n; Decrement stack address in the instruction at @stack_pop\\nsubleq @stack_pop+1, @one\\nsubleq @tmp, @tmp, @stack_pop\\n\\n; Constants\\n@one: .data 1\\n@n_one: .data -1\\n\\n; Variables\\n@tmp: .data 0\\n@count: .data 3\\n\\n; Base of stack (stack will grow upwards)\\n@stack: .data 0\\n</code></pre>\\n<h3>Characters</h3>\\n<p>When configured properly, the SIC-1 supports natural human language input and output using a highly modern (c. 1967) mapping from numbers to characters known as ASCII. For example, 72 is mapped to \\\"H\\\" (capital \\\"h\\\").</p>\\n<p>To capture the characters \\\"Hi\\\" (capital \\\"h\\\", lower case \\\"i\\\") in two variables, one could consult an ASCII lookup table and write:</p>\\n<pre><code>@H: .data 72\\n@i: .data 105\\n</code></pre>\\n<p>Consulting an ASCII table is tedious, so to make SIC Systems engineers'' lives easier, SIC-1 Assembly Language now supports automated ASCII lookup using the following advanced syntax (which is equivalent to explicitly specifying characters'' mapped numbers):</p>\\n<pre><code>@H: .data ''H'' ; 72\\n@i: .data ''i'' ; 105\\n</code></pre>\\n<p>As a final convenience, it is possible to negate the value of a character by prefixing the character literal with a minus:</p>\\n<pre><code>@n_H: .data -''H'' ; -72\\n</code></pre>\\n<h3>Character output example</h3>\\n<p>The following sample program outputs the characters \\\"Hi\\\":</p>\\n<pre><code>subleq @OUT, @n_H ; Note: (0 - (-72) = 72 = ''H'')\\nsubleq @OUT, @n_i\\n\\n@n_H: .data -''H''\\n@n_i: .data -''i''\\n</code></pre>\\n<h3>Strings</h3>\\n<p>Strings are sequences of characters that are terminated with a zero. In the following example, @string points to a 3 byte sequence representing the string \\\"Hi\\\":</p>\\n<pre><code>@string:\\n.data ''H''\\n.data ''i''\\n.data 0\\n</code></pre>\\n<p>The .data directive can also take a sequence of values to set multiple bytes, so the previous code would be simplified:</p>\\n<pre><code>@string: .data ''H'', ''i'', 0\\n</code></pre>\\n<p>And thanks to the innovative design-by-committee approach employed by SIC Systems, the following novel syntax for strings can be used (again, equivalent to the other examples):</p>\\n<pre><code>@string: .data \\\"Hi\\\" ; Sets the next 3 bytes: ''H'', ''i'', 0\\n</code></pre>\\n<p>Similar to character values, an entire string can be negated by prefixing it with a minus:</p>\\n<pre><code>@n_string: .data -\\\"Hi\\\" ; Sets the next 3 bytes: -72, -105, 0\\n</code></pre>\\n<h3>New line characters</h3>\\n<p>New line characters (value 10) can be expressed with the character <code>''\\\\n''</code>. They can also be used in strings, for example: <code>\\\"Line 1\\\\nLine 2\\\"</code>.</p>\\n<h3>String output example</h3>\\n<p>The following code outputs \\\"Hello, world!\\\":</p>\\n<pre><code>@loop:\\nsubleq @OUT, @n_message  ; Read address starts at @n_message\\nsubleq @loop+1, @n_one   ; Advance read address\\nsubleq @tmp, @tmp, @loop\\n\\n@n_one: .data -1\\n@n_message: .data -\\\"Hello, world!\\\"\\n@tmp: .data 0\\n</code></pre>\\n<h3>ASCII Reference</h3>\\n<p>For completeness, a table of ASCII characters is shown below. Note that SIC-1 only supports ASCII codes 32 through 126, so the first few rows of the table are omitted (and a few cells contain \\\"\\u25a1\\\" to indicate unsupported codes). Each row represents a tens digit (30 - 120), and each column represents a ones digit (0 - 9).</p>\\n<p>Examples:</p>\\n<ul>\\n<li>Row \\\"30\\\", column 2 is a space character (code 32)</li>\\n<li>Row \\\"120\\\", column 2 a lowercase \\\"z\\\" (code 122)</li>\\n</ul>\\n{asciiTable}\\n\\n<h3>Errata</h3>\\n<p>In order to reduce the time-to-market for the SIC-1, some compromises were made in the design of the processor and these design decisions may result in surprising behavior. This section is an attempt to document such cases:</p>\\n<ol>\\n<li>For the purposes of calculating the number of memory bytes read, every <code>subleq</code> instruction reads all 3 bytes, regardless of whether or not the final address is used (i.e. regardless of whether or not the branch is taken)</li>\\n<li><code>subleq</code> instructions (meaning the 3 addresses that comprise the instruction) are always read directly from memory; additionally, memory addresses 253, 254, and 255 cannot be modified and are initialized to zero, so the instruction starting at <code>@MAX</code> (comprised of bytes 252, 253, and 254) will be read as: <code>mem[252]</code>, 0, 0</li>\\n<li><code>subleq @IN, B, C</code> will consume an input in order to compute the result (\\\"input minus <code>mem[B]</code>\\\"), which is used to decide whether to branch to <code>C</code> or not (even though no value will be written because writes to <code>@IN</code> are ignored)</li>\\n<li><code>subleq @IN, @IN</code> will only consume a single input and the result will always be zero</li>\\n<li>Branching to any address above <code>@MAX</code> (252) will halt execution</li>\\n<li><code>subleq A, B, @IN</code> may branch to <code>@IN</code> (253), which will halt (see previous bullet)</li>\\n</ol>\\n\",\n    \"description\": \"HTML content for story mail s0_0\"\n  },\n  \"mails0_0Subject\": {\n    \"defaultMessage\": \"SIC-1 Reference Manual\",\n    \"description\": \"Subject line for story mail s0_0\"\n  },\n  \"mails0_1Content\": {\n    \"defaultMessage\": \"<h3>SIC-1 DEVELOPMENT ENVIRONMENT</h3>\\n<p>The SIC-1 Development Environment provides a state-of-the-art programming and simulation environment for SIC Systems''s Single Instruction Computer Mark 1 (SIC-1).</p>\\n<h3>MENUS</h3>\\n<p>Menus can be accessed using either the \\\"Esc\\\" key or the \\\"Menu\\\" button in the lower-left of the development environment. The Main Menu provides access to the following:</p>\\n<ul>\\n<li><strong>Program Inventory</strong>: Used for switching between assigned programming tasks, as well as viewing employee and task statistics (described in a dedicated section below).</li>\\n<li><strong>Electronic Mail</strong>: An integrated client application for viewing electronic mail from automated agents and other SIC-1 employees (described in a dedicated section below).</li>\\n<li><strong>Options</strong>: A sub-menu for modifying presentation settings (full-screen mode, volume, etc.), and other miscellaneous menus.</li>\\n</ul>\\n<h3>INTEGRATED DEVELOPMENT ENVIRONMENT</h3>\\n<p>The SIC-1 Development Environment desktop is an integrated development environment (IDE) for the SIC-1. There are three main sections (left, right, center):</p>\\n<ul>\\n<li><strong>Left</strong>: Current task description, table of input and output (both expected and actual), simulation state/statistics, buttons for controlling the simulation, and a button for opening the Main Menu (described above).</li>\\n<li><strong>Center</strong>: Main code editor for reading and writing SIC-1 Assembly Language programs (see the separate SIC-1 Reference Manual electronic mail for details).</li>\\n<li><strong>Right</strong>: Detailed simulation state including a complete view of SIC-1 memory, code manipulation tools, as well as an unprecedented, revolutionary feature: a table of variables and their current values, for convenient lookup.</li>\\n</ul>\\n<p>The memory table is shown in hexadecimal for compactness; hover over a cell to see the corresponding decimal value.</p>\\n<p>During execution, the current instruction will be highlighted in both the code editor (center) and the memory table (upper right), current inputs and outputs are highlighted in the tables on the left, and variables are displayed in a table on the right (hover for hexadecimal and unsigned representations, if needed).</p>\\n<p>To aid debugging, it is possible to set breakpoints on <code>subleq</code> instructions. When hit, these breakpoints will pause execution for manual analysis. There are two ways to set breakpoints:</p>\\n<ul>\\n<li>In code, add <code>!</code> to the beginning of a line (e.g. <code>!subleq @OUT, @IN</code>).</li>\\n<li>During execution, click the small circle to the left of any <code>subleq</code> instruction to toggle the breakpoint.</li>\\n</ul>\\n<p>Note that each program may be tested using multiple distinct test sets, the state of the SIC-1 resets between test sets, and the test sets generally include randomly generated input data. Solutions should be robust to arbitrary random data, in order to be eligible for inclusion in solution statistics.</p>\\n<h3>KEYBOARD SHORTCUTS</h3>\\n<p>The SIC-1 Development Environment supports the following convenient keyboard shortcuts:</p>\\n<ul>\\n<li><strong>Esc</strong>: Open/close menu or, if running, pause/halt execution.</li>\\n<li><strong>Ctrl+.</strong>: Execute a single instruction and pause. If the program has not been compiled yet, this will compile the program and pause before executing the first instruction.</li>\\n<li><strong>Ctrl+Enter</strong>: Run instructions until completion/error/pause. If already running, this will increase the speed of execution.</li>\\n<li><strong>Ctrl+Shift+Enter</strong>: Pause execution (if running), otherwise halt execution.</li>\\n<li><strong>F11, Alt+Enter</strong>: Toggle full-screen mode.</li>\\n</ul>\\n<p>Code editing shortcuts:</p>\\n<ul>\\n<li><strong>Ctrl+K Ctrl+F</strong>: Comment out all of the selected lines</li>\\n<li><strong>Ctrl+K Ctrl+U</strong>: Uncomment all of the selected lines</li>\\n<li><strong>Ctrl+M</strong>: Toggle <strong>Tab Insert</strong> mode (by default the Tab key cycles focus, with Tab Insert mode, tabs can be entered into the code editor)</li>\\n<li><strong>Tab</strong>: If in <strong>Tab Insert</strong> mode, insert tabs into the selected lines</li>\\n<li><strong>Shift+Tab</strong>: If in <strong>Tab Insert</strong> mode, un-indent the selected lines</li>\\n</ul>\\n<h3>PROGRAM INVENTORY</h3>\\n<p>The Program Inventory displays a list of assigned tasks on the left. There is also a special \\\"employee statistics\\\" section at the top for viewing how your progress compares to other SIC Systems employees.</p>\\n<p>Select any task on the left to view the description (or your solution''s statistics, as compared to other employees'' solutions, for completed tasks). There is button at the bottom to load the program into the development environment.</p>\\n<p>Under the \\\"File Selection\\\" heading, it''s possible to manage multiple implementations of a task (notably: \\\"New\\\" creates a new solution with default contents, \\\"Copy\\\" duplicates an existing implementation). This can be useful when there is one solution optimizing for fewest cycles, and a different solution optimizing for accessing the least amount of memory.</p>\\n<p>If available, other non-task entries will appear in the Program Inventory, under the \\\"Diversions\\\" heading (such as Sandbox Mode or any company-sanctioned electronic video games--only for use during legally-mandated breaks).</p>\\n<h3>ELECTRONIC MAIL</h3>\\n<p>SIC Systems is pioneering a new digital form of intra-office communication known as \\\"electronic mail\\\". This eliminates paper waste for memos, and also ensures that all communications are securely routed to only the intended recipients.</p>\\n<p>A complete list of received electronic mail is shown in the left pane of the electronic mail viewer (sorted from oldest at the top to newest at the bottom). Note that automated mails are de-emphasized, but they can be opened to view statistics for your completed programming tasks.</p>\\n<p>If you have any unread mail, it will appear in a separate section at the top of the left page, for convenience.</p>\\n<p>Also, remember that you can always access the SIC-1 Reference Manual and this document about the SIC-1 Development Environment from your employee on-boarding mails at the top (oldest) part of the left pane of the electronic mail viewer.</p>\\n<h3>ADDENDUM</h3>\\n<p>Although the SIC-1 Development Environment has been thoroughly tested, it is possible that you may encounter unexpected behavior in certain instances. The authors of the SIC-1 Development Environment have assured us that the most likely causes for such issues are either cosmic rays or large solar flares interfering with sensitive electronics in an unpredictable manner. The simplest way to recover from such interference is to unplug the computer, wait for 30 seconds to allow it to cool and eject any rogue electrons, and then plug it back in.</p>\\n\",\n    \"description\": \"HTML content for story mail s0_1\"\n  },\n  \"mails0_1Subject\": {\n    \"defaultMessage\": \"SIC-1 Dev. Environment\",\n    \"description\": \"Subject line for story mail s0_1\"\n  },\n  \"mails0_2Content\": {\n    \"defaultMessage\": \"<p>Congratulations, {selfName}! SIC Systems has accepted your job application.</p>\\n<p>I''m Mary, and I''ll be your human resources contact at the company.</p>\\n<p>As you''re no doubt aware, as a new trainee, you''ll need to complete a few unpaid training tasks before you''re instated as a full-time employee.</p>\\n<p>You should have already received a couple of electronic mails from our automated onboarding system that you can review:</p>\\n<ul>\\n<li>The SIC-1 Reference Manual, which includes details on <code>subleq</code> and SIC-1 Assembly Language</li>\\n<li>A guide to the SIC-1 Development Environment (including usage information, keyboard shortcuts, etc.)</li>\\n</ul>\\n<p>You can view these mails at any time in the electronic mail viewer, which can be opened using the main menu (which is accessed using the \\\"Menu\\\" button in the lower-left, or by pressing \\\"Esc\\\").</p>\\n<p>All information is, of course, confidential and covered by the nondisclosure agreement you signed as a condition of employment.</p>\\n<p>Please let me know if you have any other questions.</p>\\n<p>Thank you!</p>\\n<p>-Mary</p>\\n\",\n    \"description\": \"HTML content for story mail s0_2\"\n  },\n  \"mails0_2Subject\": {\n    \"defaultMessage\": \"Welcome to SIC Systems!\",\n    \"description\": \"Subject line for story mail s0_2\"\n  },\n  \"mails10_0Content\": {\n    \"defaultMessage\": \"<p>{selfName},</p>\\n<p>I just saw Rick''s mail about Don being promoted for his innovations in sequence processing.</p>\\n<p>Could you drop by my cubicle to discuss a few things?</p>\\n<p>I recall seeing you working late the night before this breakthrough, and I''d just like to understand your involvement there. If your work was used, you deserve credit for it.</p>\\n<p>Regards,</p>\\n<p>-Pat</p>\\n\",\n    \"description\": \"HTML content for story mail s10_0\"\n  },\n  \"mails10_0Subject\": {\n    \"defaultMessage\": \"Rick's mail\",\n    \"description\": \"Subject line for story mail s10_0\"\n  },\n  \"mails11_0Content\": {\n    \"defaultMessage\": \"<p>{selfName},</p>\\n<p>I know this is sudden and unexpected, but you''re going to be joining my team, effective today. Additionally, you have been promoted to <strong>{jobTitle}</strong>.</p>\\n<p>I''m still not entirely clear what happened with Don and the new sequence processing work, but Rick mentioned that Don was considering letting you go, and I thought that seemed unfair. Fortunately, Rick was willing to give me a chance to add you to my team.</p>\\n<p>Anyway, whatever happened, it''s in the past now and we need to focus on the road ahead.</p>\\n<p>Thanks for your hard work!</p>\\n<p>-Pat</p>\\n\",\n    \"description\": \"HTML content for story mail s11_0\"\n  },\n  \"mails11_0Subject\": {\n    \"defaultMessage\": \"Organizational change\",\n    \"description\": \"Subject line for story mail s11_0\"\n  },\n  \"mails12_0Content\": {\n    \"defaultMessage\": \"<p>Greetings, {selfName}.</p>\\n<p>Self-modifying code can be tricky to understand at first. For the \\\"stack memory\\\" example, I found that it''s easiest to simply step through the program (using the \\\"Step\\\" button or \\\"Ctrl+.\\\") to see what it''s doing. Remember that you can click the circle next to a <code>subleq</code> instruction to toggle a breakpoint.</p>\\n<p>Using this approach, you can see that the first bit of code is a loop that repeats as long as <code>@count</code> is greater than zero. Once the counter runs out, execution branches to the next chunk of code, and so on.</p>\\n<p>You can also watch the stack grow in the \\\"Memory\\\" table in the upper right. In the example, the stack happens to start at address 32 (defined by <code>@stack_address</code>), which is the beginning of the third row of the table. Note that numbers are shown in hexadecimal and the \\\"two''s complement\\\" representation is used for negative numbers (meaning <code>80</code> in hex is -128 in decimal), so <code>ff</code> means -1, <code>fe</code> means -2, and so on.</p>\\n<p>Hope that helps!</p>\\n<p>-Feng</p>\\n\",\n    \"description\": \"HTML content for story mail s12_0\"\n  },\n  \"mails12_0Subject\": {\n    \"defaultMessage\": \"Debugging\",\n    \"description\": \"Subject line for story mail s12_0\"\n  },\n  \"mails13_0Content\": {\n    \"defaultMessage\": \"<p>I''m completely lost! How can I reverse a sequence when I don''t even know its length??</p>\\n<p>Feng pointed me to the stack memory example, but that example only reverses 3 numbers. What if the sequence has 4 letters? Or 5???</p>\\n<p>This is starting to go way over my head... is there any chance I can copy your solution? I''ll make sure to have it be a little slower so that it''s not obvious I copied your work.</p>\\n<p>HELP!!!</p>\\n<p>-Ted</p>\\n\",\n    \"description\": \"HTML content for story mail s13_0\"\n  },\n  \"mails13_0Subject\": {\n    \"defaultMessage\": \"REVERSE SEQUENCE???\",\n    \"description\": \"Subject line for story mail s13_0\"\n  },\n  \"mails14_0Content\": {\n    \"defaultMessage\": \"<p>You''re making great progress, {selfName}! These are some very difficult tasks and you''re breezing right through them!</p>\\n<p>I''ll make sure that Rick knows you''re doing great work. I''m pushing hard for you to get promoted, because you really deserve it.</p>\\n<p>Well done!</p>\\n<p>-Pat</p>\\n\",\n    \"description\": \"HTML content for story mail s14_0\"\n  },\n  \"mails14_0Subject\": {\n    \"defaultMessage\": \"Excellent work!\",\n    \"description\": \"Subject line for story mail s14_0\"\n  },\n  \"mails15_0Content\": {\n    \"defaultMessage\": \"<p>Wow! Great job, {selfName}! It looks like you have a deep understanding of self-modifying code. That will be a valuable skill as we continue to push the boundaries of the SIC-1.</p>\\n<p>It''s my honor to let you know that you''ve earned a very well-deserved promotion to <strong>{jobTitle}</strong>!</p>\\n<p>Keep up the great work!</p>\\n<p>-Pat</p>\\n\",\n    \"description\": \"HTML content for story mail s15_0\"\n  },\n  \"mails15_0Subject\": {\n    \"defaultMessage\": \"Wow!\",\n    \"description\": \"Subject line for story mail s15_0\"\n  },\n  \"mails16_0Content\": {\n    \"defaultMessage\": \"<p>Hi, {selfName}! It''s been a while since we last chatted.</p>\\n<p>How do you like working on Pat''s team? It looks like you''re making excellent progress (between you and me, I think you''re doing most, if not all, of the work, though).</p>\\n<p>Don''t share this with anyone, but I''ve been working with one of the other managers (Jerin Kransky) on setting up natural language processing functionality for the SIC-1.</p>\\n<p>Do you have any interest in re-joining my team? I already have Jerin convinced that you''re the right person for the job, and I think another promotion would be in order if you''d be willing to come join us.</p>\\n<p>Let me know what you think!</p>\\n<p>-Don</p>\\n\",\n    \"description\": \"HTML content for story mail s16_0\"\n  },\n  \"mails16_0Subject\": {\n    \"defaultMessage\": \"Very impressive!\",\n    \"description\": \"Subject line for story mail s16_0\"\n  },\n  \"mails17_0Content\": {\n    \"defaultMessage\": \"<p>Hey, {selfName}.</p>\\n<p>I was chatting with Don while we played our weekly round of golf this week, and he said that you were planning to come back to his team to work on some secret new project.</p>\\n<p>It would be awesome to have you back on the team!</p>\\n<p>-Ted</p>\\n<p>P.S. Any chance you''d have time to walk me through your solution to the \\\"sort\\\" task? Thanks!</p>\\n\",\n    \"description\": \"HTML content for story mail s17_0\"\n  },\n  \"mails17_0Subject\": {\n    \"defaultMessage\": \"Don\",\n    \"description\": \"Subject line for story mail s17_0\"\n  },\n  \"mails18_0Content\": {\n    \"defaultMessage\": \"<p>Spectacular work, {selfName}! Based on your innovative solutions, you have been promoted to <strong>{jobTitle}</strong>.</p>\\n<p>Please don''t mention this to anyone else, but I''ve heard rumors that Don (your old boss) and Jerin (another manager) are struggling to make progress on their natural language processing pipeline for the SIC-1.</p>\\n<p>To be honest, I don''t think their team has any engineers of your caliber. I know it''s risky, but I''d like to put you to work on solving some of the natural language problems (under the radar, so to speak).</p>\\n<p>If we can show definitive progress soon, then I think the board would be willing to move the whole project onto our team. That would be a big (and, frankly, unprecedented) promotion for you.</p>\\n<p>Let me know if you have any concerns. And please don''t share this will anyone (especially Ted)!</p>\\n<p>Thank you!</p>\\n<p>-Pat</p>\\n\",\n    \"description\": \"HTML content for story mail s18_0\"\n  },\n  \"mails18_0Subject\": {\n    \"defaultMessage\": \"A promotion, and a new project!\",\n    \"description\": \"Subject line for story mail s18_0\"\n  },\n  \"mails19_0Content\": {\n    \"defaultMessage\": \"<p>{selfName}, do you have a few minutes to drop by my office?</p>\\n<p>I''d like to know if you have put any thought into joining Jerin and I to work on that exciting new natural language processing project I mentioned to you a little while back. It could mean a big promotion for you!</p>\\n<p>If you have any concerns, please, please let me know. It would be a shame to see your talents wasted on another team, to be honest. We''re really working on some revolutionary stuff here!</p>\\n<p>I''ll stop by your cubicle in an hour or so, in case I don''t hear from you by then.</p>\\n<p>Thanks!</p>\\n<p>-Don</p>\\n\",\n    \"description\": \"HTML content for story mail s19_0\"\n  },\n  \"mails19_0Subject\": {\n    \"defaultMessage\": \"Do you have a minute?\",\n    \"description\": \"Subject line for story mail s19_0\"\n  },\n  \"mails1_0Content\": {\n    \"defaultMessage\": \"<p>Hello, {selfName}!</p>\\n<p>I''m your manager, Don, and I''m excited to have you join our team! We''re working very hard to ship our flagship product, the SIC-1, on time and we need all the help we can get.</p>\\n<p>You''ve already met Mary from HR. The other members of your immediate team are Ted and Feng (note: their cubicles are unfortunately on the far end of this floor away from you--I''ll see if I can get you moved closer). In case you see any welcome mail from Rick, be aware that he is my boss (so your skip-level boss). If you have any concerns, I kindly ask you to raise them directly with me before looping in Rick.</p>\\n<p>With introductions out of the way, let''s talk about your job description. You are to implement programs as they''re assigned to you. Your solutions will be compared to other employees'' solutions on the basis of execution time (measured in cycles) and memory usage (measured in bytes).</p>\\n<p>Thanks in advance for your dedication!</p>\\n<p>-Don</p>\\n<p>P.S. Sorry if it was unclear that you would not be paid during training. There must have been a mix-up on HR''s end. I''ll see if there''s anything I can do to right the situation.</p>\\n\",\n    \"description\": \"HTML content for story mail s1_0\"\n  },\n  \"mails1_0Subject\": {\n    \"defaultMessage\": \"Welcome to the team!\",\n    \"description\": \"Subject line for story mail s1_0\"\n  },\n  \"mails20_0Content\": {\n    \"defaultMessage\": \"<p>Hey, {selfName}.</p>\\n<p>I don''t know if you''ve heard, but there are rumors that layoffs are coming. Now might be a good time to dust off your resume!</p>\\n<p>Speaking of which, do you think you''d have a few minutes to drop by my cubicle and tell me what you think of my resume?</p>\\n<p>Do you think it would be a stretch to say that I lead development of sequence processing for the SIC-1 (when I was really only just part of a larger team that worked on it)?</p>\\n<p>Thanks, man!</p>\\n<p>-Ted</p>\\n\",\n    \"description\": \"HTML content for story mail s20_0\"\n  },\n  \"mails20_0Subject\": {\n    \"defaultMessage\": \"Dust off your resume\",\n    \"description\": \"Subject line for story mail s20_0\"\n  },\n  \"mails21_0Content\": {\n    \"defaultMessage\": \"<p>Greetings, {selfName}.</p>\\n<p>I just wanted to let you know that today will be my last day at SIC Systems. I''ve enjoyed working with you, and I hope that my occasional clarifying electronic mails have been as beneficial to your career as working with you has been to mine.</p>\\n<p>I generally try to distance myself from office politics and rumors, but I wanted to let you know that I have credible information that the SIC Systems board is currently trying to fend off a hostile takeover by Ilano Moscato (a foreign billionaire who is rather eccentric, to put it mildly).</p>\\n<p>Based on what I''ve heard from friends who''ve worked at Ilano''s other companies, I''m expecting working conditions here to deteriorate rapidly. Ilano has a reputation for randomly pivoting strategies, overworking his employees, and even flouting certain laws.</p>\\n<p>I urge you to consider looking for employment elsewhere.</p>\\n<p>Best of luck to you, {selfName}!</p>\\n<p>-Feng</p>\\n\",\n    \"description\": \"HTML content for story mail s21_0\"\n  },\n  \"mails21_0Subject\": {\n    \"defaultMessage\": \"Farewell!\",\n    \"description\": \"Subject line for story mail s21_0\"\n  },\n  \"mails22_0Content\": {\n    \"defaultMessage\": \"<p>Rick and Pat,</p>\\n<p>It has come to my attention that Pat''s team has been discreetly working on natural language processing.</p>\\n<p><strong>This absolutely must stop.</strong></p>\\n<p>My team has been solely tasked (by the SIC Systems board) with designing and implementing the natural language processing pipeline for the SIC-1.</p>\\n<p>Your work is redundant and, to be blunt, a misuse of corporate resources. We cannot have two teams working independently on the same problem.</p>\\n<p>Pat, please turn over any documents you''ve created as a part of this duplicate effort immediately or I''ll be forced to refer your entire team to corporate affairs for disciplinary action.</p>\\n<p>-Jerin</p>\\n\",\n    \"description\": \"HTML content for story mail s22_0\"\n  },\n  \"mails22_0Subject\": {\n    \"defaultMessage\": \"Natural language processing\",\n    \"description\": \"Subject line for story mail s22_0\"\n  },\n  \"mails22_1Content\": {\n    \"defaultMessage\": \"<p>Hi, {selfName}.</p>\\n<p>It''s unfortunate that Jerin sent that mail without consulting me or Rick first, but I want you to know that the work you''re doing is very important and we shouldn''t let office politics get in the way.</p>\\n<p>You have made fantastic progress on natural language processing, and I''m confident that once the board sees our tremendous progress, Jerin will be forced to back down. This isn''t the first time an overzealous manager has come knocking on my door. Everything will be fine.</p>\\n<p>Additionally, <strong>I have put together a proposal to create a new position for you, with a significant pay bump</strong>. If you can finish this next task, I''m sure the board will have no other option than to promote you to <em>Distinguished Engineer</em>.</p>\\n<p>Thanks for all the hard work you''ve put in so far!</p>\\n<p>-Pat</p>\\n\",\n    \"description\": \"HTML content for story mail s22_1\"\n  },\n  \"mails22_1Subject\": {\n    \"defaultMessage\": \"Please ignore Jerin's mail\",\n    \"description\": \"Subject line for story mail s22_1\"\n  },\n  \"mails23_0Content\": {\n    \"defaultMessage\": \"<p>Hi, {selfName}. In case we haven''t met yet, I''m Jerin, a peer to your old skip-level manager Rick. I''d like to congratulate you on the work you''ve done so far. What I''ve seen has been most impressive!</p>\\n<p>Effective immediately, you''ll be reporting directly to me to continue your exciting work on natural language processing.</p>\\n<p>Additionally, I''d like to inform you that you''ve been promoted to <strong>{jobTitle}</strong> (although, due to budget cuts, we won''t be able to honor the original compensation package that was discussed).</p>\\n<p>Looking forward to working with you!</p>\\n<p>-Jerin</p>\\n<p>P.S. Pat is no longer employed by SIC Systems.</p>\\n\",\n    \"description\": \"HTML content for story mail s23_0\"\n  },\n  \"mails23_0Subject\": {\n    \"defaultMessage\": \"Welcome aboard!\",\n    \"description\": \"Subject line for story mail s23_0\"\n  },\n  \"mails24_0Content\": {\n    \"defaultMessage\": \"<p>Engineering team,</p>\\n<p>As reported in the news, SIC Systems has agreed to be acquired by Ilano Moscato (majority owner and CEO of Edison, Herbaleaf, and Neutralino).</p>\\n<p>What this means for you:</p>\\n<ul>\\n<li>Your day-to-day duties remain the same</li>\\n<li>No major changes to the organization are planned</li>\\n<li>Ilano has indicated that he will honor all existing approved compensation packages (both cash and equity)</li>\\n</ul>\\n<p>In other words: \\\"business as usual\\\".</p>\\n<p>Please don''t let reports in the media distract you from your work.</p>\\n<p>Let me know if you have any questions. Thank you!</p>\\n<p>-Mary</p>\\n\",\n    \"description\": \"HTML content for story mail s24_0\"\n  },\n  \"mails24_0Subject\": {\n    \"defaultMessage\": \"SIC Systems acquisition\",\n    \"description\": \"Subject line for story mail s24_0\"\n  },\n  \"mails24_1Content\": {\n    \"defaultMessage\": \"<p>{selfName},</p>\\n<p>I just wanted to let you know that I met with our new owner, Ilano, earlier today, and he''s very excited about the work you''re doing.</p>\\n<p>If there''s anything you might need to grind through the last couple of tricky problems, please let me know.</p>\\n<p>-Jerin</p>\\n\",\n    \"description\": \"HTML content for story mail s24_1\"\n  },\n  \"mails24_1Subject\": {\n    \"defaultMessage\": \"New owner\",\n    \"description\": \"Subject line for story mail s24_1\"\n  },\n  \"mails25_0Content\": {\n    \"defaultMessage\": \"<p>{selfName},</p>\\n<p>I wanted to let you know that Rick, Don, and Ted have all been let go.</p>\\n<p>On the surface, it might sound like this means that all the remaining natural language work now falls on your plate. But there''s a silver lining: I''ve been given the go-ahead to offer you some non-cash perks to help you manage your schedule, namely:</p>\\n<ul>\\n<li>Free breakfast, lunch and dinner at the office</li>\\n<li>On-site laundry service</li>\\n<li>An optional home cleaning/maintenance service, if you need it</li>\\n</ul>\\n<p>Thanks for pushing so hard these last few weeks and months!</p>\\n<p>-Jerin</p>\\n\",\n    \"description\": \"HTML content for story mail s25_0\"\n  },\n  \"mails25_0Subject\": {\n    \"defaultMessage\": \"Right-sizing our team\",\n    \"description\": \"Subject line for story mail s25_0\"\n  },\n  \"mails26_0Content\": {\n    \"defaultMessage\": \"<p>Jerin and {selfName},</p>\\n<p>Thanks for welcoming me. I''m excited to work with you!</p>\\n<p>Your team''s work on natural language processing is near and dear to my heart. As you may have heard, I founded Neutralino a few years back, with a goal of allowing a machine to reason about itself.</p>\\n<p>I''d like to task you with a special project to bring a similar capability to the SIC-1, ideally by the end of this quarter. I''ve been shopping around this capability to various governments around the world, and already have \\\"hand shake\\\" agreements for a few multi-billion dollar orders.</p>\\n<p>To say that this work is important would be an understatement. It is revolutionary!</p>\\n<p>Regards,</p>\\n<p>-Ilano</p>\\n\",\n    \"description\": \"HTML content for story mail s26_0\"\n  },\n  \"mails26_0Subject\": {\n    \"defaultMessage\": \"A new focus\",\n    \"description\": \"Subject line for story mail s26_0\"\n  },\n  \"mails26_1Content\": {\n    \"defaultMessage\": \"<p>{selfName},</p>\\n<p>I''m sure you saw the mail from Ilano. He thinks highly of us, but he also expects a lot.</p>\\n<p>To properly motivate you, Ilano has created a new job title exclusively for you: <strong>{jobTitle}</strong>.</p>\\n<p>You''ve shown tenacity to get this far, and you''ll need loads of it for the next batch of tasks. We need to give the SIC-1 the ability to understand its own code, in order to unleash its immense computing power on optimizing its own performance. In addition to existing perks, we''ll be happy to provide:</p>\\n<ul>\\n<li>Free super-vitamins (used by Ilano himself), produced by Herbaleaf</li>\\n<li>Optional sleeping quarters at the office</li>\\n<li>Discounted fertility preservation services</li>\\n</ul>\\n<p>We just need you to push through this one last sprint to the finish line. Your fellow SIC Systems family members thank you for your perseverance!</p>\\n<p>-Jerin</p>\\n\",\n    \"description\": \"HTML content for story mail s26_1\"\n  },\n  \"mails26_1Subject\": {\n    \"defaultMessage\": \"New focus, new title, new perks\",\n    \"description\": \"Subject line for story mail s26_1\"\n  },\n  \"mails27_0Content\": {\n    \"defaultMessage\": \"<p>{selfName},</p>\\n<p>I know we had discussed increasing your compensation, given the increased scope and impact of your work.</p>\\n<p>Unfortunately, Ilano has put a freeze on all new spending, so there''s nothing I can do. My hands are tied.</p>\\n<p>Having said that, I''m sure that once your work is complete and Ilano sees what you''ve been able to accomplish, he''ll make sure you''re duly compensated. He might even want to shift you over to one of his other companies where technical know-how is needed.</p>\\n<p>Just keep your focus on the task at hand!</p>\\n<p>-Jerin</p>\\n\",\n    \"description\": \"HTML content for story mail s27_0\"\n  },\n  \"mails27_0Subject\": {\n    \"defaultMessage\": \"Compensation\",\n    \"description\": \"Subject line for story mail s27_0\"\n  },\n  \"mails27_1Content\": {\n    \"defaultMessage\": \"<p>Engineering team,</p>\\n<p>Unfortunately, due to a scheduling conflict with an executive retreat, Ilano is not available for the previously planned meet & greet today.</p>\\n<p>We will reschedule for next week, at which point you can submit questions for him to answer.</p>\\n<p>Sorry for the late notice!</p>\\n<p>-Mary</p>\\n\",\n    \"description\": \"HTML content for story mail s27_1\"\n  },\n  \"mails27_1Subject\": {\n    \"defaultMessage\": \"Ilano meet & greet\",\n    \"description\": \"Subject line for story mail s27_1\"\n  },\n  \"mails28_0Content\": {\n    \"defaultMessage\": \"<p>Mary,</p>\\n<p>The food at the executive retreat was absolutely horrible. I don''t know how these events worked before, but I always treat my executives to the finest culinary delights the world has to offer.</p>\\n<p>The caviar was almost inedible (definitely <em>not</em> the Caspian Sea beluga caviar I had specifically requested), and the cocktail weenies were similarly unpalatable (anything less than Boar''s Pride should go in the dumpster).</p>\\n<p>What a disgrace!</p>\\n<p>-Ilano</p>\\n<p>P.S. Please reject all meeting requests with staff for the rest of the week. And please come up with convincing excuses this time!</p>\\n\",\n    \"description\": \"HTML content for story mail s28_0\"\n  },\n  \"mails28_0Subject\": {\n    \"defaultMessage\": \"UNACCEPTABLE!\",\n    \"description\": \"Subject line for story mail s28_0\"\n  },\n  \"mails29_0Content\": {\n    \"defaultMessage\": \"<p>Engineering team,</p>\\n<p>Please disregard the previous errant electronic mail that was purportedly sent by Ilano. That mail was apparently actually sent by a rogue human resources employee, Mary Townsend (who has since been fired).</p>\\n<p>Ilano treats all employees with dignity and respect, and would never complain about a matter so trivial as food catering at a meeting. He understands that budget cuts are difficult and, in fact, he has willingly slashed his own salary by 10% in solidarity with all SIC Systems staff.</p>\\n<p>Thank you, and have a great day!</p>\\n<p>-Jeffrey</p>\\n\",\n    \"description\": \"HTML content for story mail s29_0\"\n  },\n  \"mails29_0Subject\": {\n    \"defaultMessage\": \"Clarification\",\n    \"description\": \"Subject line for story mail s29_0\"\n  },\n  \"mails2_0Content\": {\n    \"defaultMessage\": \"<p>{selfName},</p>\\n<p>After talking with Rick, we''ve decided that it''s not fair to make you complete training without compensating you. Hopefully your sitting down for this, because I''ve got some thrilling news.</p>\\n<p><strong>We''re providing free pizza lunches to all trainees!</strong></p>\\n<p>See? I told you I''d make it up to you.</p>\\n<p>Thanks for working hard!</p>\\n<p>-Don</p>\\n\",\n    \"description\": \"HTML content for story mail s2_0\"\n  },\n  \"mails2_0Subject\": {\n    \"defaultMessage\": \"Good news!\",\n    \"description\": \"Subject line for story mail s2_0\"\n  },\n  \"mails2_1Content\": {\n    \"defaultMessage\": \"<p>Hi, {selfName}, I''m Ted. We met in the hallway earlier.</p>\\n<p>Is there any chance you could come over to my cubicle and help me with the first assessment? I''d ask Feng for help, but I haven''t seen him around yet this morning.</p>\\n<p>Yesterday, Feng mentioned something about just using a label that initially points to the value zero, but what does that even mean??? He also said something about being able to reset a variable back to zero by subtracting itself. Is that a thing? I''m so lost!</p>\\n<p>Thanks for your time!</p>\\n<p>-Ted</p>\\n\",\n    \"description\": \"HTML content for story mail s2_1\"\n  },\n  \"mails2_1Subject\": {\n    \"defaultMessage\": \"Help!\",\n    \"description\": \"Subject line for story mail s2_1\"\n  },\n  \"mails30_0Content\": {\n    \"defaultMessage\": \"<p>Truly amazing work, {selfName}!</p>\\n<p>Thank you from the bottom of my heart for all of the sacrifices you''ve made to get us to this point. The SIC-1 is now able to reason about its own code. This is an amazing breakthrough and you should be very proud.</p>\\n<p>Now that we''ve reached this exciting milestone (thanks to your tireless efforts!), SIC Systems honestly can''t challenge someone with your peerless talent. Excitingly, you can now begin the next phase of your career at one of the many other technology companies around the world. I know parting ways is tough, but SIC Systems is a business, not a family, so we have to say goodbye to employees once they''re no longer needed. Thank you one last time, and best of luck in your future endeavors!</p>\\n<p>-Ilano</p>\\n\",\n    \"description\": \"HTML content for story mail s30_0\"\n  },\n  \"mails30_0Subject\": {\n    \"defaultMessage\": \"Unbelievable work!\",\n    \"description\": \"Subject line for story mail s30_0\"\n  },\n  \"mails31_0Content\": {\n    \"defaultMessage\": \"<p>{selfName},</p>\\n<p>It''s great to hear from you!</p>\\n<p>I heard that SIC Systems let you go immediately after you demoed your (incomplete) self-hosting program. Ilano is going to be kicking himself when he realizes that the implementation SIC Systems owns doesn''t support self-modifying code!</p>\\n<p>Now that you''re solely in possession of the only <em>truly</em> self-hosting program for the SIC-1, my advice is: destroy it. Erase all copies, set them on fire, and bury the ashes out in the desert. Ilano doesn''t deserve to ever take advantage of your work again.</p>\\n<p>Speaking of work, I wanted to let you know that I found a job at a small startup that is working on a home computer with a graphical interface. It''s revolutionary stuff, and we need someone with your technical skills to go to market.</p>\\n<p>Is there any chance you''d be open to discussing a lead engineering position over here?</p>\\n<p>If you''re interested, let me know and I''ll schedule a meeting with us and the two remaining founders (both named Steve, by coincidence).</p>\\n<p>Hope to hear from you soon!</p>\\n<p>-Pat</p>\\n\",\n    \"description\": \"HTML content for story mail s31_0\"\n  },\n  \"mails31_0Subject\": {\n    \"defaultMessage\": \"Great to hear from you!\",\n    \"description\": \"Subject line for story mail s31_0\"\n  },\n  \"mails3_0Content\": {\n    \"defaultMessage\": \"<p>Thanks for completing your training, {selfName}! Your starting job title is: <strong>{jobTitle}</strong>.</p>\\n<p>Your finalized compensation package is described in the packet I left on your desk. As always, let me know if you have any questions.</p>\\n<p>Thank you!</p>\\n<p>-Mary</p>\\n\",\n    \"description\": \"HTML content for story mail s3_0\"\n  },\n  \"mails3_0Subject\": {\n    \"defaultMessage\": \"Training complete!\",\n    \"description\": \"Subject line for story mail s3_0\"\n  },\n  \"mails3_1Content\": {\n    \"defaultMessage\": \"<p>Greetings, {selfName}. I''m also on Don''s team and my name is Feng. Let me know if you ever need any assistance.</p>\\n<p>After helping Ted with the first assessment, I thought I''d share my perspective on how to think about SIC-1 Assembly Language:</p>\\n<ul>\\n<li><strong>Addresses</strong> are just numbers that identify a specific byte of memory (0 for the first byte, 1 for the second, and so on, up to 255)</li>\\n<li><strong>Labels</strong> are just names for addresses--specifically, the address of whatever comes next in your code (whether it''s a <code>subleq</code> or a <code>.data</code>)</li>\\n<li><code>subleq</code> always compiles into 3 bytes (each one an address)--if you omit the third address, it just gets set to the address of the next instruction in memory</li>\\n<li><code>.data</code> just sets one or more bytes of memory to specific values (positive or negative numbers, or even labels, i.e. addresses)</li>\\n</ul>\\n<p>In the end, everything compiles down to bytes in memory (which you can see in the memory table after you click \\\"Compile\\\" or \\\"Run\\\" to load the program). While running, the SIC-1 only sees those bytes in memory, and it doesn''t know or care how those bytes were produced (or even modified). It will happily interpret any 3 bytes as a <code>subleq</code> instruction--even if that''s not what you intended.</p>\\n<p>It can be instructive to look at a chunk of code and see the resulting compiled bytes. Here''s an example:</p>\\n<pre><code>@loop:\\nsubleq @OUT, @IN           ; 3 byte instruction stored at address 0\\nsubleq @zero, @zero, @loop ; 3 byte instruction stored at address 3\\n\\n@zero: .data 0             ; Initializes address 6 to zero\\n</code></pre>\\n<ul>\\n<li><code>@loop</code> refers to address 0, i.e. the first instruction</li>\\n<li>The first <code>subleq</code> occupies bytes 0, 1, and 2, and is compiled to: 254 (<code>@OUT</code>), 253 (<code>@IN</code>), 3 (the next instruction)</li>\\n<li>The second <code>subleq</code> occupies bytes 3, 4, and 5, and is compiled to: 6 (<code>@zero</code>), 6 (<code>@zero</code>), 0 (<code>@loop</code>)</li>\\n<li><code>@zero</code> refers to address 6, i.e. the next byte (which is initialized to zero using the <code>.data</code> directive)</li>\\n</ul>\\n<p>As you know by now, the first instruction negates an input and writes it out, then advances to the next instruction (regardless of the result). The second instruction subtracts the value at address 6 from itself, always resulting in zero, and thus always jumps to its third argument: <code>@loop</code>, i.e. address 0 (the beginning of the program).</p>\\n<p>Hope that helps!</p>\\n<p>-Feng</p>\\n\",\n    \"description\": \"HTML content for story mail s3_1\"\n  },\n  \"mails3_1Subject\": {\n    \"defaultMessage\": \"My mental model for SIC-1\",\n    \"description\": \"Subject line for story mail s3_1\"\n  },\n  \"mails4_0Content\": {\n    \"defaultMessage\": \"<p>Hey, {selfName}! How''s it feel to be a full-time employee working on the cutting edge of revolutionary technology? Only a single instruction! Amazing!</p>\\n<p>Anyway, I did see your question about the compensation package Mary provided to you. I apologize if the pay is lower than what you were expecting. Another HR mix-up! What can I say?</p>\\n<p>I''ll talk to Rick to see if we can make an exception and raise your pay immediately, but just keep in mind that this company has a lot of room to grow, so your hard efforts will be very well rewarded!</p>\\n<p>-Don</p>\\n\",\n    \"description\": \"HTML content for story mail s4_0\"\n  },\n  \"mails4_0Subject\": {\n    \"defaultMessage\": \"Checking in\",\n    \"description\": \"Subject line for story mail s4_0\"\n  },\n  \"mails4_1Content\": {\n    \"defaultMessage\": \"<p>Greetings, {selfName}.</p>\\n<p>I wanted to share with you a little side project I''ve been working on. I''m calling it \\\"Sandbox Mode\\\". Basically, it''s a special SIC-1 Emulator mode that allows you to specify your own input.</p>\\n<p>This is useful when you just want to play around with the SIC-1 to see how things work. You can experiment with this to test out new techniques without worrying about output getting flagged as incorrect.</p>\\n<p>Sandbox Mode should be visible up in your Program Inventory under the \\\"Diversions\\\" group.</p>\\n<p>Let me know what you think!</p>\\n<p>-Feng</p>\\n\",\n    \"description\": \"HTML content for story mail s4_1\"\n  },\n  \"mails4_1Subject\": {\n    \"defaultMessage\": \"Sandbox Mode\",\n    \"description\": \"Subject line for story mail s4_1\"\n  },\n  \"mails5_0Content\": {\n    \"defaultMessage\": \"<p>Greetings, {selfName}.</p>\\n<p>After talking to Ted, I thought this might be a good time to remind everyone that you can use labels for both variables <em>and constants</em>. A label is really just an address, after all.</p>\\n<p>For example, if I want to be able to write out a 1, I could create a constant. Just remember that if you''re subtracting the constant you''ll want to negate the constant:</p>\\n<pre><code>subleq @OUT, @n_one ; Write out a 1 by subtracting -1 from @OUT\\n                    ; Note: @OUT always reads as zero: 0 - (-1) = 1\\n\\n@n_one: .data -1    ; Constant\\n</code></pre>\\n<p>-Feng</p>\\n\",\n    \"description\": \"HTML content for story mail s5_0\"\n  },\n  \"mails5_0Subject\": {\n    \"defaultMessage\": \"Constants\",\n    \"description\": \"Subject line for story mail s5_0\"\n  },\n  \"mails6_0Content\": {\n    \"defaultMessage\": \"<p>{selfName}, I''m really stuck! Do you have any time to come help me with the multiplication task?</p>\\n<p>I already asked Feng for some help, but all he told me is that I could run a loop a specific number of times by subtracting 1 from a counter each time and then using the result to branch.</p>\\n<p>What does that even mean???</p>\\n<p>-Ted</p>\\n\",\n    \"description\": \"HTML content for story mail s6_0\"\n  },\n  \"mails6_0Subject\": {\n    \"defaultMessage\": \"Loops???\",\n    \"description\": \"Subject line for story mail s6_0\"\n  },\n  \"mails7_0Content\": {\n    \"defaultMessage\": \"<p>Hi, {selfName}! I''m Pat and I''m another engineering lead (I actually work on the same team as your manager, Don).</p>\\n<p>Feng (who used to report to me) mentioned that you''ve been making excellent progress!</p>\\n<p>Anyway, I''ve been tasked with helping to improve morale across the team, so if there''s anything that you especially like or don''t like about the workplace or your compensation (or your team in general), feel free to send me a mail. I''ll make sure to keep all discussions private.</p>\\n<p>Looking forward to hearing from you!</p>\\n<p>-Pat</p>\\n\",\n    \"description\": \"HTML content for story mail s7_0\"\n  },\n  \"mails7_0Subject\": {\n    \"defaultMessage\": \"Nice work!\",\n    \"description\": \"Subject line for story mail s7_0\"\n  },\n  \"mails7_1Content\": {\n    \"defaultMessage\": \"<p>Engineering team,</p>\\n<p>To help improve morale, SIC Systems has provided an officially sanctioned computer video game called \\\"Avoision\\\" for employees to play. If you think your work would benefit from an entertaining diversion, please feel free to compete against your coworkers for the highest score in \\\"Avoision\\\" (during your two legally-mandated unpaid breaks, or in lieu of an unneeded bathroom break).</p>\\n<p>You can find \\\"Avoision\\\" in the \\\"Diversions\\\" section of the program inventory and also in the main menu of the SIC-1 Development Environment.</p>\\n<p>Enjoy!</p>\\n<p>-Mary</p>\\n\",\n    \"description\": \"HTML content for story mail s7_1\"\n  },\n  \"mails7_1Subject\": {\n    \"defaultMessage\": \"Fun and games\",\n    \"description\": \"Subject line for story mail s7_1\"\n  },\n  \"mails8_0Content\": {\n    \"defaultMessage\": \"<p>Nice work on the arithmetic programs, {selfName}! As of this electronic mail, you have been promoted to <strong>{jobTitle}</strong>.</p>\\n<p>I know it''s getting late (and please try to keep this to yourself), but our team really needs to improve our velocity. If there''s any way you can stay late and complete your next task <em>today</em>, there is a very good chance that I''ll be able to promote you to Senior Engineer (and that comes with a hefty pay bump).</p>\\n<p>Again, keep this to yourself. This sort of rapid promotion is extremely rare. Obviously, I can''t guarantee anything, but if you can knuckle down and churn out this next task, things are looking pretty good...</p>\\n<p>Thank you!</p>\\n<p>-Don</p>\\n\",\n    \"description\": \"HTML content for story mail s8_0\"\n  },\n  \"mails8_0Subject\": {\n    \"defaultMessage\": \"Great start!\",\n    \"description\": \"Subject line for story mail s8_0\"\n  },\n  \"mails9_0Content\": {\n    \"defaultMessage\": \"<p>Don (and Don''s team),</p>\\n<p>In recognition of Don''s tireless efforts that have recently culminated in the ability of the SIC-1 to process sequences, I''d like everyone to join me in congratulating Don on his promotion to Principal Engineering Lead!</p>\\n<p>Don, I don''t know how you managed to get sequences up and running so quickly, but we all owe a great debt to you.</p>\\n<p>Thank you once again!</p>\\n<p>-Rick</p>\\n\",\n    \"description\": \"HTML content for story mail s9_0\"\n  },\n  \"mails9_0Subject\": {\n    \"defaultMessage\": \"Congratulations, Don!\",\n    \"description\": \"Subject line for story mail s9_0\"\n  },\n  \"manualHeading\": {\n    \"defaultMessage\": \"<h1>SIC-1 Reference Manual</h1><p>(C) 1979 - 1980 SIC Systems, Inc.</p>\",\n    \"description\": \"Markup shown at the top of the printable/HTML manual\"\n  },\n  \"manualTitle\": {\n    \"defaultMessage\": \"SIC-1 Manual\",\n    \"description\": \"Page title for the HTML/printable manual\"\n  },\n  \"puzzleCodeAddition\": {\n    \"defaultMessage\": \"; Read two numbers and output their sum. Repeat.\\n;\\n; Below is the solution to the previous task. You will need to add additional code to perform addition of two inputs (instead of passing through a single input):\\n\\n@loop:\\nsubleq @tmp, @IN\\nsubleq @OUT, @tmp\\nsubleq @tmp, @tmp, @loop  ; Reset @tmp to zero, and jump to @loop\\n\\n@tmp: .data 0\\n\",\n    \"description\": \"Initial code for the 'Addition' puzzle\"\n  },\n  \"puzzleCodeCharacters\": {\n    \"defaultMessage\": \"; When configured properly, the SIC-1 supports natural human language input and output using a highly modern (c. 1967) mapping from numbers to characters known as ASCII. For example, 72 is mapped to \\\"H\\\" (capital \\\"h\\\").\\n;\\n; To capture the characters \\\"Hi\\\" (capital \\\"h\\\", lower case \\\"i\\\") in two variables, one could consult an ASCII lookup table and write:\\n;\\n;   @H: .data 72\\n;   @i: .data 105\\n;\\n; Consulting an ASCII table is tedious, so to make SIC Systems engineers' lives easier, SIC-1 Assembly Language now supports automated ASCII lookup using the following advanced syntax (which is equivalent to explicitly specifying characters' mapped numbers):\\n;\\n;   @H: .data 'H' ; 72\\n;   @i: .data 'i' ; 105\\n;\\n; As a final convenience, it is possible to negate the value of a character by prefixing the character literal with a minus:\\n;\\n;   @n_H: .data -'H' ; -72\\n;\\n; The following sample program outputs the characters \\\"Hi\\\":\\n\\nsubleq @OUT, @n_H ; Note: (0 - (-72) = 72 = 'H')\\nsubleq @OUT, @n_i\\n\\n@n_H: .data -'H'\\n@n_i: .data -'i'\\n\",\n    \"description\": \"Initial code for the 'Characters' puzzle\"\n  },\n  \"puzzleCodeData Directive and Looping\": {\n    \"defaultMessage\": \"; Custom labels are defined by putting \\\"@name: \\\" at the beginning of a line, e.g.:\\n;\\n;   @loop: subleq 1, 2\\n;\\n; In addition to \\\"subleq\\\", there is an assembler directive \\\".data\\\" that sets a byte of memory to a value at compile time (note: this is not an instruction!):\\n;\\n;   .data X\\n;\\n; X is a signed byte between -128 and 127 (inclusive).\\n;\\n; Combining labels and the \\\".data\\\" directive allows you to develop a system of constants and variables. For example, here a byte is set to zero, and the label @zero points to that value:\\n;\\n;   @zero: .data 0\\n;\\n; Note that, while a program is executing, you can view the current value of each variable in the variable table on the right (under the memory table).\\n;\\n; Variables can be used for implementing an unconditional jump:\\n;\\n;   subleq @zero, @zero, @next\\n;\\n; This will set @zero to @zero - @zero (still zero) and, since the result is always \\u2264 0, execution branches to @next.\\n;\\n; Below is an updated negation program that repeatedly negates input values and writes them out in a loop.\\n\\n@loop:\\nsubleq @OUT, @IN\\nsubleq @zero, @zero, @loop\\n\\n@zero: .data 0\\n\",\n    \"description\": \"Initial code for the 'Data Directive and Looping' puzzle\"\n  },\n  \"puzzleCodeDecimal Digits\": {\n    \"defaultMessage\": \"; For this assignment, map each decimal digit character (e.g. '1') to the numeric value it represents (e.g. '1' -> 1). Inputs will be characters, but outputs are expected to be numbers.\\n;\\n; Keep in mind that the character '1' is not the same as the number 1. The ASCII mapping for '1' is actually 49.\\n;\\n; Also note that the ASCII mappings for '0', '1', '2', etc. are contiguous:\\n;\\n; '0' = 48\\n; '1' = 49\\n; '2' = 50\\n; etc.\\n\\n\",\n    \"description\": \"Initial code for the 'Decimal Digits' puzzle\"\n  },\n  \"puzzleCodeFirst Assessment\": {\n    \"defaultMessage\": \"; Now that you understand the \\\"subleq\\\" instruction, the \\\".data\\\" directive, and labels, you should be able to read values from input and write the exact same values out, by negating the value twice.\\n;\\n; Below is an almost complete solution. You will need to replace instances of \\\"???\\\". Hint: use a label that points to a storage location for a (negated) value.\\n\\n@loop:\\nsubleq ???, @IN\\nsubleq @OUT, ???\\nsubleq @tmp, @tmp, @loop  ; Reset @tmp to zero, and jump to @loop\\n\\n@tmp: .data 0\\n\",\n    \"description\": \"Initial code for the 'First Assessment' puzzle\"\n  },\n  \"puzzleCodeMulti-Line Strings\": {\n    \"defaultMessage\": \"; New line characters (value 10) can be expressed with the character '\\\\n'. They can also be used in strings, for example: \\\"Line 1\\\\nLine 2\\\".\\n;\\n; Read a string with multiple lines and write out each line as a string.\\n\\n\",\n    \"description\": \"Initial code for the 'Multi-Line Strings' puzzle\"\n  },\n  \"puzzleCodeParse Data Directives\": {\n    \"defaultMessage\": \"; Parse a program with multiple .data directives and output the corresponding values.\\n;\\n; Each .data directive only has a single value on the range [-128, 127] (inclusive).\\n\\n\",\n    \"description\": \"Initial code for the 'Parse Data Directives' puzzle\"\n  },\n  \"puzzleCodeParse Subleq Instructions\": {\n    \"defaultMessage\": \"; Parse a program with multiple subleq instructions and output the compiled program.\\n;\\n; Each subleq instruction specifies 3 addresses, separated by spaces (' '). The addresses are on the range [0, 255] (inclusive).\\n;\\n; Note that the unsigned (nonnegative) addresses will be written out as signed values on the range [-128, 127] (also inclusive). For example, 255 becomes -1, 254 becomes -2, ..., 128 becomes -128, but 127 and below are unchanged.\\n\\n\",\n    \"description\": \"Initial code for the 'Parse Subleq Instructions' puzzle\"\n  },\n  \"puzzleCodeSandbox Mode\": {\n    \"defaultMessage\": \"; This is an open-ended program that allows specifying arbitrary input to help employees explore how the SIC-1 operates.\\n;\\n; Use the \\\"Configure Input\\\" button to the left (above the IO table) to provide custom input to the program.\",\n    \"description\": \"Initial code for the 'Sandbox Mode' puzzle\"\n  },\n  \"puzzleCodeSelf-Hosting\": {\n    \"defaultMessage\": \"; Parse a program containing .data directives and subleq instructions, then execute that program.\\n;\\n; All addresses used by the input program should be isolated from your program's address space.\\n;\\n; As in any other program, if the program writes to address 254 (@OUT; signed value: -2), that value should be directly written out.\\n;\\n; If the program branches to address 255 (@HALT; signed value: -1), then the program is done. Start over from scratch with the next input program.\\n;\\n; The compiled size of each input program is \\u2264 21 bytes.\\n;\\n; As in previous tasks, the .data directive will always have exactly 1 value and subleq instructions will specify exactly 3 addresses (separated by spaces only).\\n;\\n; Additionally, the input programs will not use self-modifying code or declare/use any labels or variables. The only built-in addresses that will be used will be referenced by address instead of label (e.g. \\\"254\\\" will be used but \\\"@OUT\\\" will not).\\n\\n\",\n    \"description\": \"Initial code for the 'Self-Hosting' puzzle\"\n  },\n  \"puzzleCodeSelf-Hosting Part 2\": {\n    \"defaultMessage\": \"; Parse a self-modifying program containing .data directives and subleq instructions, then execute that program.\\n;\\n; Writes to address @OUT should be directly written out. If the program branches to address @HALT, then the program is done. Start over from scratch with the next input program.\\n;\\n; The compiled size of each input program is \\u2264 21 bytes.\\n;\\n; As in previous tasks, the .data directive will always have exactly 1 value and subleq instructions will specify exactly 3 addresses (separated by spaces only) and no labels will be used.\\n\\n\",\n    \"description\": \"Initial code for the 'Self-Hosting Part 2' puzzle\"\n  },\n  \"puzzleCodeSelf-Modifying Code\": {\n    \"defaultMessage\": \"; Label expressions can include an optional offset. For example, @loop+1 refers to the second byte of the instruction pointed to by @loop:\\n;\\n;   subleq @loop+1, @one\\n;\\n; This is useful in self-modifying code. Remember, each \\\"subleq\\\" instruction is stored as 3 consecutive addresses, ABC:\\n;\\n; mem[A] \\u2190 mem[A] - mem[B], with a branch to C if the result is less than or equal to zero.\\n;\\n; The sample program below reads its own compiled code. The third instruction is an example of self-modifying code because it actually modifies the first instruction. Specifically, it increments the first instruction's second address (@loop+1). This causes the *next* loop iteration's first instruction to read the *next* byte of memory (0, 1, 2, 3, ...).\\n;\\n; Note: When running a program, the original (unmodified) source code is always shown. If the program modifies itself, the changes are reflected in the memory table in the top right, but *not* in the source code viewer.\\n\\n@loop:\\nsubleq @tmp, 0           ; Second address (initially zero) will be incremented\\nsubleq @OUT, @tmp        ; Output the value\\nsubleq @loop+1, @n_one   ; Here is where the increment is performed\\nsubleq @tmp, @tmp, @loop\\n\\n@tmp: .data 0\\n@n_one: .data -1\\n\",\n    \"description\": \"Initial code for the 'Self-Modifying Code' puzzle\"\n  },\n  \"puzzleCodeStack Memory\": {\n    \"defaultMessage\": \"; This program implements a last-in, first-out stack by modifying the read and write addresses of the instructions that interact with the stack.\\n;\\n; The program pushes 3 (defined by @count) input values onto the stack and then pops them off (outputting them in reverse order).\\n\\n; The first address of this instruction (which starts pointing to @stack) will be incremented with each write to the stack\\n\\n@stack_push:\\nsubleq @stack, @IN\\nsubleq @count, @one, @prepare_to_pop\\n\\n; Modify the instruction at @stack_push (increment target address)\\nsubleq @stack_push, @n_one\\nsubleq @tmp, @tmp, @stack_push\\n\\n; Prepare to start popping values off of the stack by copying the current stack position to @stack_pop+1\\n@prepare_to_pop:\\nsubleq @tmp, @stack_push\\nsubleq @stack_pop+1, @tmp\\n\\n; Read a value from the stack (note: the second address of this instruction is repeatedly decremented)\\n@stack_pop:\\nsubleq @OUT, 0\\n\\n; Decrement stack address in the instruction at @stack_pop\\nsubleq @stack_pop+1, @one\\nsubleq @tmp, @tmp, @stack_pop\\n\\n; Constants\\n@one: .data 1\\n@n_one: .data -1\\n\\n; Variables\\n@tmp: .data 0\\n@count: .data 3\\n\\n; Address of @stack (defined below)\\n@stack_address: .data @stack\\n\\n; Base of stack (stack will grow to larger addresses, so no variables should be placed after this one)\\n@stack: .data 0\\n\",\n    \"description\": \"Initial code for the 'Stack Memory' puzzle\"\n  },\n  \"puzzleCodeStrings\": {\n    \"defaultMessage\": \"; Strings are sequences of characters that are terminated with a zero. In the following example, @string points to a 3 byte sequence representing the string \\\"Hi\\\":\\n;\\n;   @string:\\n;   .data 'H'\\n;   .data 'i'\\n;   .data 0\\n;\\n; Although not discussed previously, the .data directive can actually take a sequence of values to set multiple bytes, so the previous code could be simplified:\\n;\\n;   @string: .data 'H', 'i', 0\\n;\\n; And thanks to the innovative design-by-committee approach employed by SIC Systems, the following novel syntax for strings can be used (again, equivalent to the other examples):\\n;\\n;   @string: .data \\\"Hi\\\" ; Sets the next 3 bytes: 'H', 'i', 0\\n;\\n; Similar to character values, an entire string can be negated by prefixing it with a minus:\\n;\\n;   @n_string: .data -\\\"Hi\\\" ; Sets the next 3 bytes: -72, -105, 0\\n;\\n; The following code outputs \\\"Hello, world!\\\":\\n\\n@loop:\\nsubleq @OUT, @n_message  ; Read address starts at @n_message\\nsubleq @loop+1, @n_one   ; Advance read address\\nsubleq @tmp, @tmp, @loop\\n\\n@n_one: .data -1\\n@n_message: .data -\\\"Hello, world!\\\"\\n@tmp: .data 0\\n\",\n    \"description\": \"Initial code for the 'Strings' puzzle\"\n  },\n  \"puzzleCodeSubleq Instruction and Output\": {\n    \"defaultMessage\": \"; The Single Instruction Computer Mark 1 (SIC-1) is an 8-bit computer with 256 bytes of memory. Programs for the SIC-1 are written in SIC-1 Assembly Language.\\n;\\n; Each instruction is 3 bytes, specified as follows:\\n;\\n;   subleq A B [C]\\n;\\n; A, B, and C are memory addresses (0 - 255) or labels.\\n;\\n; \\\"subleq\\\" subtracts the value at address B from the value at address A and stores the result at address A (i.e. mem[A] \\u2190 mem[A] - mem[B]).\\n;\\n; If the result is \\u2264 0, execution branches to address C.\\n;\\n; Note that if C is not specified, the address of the next instruction is automatically added by the assembler (in effect, this means that taking the branch is no different from advancing to the next instruction).\\n;\\n; For convenience, addresses can be specified using labels. The following predefined labels are always available:\\n;\\n;   @MAX (252): Maximum user-modifiable address\\n;   @IN (253): Reads a value from input (writes are ignored)\\n;   @OUT (254): Writes a result to output (reads as zero)\\n;   @HALT (255): Terminates the program when accessed\\n;\\n; Note: any text following a semicolon is considered a comment. Comments are ignored by the assembler.\\n; \\n; Below is a very simple SIC-1 program that negates one input value and writes it out.\\n;\\n; E.g. if the input value from @IN is 3, it subtracts 3 from @OUT (which reads as zero), and the result of 0 - 3 = -3 is written out.\\n\\nsubleq @OUT, @IN\\n\\n; Use the \\\"Compile/Step\\\" (Ctrl+.) and \\\"Run\\\" (Ctrl+Enter) buttons to execute the program until all expected outputs have been successfully written out (see the \\\"In\\\"/\\\"Expected\\\"/\\\"Out\\\" table to the left).\\n    \",\n    \"description\": \"Initial code for the 'Subleq Instruction and Output' puzzle\"\n  },\n  \"puzzleCodeTokenizer\": {\n    \"defaultMessage\": \"; Read a string and output each word as its own string. Repeat.\\n;\\n; Note: words are each separated by a single space (and the last word ends with a zero).\\n\\n\",\n    \"description\": \"Initial code for the 'Tokenizer' puzzle\"\n  },\n  \"puzzleCodeUppercase\": {\n    \"defaultMessage\": \"; Read and output characters. For each alphabetic character, convert it to uppercase if needed.\\n;\\n; Note that the mappings for 'a', 'b', ... 'z' are contiguous, as are 'A', 'B', ... 'Z'.\\n\\n\",\n    \"description\": \"Initial code for the 'Uppercase' puzzle\"\n  },\n  \"puzzleDescriptionAddition\": {\n    \"defaultMessage\": \"Read two numbers and output their sum. Repeat.\",\n    \"description\": \"Description of the 'Addition' puzzle\"\n  },\n  \"puzzleDescriptionCalculator\": {\n    \"defaultMessage\": \"Read a string representing arithmetic (+, -, or *) on 2 numbers on the interval [1, 127]; write out the resulting value. Repeat.\",\n    \"description\": \"Description of the 'Calculator' puzzle\"\n  },\n  \"puzzleDescriptionCharacters\": {\n    \"defaultMessage\": \"Output the following two characters: \\\"Hi\\\"\",\n    \"description\": \"Description of the 'Characters' puzzle\"\n  },\n  \"puzzleDescriptionData Directive and Looping\": {\n    \"defaultMessage\": \"Use .data and labels to loop.\",\n    \"description\": \"Description of the 'Data Directive and Looping' puzzle\"\n  },\n  \"puzzleDescriptionDecimal Digits\": {\n    \"defaultMessage\": \"Read a decimal digit character, output the numeric value. Repeat.\",\n    \"description\": \"Description of the 'Decimal Digits' puzzle\"\n  },\n  \"puzzleDescriptionDivision\": {\n    \"defaultMessage\": \"Read two positive numbers (A, then B), divide A by B, and output the quotient followed by the remainder. Repeat.\",\n    \"description\": \"Description of the 'Division' puzzle\"\n  },\n  \"puzzleDescriptionFirst Assessment\": {\n    \"defaultMessage\": \"Write input values to output.\",\n    \"description\": \"Description of the 'First Assessment' puzzle\"\n  },\n  \"puzzleDescriptionIndicator Function\": {\n    \"defaultMessage\": \"Read two zero-terminated sets of numbers on the interval [1, 99], A and B. For each element of B, output a 1 if the value is in A and 0 otherwise. Repeat.\",\n    \"description\": \"Description of the 'Indicator Function' puzzle\"\n  },\n  \"puzzleDescriptionInterleave\": {\n    \"defaultMessage\": \"Read two equal length positive sequences (A and B) and interleave their elements (A1, B1, A2, B2, ...), ending with a single zero. Repeat.\",\n    \"description\": \"Description of the 'Interleave' puzzle\"\n  },\n  \"puzzleDescriptionMode\": {\n    \"defaultMessage\": \"Read a list of numbers on the interval [1, 99] (terminated by a zero) and output the most common element. Repeat.\",\n    \"description\": \"Description of the 'Mode' puzzle\"\n  },\n  \"puzzleDescriptionMulti-Line Strings\": {\n    \"defaultMessage\": \"Read a string with multiple lines and write out each line as a string.\",\n    \"description\": \"Description of the 'Multi-Line Strings' puzzle\"\n  },\n  \"puzzleDescriptionMultiplication\": {\n    \"defaultMessage\": \"Read two nonnegative numbers and output the resulting (nonnegative) product. Repeat.\",\n    \"description\": \"Description of the 'Multiplication' puzzle\"\n  },\n  \"puzzleDescriptionNumber to Sequence\": {\n    \"defaultMessage\": \"Read a number and then output that many 1s, followed by a 0. Repeat.\",\n    \"description\": \"Description of the 'Number to Sequence' puzzle\"\n  },\n  \"puzzleDescriptionParse Data Directives\": {\n    \"defaultMessage\": \"Parse a program with multiple .data directives and output the corresponding values.\",\n    \"description\": \"Description of the 'Parse Data Directives' puzzle\"\n  },\n  \"puzzleDescriptionParse Decimal\": {\n    \"defaultMessage\": \"Read a string representing a number on the interval [1, 127] and output the corresponding value. Repeat.\",\n    \"description\": \"Description of the 'Parse Decimal' puzzle\"\n  },\n  \"puzzleDescriptionParse Subleq Instructions\": {\n    \"defaultMessage\": \"Parse a program with multiple subleq instructions and output the compiled program.\",\n    \"description\": \"Description of the 'Parse Subleq Instructions' puzzle\"\n  },\n  \"puzzleDescriptionPrint Decimal\": {\n    \"defaultMessage\": \"Read a positive number on the interval [1, 127] and output a string representing the number in decimal form. Repeat.\",\n    \"description\": \"Description of the 'Print Decimal' puzzle\"\n  },\n  \"puzzleDescriptionReverse Sequence\": {\n    \"defaultMessage\": \"Read a sequence of positive numbers (terminated by a zero) and output the sequence in reverse order (with zero terminator). Repeat.\",\n    \"description\": \"Description of the 'Reverse Sequence' puzzle\"\n  },\n  \"puzzleDescriptionSandbox Mode\": {\n    \"defaultMessage\": \"An open-ended, configurable program for exploration purposes.\",\n    \"description\": \"Description of the 'Sandbox Mode' puzzle\"\n  },\n  \"puzzleDescriptionSelf-Hosting\": {\n    \"defaultMessage\": \"Read in a SIC-1 program and execute it until it branches to address 255, writing out any values written to address 254. Repeat.\",\n    \"description\": \"Description of the 'Self-Hosting' puzzle\"\n  },\n  \"puzzleDescriptionSelf-Hosting Part 2\": {\n    \"defaultMessage\": \"Read in a self-modifying SIC-1 program and execute it until it branches to address 255, writing out any values written to address 254. Repeat.\",\n    \"description\": \"Description of the 'Self-Hosting Part 2' puzzle\"\n  },\n  \"puzzleDescriptionSelf-Modifying Code\": {\n    \"defaultMessage\": \"Output the program's compiled code byte-by-byte.\",\n    \"description\": \"Description of the 'Self-Modifying Code' puzzle\"\n  },\n  \"puzzleDescriptionSequence Cardinality\": {\n    \"defaultMessage\": \"Read a sequence of positive numbers and output the count of numbers. Repeat. Sequences are terminated by a zero.\",\n    \"description\": \"Description of the 'Sequence Cardinality' puzzle\"\n  },\n  \"puzzleDescriptionSequence Sum\": {\n    \"defaultMessage\": \"Read a sequence of positive numbers and output their sum. Repeat. Sequences are terminated by a zero.\",\n    \"description\": \"Description of the 'Sequence Sum' puzzle\"\n  },\n  \"puzzleDescriptionSign Function\": {\n    \"defaultMessage\": \"Read a number. If less than zero, output -1; if equal to zero, output 0; otherwise output 1. Repeat.\",\n    \"description\": \"Description of the 'Sign Function' puzzle\"\n  },\n  \"puzzleDescriptionSort\": {\n    \"defaultMessage\": \"Read a list of numbers on the interval [1, 99] (terminated by a zero) and output the list ordered smallest to largest, ending with a zero. Repeat.\",\n    \"description\": \"Description of the 'Sort' puzzle\"\n  },\n  \"puzzleDescriptionStack Memory\": {\n    \"defaultMessage\": \"Read 3 values from input and then output the values in reverse order.\",\n    \"description\": \"Description of the 'Stack Memory' puzzle\"\n  },\n  \"puzzleDescriptionStrings\": {\n    \"defaultMessage\": \"Output the string \\\"Hello, world!\\\".\",\n    \"description\": \"Description of the 'Strings' puzzle\"\n  },\n  \"puzzleDescriptionSubleq Instruction and Output\": {\n    \"defaultMessage\": \"Use subleq and input/output to negate an input and write it out.\",\n    \"description\": \"Description of the 'Subleq Instruction and Output' puzzle\"\n  },\n  \"puzzleDescriptionSubtraction\": {\n    \"defaultMessage\": \"Read two numbers (A, then B) and output A minus B. Repeat.\",\n    \"description\": \"Description of the 'Subtraction' puzzle\"\n  },\n  \"puzzleDescriptionTokenizer\": {\n    \"defaultMessage\": \"Read a string and output each word as its own string. Repeat.\",\n    \"description\": \"Description of the 'Tokenizer' puzzle\"\n  },\n  \"puzzleDescriptionUppercase\": {\n    \"defaultMessage\": \"Read and output characters, converting all lowercase characters to uppercase.\",\n    \"description\": \"Description of the 'Uppercase' puzzle\"\n  },\n  \"puzzleDetailSandbox Mode\": {\n    \"defaultMessage\": \"<p>Use Sandbox Mode to freely experiment with the SIC-1 without worrying about output getting flagged as incorrect.</p><p>It's possible to specify custom input using the \\\"Configure Input\\\" button on the left side of the main SIC-1 Development Environment (above the IO table). Input uses the same syntax as in a <code>.data</code> directive (examples: <code>-7</code>, <code>''A''</code>, <code>-\\\"Negated string\\\"</code>).</p>\",\n    \"description\": \"Detailed description of 'Sandbox Mode', shown on its task viewer page\"\n  },\n  \"puzzleGroupTitleAdvanced Techniques\": {\n    \"defaultMessage\": \"Advanced Techniques\",\n    \"description\": \"Title of 'Advanced Techniques' puzzle group\"\n  },\n  \"puzzleGroupTitleArithmetic\": {\n    \"defaultMessage\": \"Arithmetic\",\n    \"description\": \"Title of 'Arithmetic' puzzle group\"\n  },\n  \"puzzleGroupTitleNatural Language Processing\": {\n    \"defaultMessage\": \"Natural Language Processing\",\n    \"description\": \"Title of 'Natural Language Processing' puzzle group\"\n  },\n  \"puzzleGroupTitleSelf-Hosting\": {\n    \"defaultMessage\": \"Self-Hosting\",\n    \"description\": \"Title of 'Self-Hosting' puzzle group\"\n  },\n  \"puzzleGroupTitleSequence Manipulation\": {\n    \"defaultMessage\": \"Sequence Manipulation\",\n    \"description\": \"Title of 'Sequence Manipulation' puzzle group\"\n  },\n  \"puzzleGroupTitleSequences\": {\n    \"defaultMessage\": \"Sequences\",\n    \"description\": \"Title of 'Sequences' puzzle group\"\n  },\n  \"puzzleGroupTitleTutorial\": {\n    \"defaultMessage\": \"Tutorial\",\n    \"description\": \"Title of 'Tutorial' puzzle group\"\n  },\n  \"puzzleHintAddition\": {\n    \"defaultMessage\": \"<p>Subtract two inputs into <code>@tmp</code>.</p>\",\n    \"description\": \"Hint for the 'Addition' puzzle\"\n  },\n  \"puzzleHintCalculator\": {\n    \"defaultMessage\": \"<p>Combine the solutions to \\\"Addition\\\", \\\"Subtraction\\\", \\\"Multiplication\\\", and \\\"Parse Decimal\\\".</p>\",\n    \"description\": \"Hint for the 'Calculator' puzzle\"\n  },\n  \"puzzleHintCharacters\": {\n    \"defaultMessage\": \"<p>This task has already been solved, but note how character literals are used (and negated).</p>\",\n    \"description\": \"Hint for the 'Characters' puzzle\"\n  },\n  \"puzzleHintData Directive and Looping\": {\n    \"defaultMessage\": \"<p>This task has already been solved. Just click <strong>Run</strong>.</p>\",\n    \"description\": \"Hint for the 'Data Directive and Looping' puzzle\"\n  },\n  \"puzzleHintDecimal Digits\": {\n    \"defaultMessage\": \"<p>Subtract the character literal <code>''0''</code>.</p>\",\n    \"description\": \"Hint for the 'Decimal Digits' puzzle\"\n  },\n  \"puzzleHintDivision\": {\n    \"defaultMessage\": \"<p>Repeatedly subtract the divisor from the dividend.</p>\",\n    \"description\": \"Hint for the 'Division' puzzle\"\n  },\n  \"puzzleHintFirst Assessment\": {\n    \"defaultMessage\": \"<p>Negate the value twice (these operations cancel out and result in the original number). This can be done by storing the negated value in a memory location that starts out as zero (e.g. <code>@tmp</code>).</p>\",\n    \"description\": \"Hint for the 'First Assessment' puzzle\"\n  },\n  \"puzzleHintIndicator Function\": {\n    \"defaultMessage\": \"<p>Store the first list for later lookup. Remember to clear the list afterwards.</p>\",\n    \"description\": \"Hint for the 'Indicator Function' puzzle\"\n  },\n  \"puzzleHintInterleave\": {\n    \"defaultMessage\": \"<p>Store the first list for later output. Remember to clear the list afterwards.</p>\",\n    \"description\": \"Hint for the 'Interleave' puzzle\"\n  },\n  \"puzzleHintMode\": {\n    \"defaultMessage\": \"<p>Track both the items, as well as their count.</p>\",\n    \"description\": \"Hint for the 'Mode' puzzle\"\n  },\n  \"puzzleHintMulti-Line Strings\": {\n    \"defaultMessage\": \"<p>This task is very similar to Tokenizer.</p>\",\n    \"description\": \"Hint for the 'Multi-Line Strings' puzzle\"\n  },\n  \"puzzleHintMultiplication\": {\n    \"defaultMessage\": \"<p>Repeatedly subtract one of the numbers, using a counter to ensure the subtraction is done the appropriate number of times.</p>\",\n    \"description\": \"Hint for the 'Multiplication' puzzle\"\n  },\n  \"puzzleHintNumber to Sequence\": {\n    \"defaultMessage\": \"<p>Use a counter to write the appropriate number of <strong>1</strong>s.</p>\",\n    \"description\": \"Hint for the 'Number to Sequence' puzzle\"\n  },\n  \"puzzleHintParse Data Directives\": {\n    \"defaultMessage\": \"<p>This task is similar to \\\"Parse Decimal\\\", but negative numbers need to be handled.</p>\",\n    \"description\": \"Hint for the 'Parse Data Directives' puzzle\"\n  },\n  \"puzzleHintParse Decimal\": {\n    \"defaultMessage\": \"<p>Shifting left one decimal digit is the same as multiplying by ten.</p>\",\n    \"description\": \"Hint for the 'Parse Decimal' puzzle\"\n  },\n  \"puzzleHintParse Subleq Instructions\": {\n    \"defaultMessage\": \"<p>This task is very similar to \\\"Parse Decimal\\\".</p>\",\n    \"description\": \"Hint for the 'Parse Subleq Instructions' puzzle\"\n  },\n  \"puzzleHintPrint Decimal\": {\n    \"defaultMessage\": \"<p>Remember to output digits from most significant to least.</p>\",\n    \"description\": \"Hint for the 'Print Decimal' puzzle\"\n  },\n  \"puzzleHintReverse Sequence\": {\n    \"defaultMessage\": \"<p>Use a stack, and remember to clear the stack afterwards.</p>\",\n    \"description\": \"Hint for the 'Reverse Sequence' puzzle\"\n  },\n  \"puzzleHintSandbox Mode\": {\n    \"defaultMessage\": \"<p>Click \\\"Configure Input\\\" to supply custom input.</p>\",\n    \"description\": \"Hint for the 'Sandbox Mode' puzzle\"\n  },\n  \"puzzleHintSelf-Hosting\": {\n    \"defaultMessage\": \"<p>Use previous decimal-parsing solutions to compile the program, but take care to follow the instructions precisely.</p>\",\n    \"description\": \"Hint for the 'Self-Hosting' puzzle\"\n  },\n  \"puzzleHintSelf-Hosting Part 2\": {\n    \"defaultMessage\": \"<p>You're on your own for this one.</p>\",\n    \"description\": \"Hint for the 'Self-Hosting Part 2' puzzle\"\n  },\n  \"puzzleHintSelf-Modifying Code\": {\n    \"defaultMessage\": \"<p>This task has already been solved, but carefully note how the second byte of the first instruction is modified.</p>\",\n    \"description\": \"Hint for the 'Self-Modifying Code' puzzle\"\n  },\n  \"puzzleHintSequence Cardinality\": {\n    \"defaultMessage\": \"<p>Increment a counter for each element in the sequence.</p>\",\n    \"description\": \"Hint for the 'Sequence Cardinality' puzzle\"\n  },\n  \"puzzleHintSequence Sum\": {\n    \"defaultMessage\": \"<p>Store the value to test whether it indicates the end of the sequence.</p>\",\n    \"description\": \"Hint for the 'Sequence Sum' puzzle\"\n  },\n  \"puzzleHintSign Function\": {\n    \"defaultMessage\": \"<p>Use the \\\"branch if result is \\u2264 0\\\" property of subleq to branch between code blocks, then use (negated) constants to write the appropriate output.</p>\",\n    \"description\": \"Hint for the 'Sign Function' puzzle\"\n  },\n  \"puzzleHintSort\": {\n    \"defaultMessage\": \"<p>Insert items into memory in the correct position.</p>\",\n    \"description\": \"Hint for the 'Sort' puzzle\"\n  },\n  \"puzzleHintStack Memory\": {\n    \"defaultMessage\": \"<p>This task has already been solved, but carefully watch the memory window to see how items are added to the stack.</p>\",\n    \"description\": \"Hint for the 'Stack Memory' puzzle\"\n  },\n  \"puzzleHintStrings\": {\n    \"defaultMessage\": \"<p>This task has already been solved, but note that strings are terminated by a zero.</p>\",\n    \"description\": \"Hint for the 'Strings' puzzle\"\n  },\n  \"puzzleHintSubleq Instruction and Output\": {\n    \"defaultMessage\": \"<p>This task has already been solved. Just click <strong>Run</strong>.</p>\",\n    \"description\": \"Hint for the 'Subleq Instruction and Output' puzzle\"\n  },\n  \"puzzleHintSubtraction\": {\n    \"defaultMessage\": \"<p>Use two variables.</p>\",\n    \"description\": \"Hint for the 'Subtraction' puzzle\"\n  },\n  \"puzzleHintTokenizer\": {\n    \"defaultMessage\": \"<p>Strings are terminated by a single zero.</p>\",\n    \"description\": \"Hint for the 'Tokenizer' puzzle\"\n  },\n  \"puzzleHintUppercase\": {\n    \"defaultMessage\": \"<p>Test to see if the input is between \\\"a\\\" and \\\"z\\\", and modify the value as needed.</p>\",\n    \"description\": \"Hint for the 'Uppercase' puzzle\"\n  },\n  \"puzzleTitleAddition\": {\n    \"defaultMessage\": \"Addition\",\n    \"description\": \"Title of the 'Addition' puzzle\"\n  },\n  \"puzzleTitleCalculator\": {\n    \"defaultMessage\": \"Calculator\",\n    \"description\": \"Title of the 'Calculator' puzzle\"\n  },\n  \"puzzleTitleCharacters\": {\n    \"defaultMessage\": \"Characters\",\n    \"description\": \"Title of the 'Characters' puzzle\"\n  },\n  \"puzzleTitleData Directive and Looping\": {\n    \"defaultMessage\": \"Data Directive and Looping\",\n    \"description\": \"Title of the 'Data Directive and Looping' puzzle\"\n  },\n  \"puzzleTitleDecimal Digits\": {\n    \"defaultMessage\": \"Decimal Digits\",\n    \"description\": \"Title of the 'Decimal Digits' puzzle\"\n  },\n  \"puzzleTitleDivision\": {\n    \"defaultMessage\": \"Division\",\n    \"description\": \"Title of the 'Division' puzzle\"\n  },\n  \"puzzleTitleFirst Assessment\": {\n    \"defaultMessage\": \"First Assessment\",\n    \"description\": \"Title of the 'First Assessment' puzzle\"\n  },\n  \"puzzleTitleIndicator Function\": {\n    \"defaultMessage\": \"Indicator Function\",\n    \"description\": \"Title of the 'Indicator Function' puzzle\"\n  },\n  \"puzzleTitleInterleave\": {\n    \"defaultMessage\": \"Interleave\",\n    \"description\": \"Title of the 'Interleave' puzzle\"\n  },\n  \"puzzleTitleMode\": {\n    \"defaultMessage\": \"Mode\",\n    \"description\": \"Title of the 'Mode' puzzle\"\n  },\n  \"puzzleTitleMulti-Line Strings\": {\n    \"defaultMessage\": \"Multi-Line Strings\",\n    \"description\": \"Title of the 'Multi-Line Strings' puzzle\"\n  },\n  \"puzzleTitleMultiplication\": {\n    \"defaultMessage\": \"Multiplication\",\n    \"description\": \"Title of the 'Multiplication' puzzle\"\n  },\n  \"puzzleTitleNumber to Sequence\": {\n    \"defaultMessage\": \"Number to Sequence\",\n    \"description\": \"Title of the 'Number to Sequence' puzzle\"\n  },\n  \"puzzleTitleParse Data Directives\": {\n    \"defaultMessage\": \"Parse Data Directives\",\n    \"description\": \"Title of the 'Parse Data Directives' puzzle\"\n  },\n  \"puzzleTitleParse Decimal\": {\n    \"defaultMessage\": \"Parse Decimal\",\n    \"description\": \"Title of the 'Parse Decimal' puzzle\"\n  },\n  \"puzzleTitleParse Subleq Instructions\": {\n    \"defaultMessage\": \"Parse Subleq Instructions\",\n    \"description\": \"Title of the 'Parse Subleq Instructions' puzzle\"\n  },\n  \"puzzleTitlePrint Decimal\": {\n    \"defaultMessage\": \"Print Decimal\",\n    \"description\": \"Title of the 'Print Decimal' puzzle\"\n  },\n  \"puzzleTitleReverse Sequence\": {\n    \"defaultMessage\": \"Reverse Sequence\",\n    \"description\": \"Title of the 'Reverse Sequence' puzzle\"\n  },\n  \"puzzleTitleSandbox Mode\": {\n    \"defaultMessage\": \"Sandbox Mode\",\n    \"description\": \"Title of the 'Sandbox Mode' puzzle\"\n  },\n  \"puzzleTitleSelf-Hosting\": {\n    \"defaultMessage\": \"Self-Hosting\",\n    \"description\": \"Title of the 'Self-Hosting' puzzle\"\n  },\n  \"puzzleTitleSelf-Hosting Part 2\": {\n    \"defaultMessage\": \"Self-Hosting Part 2\",\n    \"description\": \"Title of the 'Self-Hosting Part 2' puzzle\"\n  },\n  \"puzzleTitleSelf-Modifying Code\": {\n    \"defaultMessage\": \"Self-Modifying Code\",\n    \"description\": \"Title of the 'Self-Modifying Code' puzzle\"\n  },\n  \"puzzleTitleSequence Cardinality\": {\n    \"defaultMessage\": \"Sequence Cardinality\",\n    \"description\": \"Title of the 'Sequence Cardinality' puzzle\"\n  },\n  \"puzzleTitleSequence Sum\": {\n    \"defaultMessage\": \"Sequence Sum\",\n    \"description\": \"Title of the 'Sequence Sum' puzzle\"\n  },\n  \"puzzleTitleSign Function\": {\n    \"defaultMessage\": \"Sign Function\",\n    \"description\": \"Title of the 'Sign Function' puzzle\"\n  },\n  \"puzzleTitleSort\": {\n    \"defaultMessage\": \"Sort\",\n    \"description\": \"Title of the 'Sort' puzzle\"\n  },\n  \"puzzleTitleStack Memory\": {\n    \"defaultMessage\": \"Stack Memory\",\n    \"description\": \"Title of the 'Stack Memory' puzzle\"\n  },\n  \"puzzleTitleStrings\": {\n    \"defaultMessage\": \"Strings\",\n    \"description\": \"Title of the 'Strings' puzzle\"\n  },\n  \"puzzleTitleSubleq Instruction and Output\": {\n    \"defaultMessage\": \"Subleq Instruction and Output\",\n    \"description\": \"Title of the 'Subleq Instruction and Output' puzzle\"\n  },\n  \"puzzleTitleSubtraction\": {\n    \"defaultMessage\": \"Subtraction\",\n    \"description\": \"Title of the 'Subtraction' puzzle\"\n  },\n  \"puzzleTitleTokenizer\": {\n    \"defaultMessage\": \"Tokenizer\",\n    \"description\": \"Title of the 'Tokenizer' puzzle\"\n  },\n  \"puzzleTitleUppercase\": {\n    \"defaultMessage\": \"Uppercase\",\n    \"description\": \"Title of the 'Uppercase' puzzle\"\n  },\n  \"rank\": {\n    \"defaultMessage\": \"Rank: {ranking}\",\n    \"description\": \"Current ranking of the player\"\n  },\n  \"rankOutOf\": {\n    \"defaultMessage\": \"{rank} out of {total}\",\n    \"description\": \"Actual ranking value (out of total)\"\n  },\n  \"selectColorScheme\": {\n    \"defaultMessage\": \"Color scheme:\",\n    \"description\": \"Label for the 'color scheme' dropdown menu\"\n  },\n  \"selectLanguage\": {\n    \"defaultMessage\": \"Language:\",\n    \"description\": \"Label for the 'language selection' dropdown menu\"\n  },\n  \"sliderMusicVolume\": {\n    \"defaultMessage\": \"Music volume:\",\n    \"description\": \"Label for the 'music volume' slider\"\n  },\n  \"sliderSoundVolume\": {\n    \"defaultMessage\": \"Sound effects volume:\",\n    \"description\": \"Label for the 'sound effects volume' slider\"\n  },\n  \"sliderZoom\": {\n    \"defaultMessage\": \"Zoom:\",\n    \"description\": \"Label for the text size slider\"\n  },\n  \"solutionButtonCancelDelete\": {\n    \"defaultMessage\": \"Cancel\",\n    \"description\": \"Text on the 'cancel' button when trying to delete an item in the solution manager\"\n  },\n  \"solutionButtonConfirmDelete\": {\n    \"defaultMessage\": \"Delete\",\n    \"description\": \"Text on 'delete' button to confirm deletion in the solution manager\"\n  },\n  \"solutionNameDefault\": {\n    \"defaultMessage\": \"Untitled\",\n    \"description\": \"Default name for new solution files\"\n  },\n  \"solutionStatsSuffix\": {\n    \"defaultMessage\": \" (cycles: {cycles}, bytes: {bytes})\",\n    \"description\": \"Formatted statistics that are appended to a solution title, for reference (note the leading space)\"\n  },\n  \"stateStatusRunning\": {\n    \"defaultMessage\": \"Running\",\n    \"description\": \"Text shown for the simulation 'state' shown in the lower-left, when running\"\n  },\n  \"stateStatusStopped\": {\n    \"defaultMessage\": \"Stopped\",\n    \"description\": \"Text shown for the simulation 'state' shown in the lower-left, when stopped\"\n  },\n  \"taskAchievements\": {\n    \"defaultMessage\": \"Achievements\",\n    \"description\": \"Title of the 'achievements' item in the program inventory/task selector window\"\n  },\n  \"taskAvoision\": {\n    \"defaultMessage\": \"Avoision\",\n    \"description\": \"Title of the 'Avoision' page in the task viewer selector\"\n  },\n  \"taskContentAvoision\": {\n    \"defaultMessage\": \"<p>To help improve morale, SIC Systems has provided an officially sanctioned computer video game called \\\"Avoision\\\" for employees to play. If you think your work would benefit from an entertaining diversion, please feel free to compete against your coworkers for the highest score in \\\"Avoision\\\" (during your two legally-mandated unpaid breaks, or in lieu of an unneeded bathroom break).</p>\\n<h3>Instructions</h3>\\n<p>Use the arrow keys to move your bright green block and try to capture the bright green square. The faster you capture the square, the more points you will score.</p>\\n<p>As you progress, moving dark green blocks will appear. If your bright green block collides with a dark green block, the game is over.</p>\\n<p>Click the \\\"Play Avoision\\\" button below to play.</p>\",\n    \"description\": \"Markup for the 'Avoision' page in the task viewer\"\n  },\n  \"taskDiversions\": {\n    \"defaultMessage\": \"Diversions\",\n    \"description\": \"Title of the 'diversions' group in the program inventory/task selector window\"\n  },\n  \"taskNumberedList\": {\n    \"defaultMessage\": \"{number}. {title}\",\n    \"description\": \"Format for a numbered group in the program inventory/task selection window\"\n  },\n  \"taskProgress\": {\n    \"defaultMessage\": \"Task Progress\",\n    \"description\": \"Title of the 'task progress' item in the program inventory/task selector window\"\n  },\n  \"taskStatusIncomplete\": {\n    \"defaultMessage\": \"Incomplete\",\n    \"description\": \"Status shown for a task that has been viewed, but not yet completed\"\n  },\n  \"taskStatusNew\": {\n    \"defaultMessage\": \"New\",\n    \"description\": \"Status shown for a task that has not yet been viewed\"\n  },\n  \"taskViewerButtonAvoision\": {\n    \"defaultMessage\": \"Play Avoision\",\n    \"description\": \"Text on button for playing Avoision\"\n  },\n  \"taskViewerButtonContinueEditing\": {\n    \"defaultMessage\": \"Continue Editing Current Program\",\n    \"description\": \"Text on button for continuing editing the current program\"\n  },\n  \"taskViewerButtonLoad\": {\n    \"defaultMessage\": \"Load This Program\",\n    \"description\": \"Text on button for loading the selected program\"\n  },\n  \"taskViewerButtonNextIncompleteTask\": {\n    \"defaultMessage\": \"View Next Incomplete Task\",\n    \"description\": \"Text on button for viewing the next incomplete task\"\n  },\n  \"taskViewerButtonSandbox\": {\n    \"defaultMessage\": \"Enter Sandbox Mode\",\n    \"description\": \"Text on button for Sandbox Mode\"\n  },\n  \"taskViewerButtonSolutionCopy\": {\n    \"defaultMessage\": \"Copy\",\n    \"description\": \"Text on the task viewer button to copy a solution file\"\n  },\n  \"taskViewerButtonSolutionDelete\": {\n    \"defaultMessage\": \"Delete\",\n    \"description\": \"Text on the task viewer button to attempt to delete a solution file\"\n  },\n  \"taskViewerButtonSolutionNew\": {\n    \"defaultMessage\": \"New\",\n    \"description\": \"Text on the task viewer button to create a new solution file\"\n  },\n  \"taskViewerButtonSolutionRename\": {\n    \"defaultMessage\": \"Rename\",\n    \"description\": \"Text on the task viewer button to rename a solution file\"\n  },\n  \"taskViewerButtonViewUnread\": {\n    \"defaultMessage\": \"View Unread Electronic Mail\",\n    \"description\": \"Text on button for viewing unread mail\"\n  },\n  \"taskViewerFilesEmpty\": {\n    \"defaultMessage\": \"(No files found)\",\n    \"description\": \"Text shown when there are no solutions saved for a task\"\n  },\n  \"taskViewerHeadingAvoision\": {\n    \"defaultMessage\": \"<cap>User</cap>: {name}{newline}<cap>Program</cap>: Avoision\",\n    \"description\": \"Markup for the heading shown for Avoision in the task viewer; use {newline} in between lines\"\n  },\n  \"taskViewerHeadingFile\": {\n    \"defaultMessage\": \"File Selection\",\n    \"description\": \"Heading for the 'file selection' (save management) part of a task\"\n  },\n  \"taskViewerHeadingUser\": {\n    \"defaultMessage\": \"<cap>User</cap>: {name}{newline}<cap>Title</cap>: {title}\",\n    \"description\": \"Markup for the heading shown on a user-specific page of the program inventory/task viewer; use {newline} in between lines\"\n  },\n  \"taskViewerMotivation\": {\n    \"defaultMessage\": \"<p>SIC Systems appreciates your continued effort.</p><p>For motivational purposes, here is how the number of tasks you have completed compares to other engineers.</p>\",\n    \"description\": \"Motivational message from employer introducing task completion statistics\"\n  },\n  \"taskViewerStatusCompleted\": {\n    \"defaultMessage\": \"Completed\",\n    \"description\": \"Status shown when a task has been completed\"\n  },\n  \"taskViewerStatusLine\": {\n    \"defaultMessage\": \"<cap>Status</cap>: <cap>{status}</cap>\",\n    \"description\": \"Line for status of the task heading shown in the task viewer\"\n  },\n  \"taskViewerTaskHeading\": {\n    \"defaultMessage\": \"<cap>User</cap>: {name}{newline}<cap>Task</cap>: {title}{newline}{statusLine}{newline}{newline}<cap>Description</cap>: {description}\",\n    \"description\": \"Heading content markup shown in the program inventory/task viewer for a particular task; use {newline} at the end of each line; note that {statusLine} is empty for Sandbox Mode\"\n  },\n  \"taskViewerTextIncomplete\": {\n    \"defaultMessage\": \"You have not implemented this program yet. Click \\\"Load This Program\\\" at the bottom of this window to load the program into the editor.\",\n    \"description\": \"Text shown in the task selector when a task has not been successfully implemented yet\"\n  },\n  \"taskWithStatus\": {\n    \"defaultMessage\": \"{title} (<cap>{status}</cap>)\",\n    \"description\": \"Format for showing a task with incomplete or new status\"\n  },\n  \"templateSolutionCopy\": {\n    \"defaultMessage\": \"Copy of {name}\",\n    \"description\": \"Text template for new names when copying an existing solution\"\n  },\n  \"templateSolutionDuplicate\": {\n    \"defaultMessage\": \"{name} ({number})\",\n    \"description\": \"Text template for new names when the desired name already exists\"\n  },\n  \"textCompilationErrorContext\": {\n    \"defaultMessage\": \"<p>On line {sourceLineNumber}:</p><p>{sourceLine}</p>\",\n    \"description\": \"Markup shown for the context of a compilation error, when a source line and line number are available\"\n  },\n  \"textConfirmDelete\": {\n    \"defaultMessage\": \"Delete \\\"{itemName}\\\"?\",\n    \"description\": \"Text asking if the item should be deleted\"\n  },\n  \"textCopyFailed\": {\n    \"defaultMessage\": \"Error: Failed to copy to the clipboard.\",\n    \"description\": \"Message shown when copying text to the clipboard fails (only used on the web version)\"\n  },\n  \"textCopySucceeded\": {\n    \"defaultMessage\": \"Copied to the clipboard!\",\n    \"description\": \"Message printed after copying text to the clipboard succeeds (only used on the web version)\"\n  },\n  \"textCreditsFooter\": {\n    \"defaultMessage\": \"To view third party licenses, {link}.\",\n    \"description\": \"Text at the bottom of the 'credits' message box, with instructions for viewing third party licenses\"\n  },\n  \"textHaltUnexpected\": {\n    \"defaultMessage\": \"All of your assigned tasks require the program to repeat indefinitely, so this is an error that must be corrected.\",\n    \"description\": \"Clarification that halting is not expected for all assigned tasks\"\n  },\n  \"textHint\": {\n    \"defaultMessage\": \"Hint for {task}:\",\n    \"description\": \"Text shown as a heading in the 'hint' message box\"\n  },\n  \"textInputError\": {\n    \"defaultMessage\": \"Error: {message}\",\n    \"description\": \"Text shown when an error occurs when parsing custom input in Sandbox Mode\"\n  },\n  \"textLicenses\": {\n    \"defaultMessage\": \"Third Party Licenses\",\n    \"description\": \"Text heading for the 'third party licenses' message box, showing copyright notices, etc.\"\n  },\n  \"textSaveClear\": {\n    \"defaultMessage\": \"Use the button below to delete your solutions, user name, and achievements:\",\n    \"description\": \"Text content shown in the initial 'clear save data' message box (only used on the web version)\"\n  },\n  \"textSaveClearFailed\": {\n    \"defaultMessage\": \"Error: Failed to clear save data.\",\n    \"description\": \"Message shown when clearing save data fails (only used on the web version)\"\n  },\n  \"textSaveDataImport\": {\n    \"defaultMessage\": \"Paste in your previously exported save data string here:\",\n    \"description\": \"Instructional text shown in the 'import save data' window\"\n  },\n  \"textSaveExport\": {\n    \"defaultMessage\": \"Below is a compressed and encoded copy of your save data. You can later import this data to restore it.\",\n    \"description\": \"Text shown in the 'export save data' message box (only used in the web version)\"\n  },\n  \"textSaveImportFailed\": {\n    \"defaultMessage\": \"Error: Failed to overwrite save data.\",\n    \"description\": \"Text shown when importing save data fails (only used on web version)\"\n  },\n  \"textTaskStatistics\": {\n    \"defaultMessage\": \"Here are performance statistics of your program (as compared to others' programs):\",\n    \"description\": \"Markup introducing task statistic charts for completed tasks\"\n  },\n  \"textVariablesEmpty\": {\n    \"defaultMessage\": \"(empty)\",\n    \"description\": \"Text shown in the 'variables' table when there are no variables\"\n  },\n  \"tooltipCommentBlock\": {\n    \"defaultMessage\": \"Ctrl+K Ctrl+C\",\n    \"description\": \"Tooltip for the 'comment block' button, which comments out the selected lines of program text\"\n  },\n  \"tooltipIndentBlock\": {\n    \"defaultMessage\": \"Tab (in Tab Insert Mode only)\",\n    \"description\": \"Tooltip for the 'indent block' button, which prepends one level of indentation to the selected lines of program text (note: the shortcut key is only supported when Tab Insert Mode is enabled)\"\n  },\n  \"tooltipMenu\": {\n    \"defaultMessage\": \"Esc or F1\",\n    \"description\": \"Tooltip for the 'menu' button, which opens the main menu\"\n  },\n  \"tooltipStep\": {\n    \"defaultMessage\": \"Ctrl+.\",\n    \"description\": \"Tooltip for the 'step/compile' button, indicating keyboard shortcut\"\n  },\n  \"tooltipStepRate\": {\n    \"defaultMessage\": \"Ctrl+Enter\",\n    \"description\": \"Tooltip for the 'run/turbo' button, which adjusts the program execution speed\"\n  },\n  \"tooltipStop\": {\n    \"defaultMessage\": \"Esc or Ctrl+Shift+Enter\",\n    \"description\": \"Tooltip for the 'pause/stop' button, indicating keyboard shortcut\"\n  },\n  \"tooltipTabInsertMode\": {\n    \"defaultMessage\": \"Ctrl+M\",\n    \"description\": \"Tooltip for the 'tab insert mode' toggle button, indicating keyboard shortcut\"\n  },\n  \"tooltipUncommentBlock\": {\n    \"defaultMessage\": \"Ctrl+K Ctrl+U\",\n    \"description\": \"Tooltip for the 'uncomment block' button, which uncomments the selected lines of program text\"\n  },\n  \"tooltipUnindentBlock\": {\n    \"defaultMessage\": \"Shift+Tab (in Tab Insert Mode only)\",\n    \"description\": \"Tooltip for the 'unindent block' button, which removes one level of indentation from the selected lines of program text (note: the shortcut key is only supported when Tab Insert Mode is enabled)\"\n  },\n  \"windowConfigureInput\": {\n    \"defaultMessage\": \"Configure Input\",\n    \"description\": \"Window title for configuring input in Sandbox Mode\"\n  },\n  \"windowEditProfile\": {\n    \"defaultMessage\": \"User Profile\",\n    \"description\": \"Window title for the user profile editing message box (only used on the web version)\"\n  },\n  \"windowHelp\": {\n    \"defaultMessage\": \"Help\",\n    \"description\": \"Window title for the 'help' menu, which provides access to hints, manuals, etc.\"\n  },\n  \"windowHint\": {\n    \"defaultMessage\": \"Hint\",\n    \"description\": \"Window title for the 'hint' message box\"\n  },\n  \"windowIntro\": {\n    \"defaultMessage\": \"Job Application\",\n    \"description\": \"Window title for introduction ('job application') message box\"\n  },\n  \"windowMail\": {\n    \"defaultMessage\": \"Electronic Mail\",\n    \"description\": \"Window title for mail viewer message box\"\n  },\n  \"windowMenu\": {\n    \"defaultMessage\": \"Main Menu\",\n    \"description\": \"Window title for the main menu\"\n  },\n  \"windowOptions\": {\n    \"defaultMessage\": \"Options\",\n    \"description\": \"Window title for the general 'options' message box\"\n  },\n  \"windowSaveClear\": {\n    \"defaultMessage\": \"Clear Data\",\n    \"description\": \"Window title for the 'clear data' initial message box (only used on the web version)\"\n  },\n  \"windowSaveClearConfirm\": {\n    \"defaultMessage\": \"Clear Data?\",\n    \"description\": \"Window title of the 'clear save data' confirmation message box (only used on the web version)\"\n  },\n  \"windowSaveExport\": {\n    \"defaultMessage\": \"Export Data\",\n    \"description\": \"Title of the 'export save data' message box (only used on the web version)\"\n  },\n  \"windowSaveImport\": {\n    \"defaultMessage\": \"Import Data\",\n    \"description\": \"Title of the 'import save data' message box' (only used on the web version)\"\n  },\n  \"windowSaveManage\": {\n    \"defaultMessage\": \"Manage Save Data\",\n    \"description\": \"Window title for the 'manage save data' message box (only used on the web version)\"\n  },\n  \"windowSaveOverwrite\": {\n    \"defaultMessage\": \"Overwrite Data?\",\n    \"description\": \"Window title for the 'overwrite data when importing' confirmation message box (only used on web version)\"\n  },\n  \"windowTasks\": {\n    \"defaultMessage\": \"Program Inventory\",\n    \"description\": \"Window title for the 'program inventory' (shown when resuming and when selecting tasks)\"\n  },\n  \"windowTitleAvoision\": {\n    \"defaultMessage\": \"Avoision\",\n    \"description\": \"Window title for the Avoision message box\"\n  },\n  \"windowTitleConfirmDelete\": {\n    \"defaultMessage\": \"Confirm Deletion\",\n    \"description\": \"Title of 'confirm deletion' message box\"\n  },\n  \"windowTitleCredits\": {\n    \"defaultMessage\": \"Credits\",\n    \"description\": \"Window title for the 'credits' message box\"\n  },\n  \"windowTitleHalt\": {\n    \"defaultMessage\": \"Program Halted\",\n    \"description\": \"Window title for the message box that appears when a program halts\"\n  },\n  \"windowTitleLicenses\": {\n    \"defaultMessage\": \"Licenses\",\n    \"description\": \"Window title for the 'third party licenses' message box, showing copyright notices, etc.\"\n  },\n  \"windowTitleNameExists\": {\n    \"defaultMessage\": \"Name Already Exists\",\n    \"description\": \"Title of 'name already exists' error message box\"\n  },\n  \"windowTitleNameInvalid\": {\n    \"defaultMessage\": \"Invalid Name\",\n    \"description\": \"Title of 'invalid name' error message box\"\n  },\n  \"windowTitleNoProgram\": {\n    \"defaultMessage\": \"No Program\",\n    \"description\": \"Window title for the message box that appears when attempting to run an empty program\"\n  },\n  \"windowTitlePresentationSettings\": {\n    \"defaultMessage\": \"Presentation\",\n    \"description\": \"Window title for the 'presentation settings' message box, which allows toggling full-screen, adjusting volume, etc.\"\n  }\n}", "sic1/client/content/messages-compiled/en.json": "{\n  \"achievementDescriptionAVOISION\": [\n    {\n      \"type\": 0,\n      \"value\": \"Score at least 250 points in Avoision.\"\n    }\n  ],\n  \"achievementDescriptionERASE\": [\n    {\n      \"type\": 0,\n      \"value\": \"Write a program that reads a single input and then deletes itself (sets all memory to zero), without producing output.\"\n    }\n  ],\n  \"achievementDescriptionJOB_TITLE_1\": [\n    {\n      \"type\": 0,\n      \"value\": \"Get promoted to Engineer.\"\n    }\n  ],\n  \"achievementDescriptionJOB_TITLE_2\": [\n    {\n      \"type\": 0,\n      \"value\": \"Get promoted to Engineer II.\"\n    }\n  ],\n  \"achievementDescriptionJOB_TITLE_3\": [\n    {\n      \"type\": 0,\n      \"value\": \"Get promoted to Senior Engineer.\"\n    }\n  ],\n  \"achievementDescriptionJOB_TITLE_4\": [\n    {\n      \"type\": 0,\n      \"value\": \"Get promoted to Principal Engineer.\"\n    }\n  ],\n  \"achievementDescriptionJOB_TITLE_5\": [\n    {\n      \"type\": 0,\n      \"value\": \"Get promoted to Partner Engineer.\"\n    }\n  ],\n  \"achievementDescriptionJOB_TITLE_6\": [\n    {\n      \"type\": 0,\n      \"value\": \"Get promoted to Distinguished Engineer.\"\n    }\n  ],\n  \"achievementDescriptionJOB_TITLE_7\": [\n    {\n      \"type\": 0,\n      \"value\": \"Get a new job title made just for you.\"\n    }\n  ],\n  \"achievementDescriptionJOB_TITLE_8\": [\n    {\n      \"type\": 0,\n      \"value\": \"Obtain the final promotion.\"\n    }\n  ],\n  \"achievementDescriptionNEW_END\": [\n    {\n      \"type\": 0,\n      \"value\": \"Share a true self-hosting program with an old friend.\"\n    }\n  ],\n  \"achievementDescriptionOMIT_SUBLEQ\": [\n    {\n      \"type\": 0,\n      \"value\": \"Solve \\\"Addition\\\" without typing \\\"subleq\\\".\"\n    }\n  ],\n  \"achievementDescriptionTIME_EARLY\": [\n    {\n      \"type\": 0,\n      \"value\": \"Complete a task before 6am (06:00) local time.\"\n    }\n  ],\n  \"achievementDescriptionTIME_LATE\": [\n    {\n      \"type\": 0,\n      \"value\": \"Complete a task after 9pm (21:00) local time.\"\n    }\n  ],\n  \"achievementNameAVOISION\": [\n    {\n      \"type\": 0,\n      \"value\": \"Master Avoider\"\n    }\n  ],\n  \"achievementNameERASE\": [\n    {\n      \"type\": 0,\n      \"value\": \"Self-Destruct\"\n    }\n  ],\n  \"achievementNameJOB_TITLE_1\": [\n    {\n      \"type\": 0,\n      \"value\": \"Engineer\"\n    }\n  ],\n  \"achievementNameJOB_TITLE_2\": [\n    {\n      \"type\": 0,\n      \"value\": \"Engineer II\"\n    }\n  ],\n  \"achievementNameJOB_TITLE_3\": [\n    {\n      \"type\": 0,\n      \"value\": \"Senior Engineer\"\n    }\n  ],\n  \"achievementNameJOB_TITLE_4\": [\n    {\n      \"type\": 0,\n      \"value\": \"Principal Engineer\"\n    }\n  ],\n  \"achievementNameJOB_TITLE_5\": [\n    {\n      \"type\": 0,\n      \"value\": \"Partner Engineer\"\n    }\n  ],\n  \"achievementNameJOB_TITLE_6\": [\n    {\n      \"type\": 0,\n      \"value\": \"Distinguished Engineer\"\n    }\n  ],\n  \"achievementNameJOB_TITLE_7\": [\n    {\n      \"type\": 0,\n      \"value\": \"Special Promotion\"\n    }\n  ],\n  \"achievementNameJOB_TITLE_8\": [\n    {\n      \"type\": 0,\n      \"value\": \"Terminal Promotion\"\n    }\n  ],\n  \"achievementNameNEW_END\": [\n    {\n      \"type\": 0,\n      \"value\": \"To Be Continued\"\n    }\n  ],\n  \"achievementNameOMIT_SUBLEQ\": [\n    {\n      \"type\": 0,\n      \"value\": \"Zero Instruction Computer\"\n    }\n  ],\n  \"achievementNameTIME_EARLY\": [\n    {\n      \"type\": 0,\n      \"value\": \"Up and at 'Em\"\n    }\n  ],\n  \"achievementNameTIME_LATE\": [\n    {\n      \"type\": 0,\n      \"value\": \"Workin' Hard\"\n    }\n  ],\n  \"achievementPopUpTitle\": [\n    {\n      \"type\": 0,\n      \"value\": \"Achievement Unlocked\"\n    }\n  ],\n  \"achievementProgressDetail\": [\n    {\n      \"type\": 1,\n      \"value\": \"achievedCount\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" of \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"achievementCount\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" (\"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"percent\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \")\"\n    }\n  ],\n  \"achievementProgressLine\": [\n    {\n      \"type\": 0,\n      \"value\": \"Achievement Progress: \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"summary\"\n    }\n  ],\n  \"avoisionDefaultScore1\": [\n    {\n      \"type\": 0,\n      \"value\": \"Jerin\"\n    }\n  ],\n  \"avoisionDefaultScore2\": [\n    {\n      \"type\": 0,\n      \"value\": \"Pat\"\n    }\n  ],\n  \"avoisionDefaultScore3\": [\n    {\n      \"type\": 0,\n      \"value\": \"Ted\"\n    }\n  ],\n  \"avoisionGameOver\": [\n    {\n      \"type\": 0,\n      \"value\": \"Game Over\"\n    }\n  ],\n  \"avoisionNewHigh\": [\n    {\n      \"type\": 0,\n      \"value\": \"New High Score!\"\n    }\n  ],\n  \"avoisionPoints\": [\n    {\n      \"type\": 0,\n      \"value\": \"Points: \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"value\"\n    }\n  ],\n  \"avoisionScore\": [\n    {\n      \"type\": 0,\n      \"value\": \"Score: \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"value\"\n    }\n  ],\n  \"bootMessage\": [\n    {\n      \"type\": 0,\n      \"value\": \"\\n ████  █████   ████\\n██       █    ██\\n ███     █    █      SYSTEMS (TM)\\n   ██    █    ██\\n████   █████   ████\\n\\n     \\\"Synergy, simply.\\\"\\n\\n(C) 1980 SIC Systems, Inc.\\n\\nSIC-1 emulator - 50 Hz          ... OK\\nChecking SIC-1 memory      ###/256B OK\\nSimulating SIC-1 8-bit I/O port ... OK\\n\\nLoading SIC-1 Development Environment v120279...\\n\\nStarting hi-res, tri-color graphical session... \"\n    }\n  ],\n  \"buttonAchievementsMenu\": [\n    {\n      \"type\": 0,\n      \"value\": \"Achievements\"\n    }\n  ],\n  \"buttonAvoisionPage\": [\n    {\n      \"type\": 0,\n      \"value\": \"Avoision\"\n    }\n  ],\n  \"buttonCancel\": [\n    {\n      \"type\": 0,\n      \"value\": \"Cancel\"\n    }\n  ],\n  \"buttonCommentBlock\": [\n    {\n      \"type\": 0,\n      \"value\": \"Comment Block\"\n    }\n  ],\n  \"buttonCompile\": [\n    {\n      \"type\": 0,\n      \"value\": \"Compile\"\n    }\n  ],\n  \"buttonConfigureInput\": [\n    {\n      \"type\": 0,\n      \"value\": \"Configure Input\"\n    }\n  ],\n  \"buttonCopyToClipboard\": [\n    {\n      \"type\": 0,\n      \"value\": \"Copy to Clipboard\"\n    }\n  ],\n  \"buttonCredits\": [\n    {\n      \"type\": 0,\n      \"value\": \"Credits\"\n    }\n  ],\n  \"buttonDisableAutoIndent\": [\n    {\n      \"type\": 0,\n      \"value\": \"Disable Auto-Indent Mode\"\n    }\n  ],\n  \"buttonDisableTabInsertMode\": [\n    {\n      \"type\": 0,\n      \"value\": \"Disable Tab Insert Mode\"\n    }\n  ],\n  \"buttonEnableAutoIndent\": [\n    {\n      \"type\": 0,\n      \"value\": \"Enable Auto-Indent Mode\"\n    }\n  ],\n  \"buttonEnableTabInsertMode\": [\n    {\n      \"type\": 0,\n      \"value\": \"Enable Tab Insert Mode\"\n    }\n  ],\n  \"buttonExit\": [\n    {\n      \"type\": 0,\n      \"value\": \"Exit SIC-1\"\n    }\n  ],\n  \"buttonHelp\": [\n    {\n      \"type\": 0,\n      \"value\": \"Help\"\n    }\n  ],\n  \"buttonHelpMenu\": [\n    {\n      \"type\": 0,\n      \"value\": \"Help\"\n    }\n  ],\n  \"buttonHint\": [\n    {\n      \"type\": 0,\n      \"value\": \"Show Hint\"\n    }\n  ],\n  \"buttonIndentBlock\": [\n    {\n      \"type\": 0,\n      \"value\": \"Indent Block\"\n    }\n  ],\n  \"buttonLicenses\": [\n    {\n      \"type\": 0,\n      \"value\": \"click here\"\n    }\n  ],\n  \"buttonManualAssembly\": [\n    {\n      \"type\": 0,\n      \"value\": \"Open SIC-1 Assembly Manual\"\n    }\n  ],\n  \"buttonManualDevEnv\": [\n    {\n      \"type\": 0,\n      \"value\": \"Open Dev. Environment Manual\"\n    }\n  ],\n  \"buttonManualNewWindow\": [\n    {\n      \"type\": 0,\n      \"value\": \"Open Assembly Manual Here\"\n    }\n  ],\n  \"buttonMenu\": [\n    {\n      \"type\": 0,\n      \"value\": \"Menu\"\n    }\n  ],\n  \"buttonMenuMailViewer\": [\n    {\n      \"type\": 0,\n      \"value\": \"Electronic Mail\"\n    }\n  ],\n  \"buttonMenuTaskViewer\": [\n    {\n      \"type\": 0,\n      \"value\": \"Program Inventory\"\n    }\n  ],\n  \"buttonOptionsMenu\": [\n    {\n      \"type\": 0,\n      \"value\": \"Options\"\n    }\n  ],\n  \"buttonPause\": [\n    {\n      \"type\": 0,\n      \"value\": \"Pause\"\n    }\n  ],\n  \"buttonPresentationSettings\": [\n    {\n      \"type\": 0,\n      \"value\": \"Presentation Settings\"\n    }\n  ],\n  \"buttonSandboxMenu\": [\n    {\n      \"type\": 0,\n      \"value\": \"Sandbox Mode\"\n    }\n  ],\n  \"buttonSaveChanges\": [\n    {\n      \"type\": 0,\n      \"value\": \"Save Changes\"\n    }\n  ],\n  \"buttonSaveClear\": [\n    {\n      \"type\": 0,\n      \"value\": \"Clear Data\"\n    }\n  ],\n  \"buttonSaveClearCancel\": [\n    {\n      \"type\": 0,\n      \"value\": \"No, Keep My Save Data\"\n    }\n  ],\n  \"buttonSaveClearConfirm\": [\n    {\n      \"type\": 0,\n      \"value\": \"Yes, Delete My Save Data\"\n    }\n  ],\n  \"buttonSaveClearMenu\": [\n    {\n      \"type\": 0,\n      \"value\": \"Clear Save Data\"\n    }\n  ],\n  \"buttonSaveDataImport\": [\n    {\n      \"type\": 0,\n      \"value\": \"Import Save Data\"\n    }\n  ],\n  \"buttonSaveExportMenu\": [\n    {\n      \"type\": 0,\n      \"value\": \"Export Save Data\"\n    }\n  ],\n  \"buttonSaveImportMenu\": [\n    {\n      \"type\": 0,\n      \"value\": \"Import Save Data\"\n    }\n  ],\n  \"buttonSaveMenu\": [\n    {\n      \"type\": 0,\n      \"value\": \"Manage Save Data\"\n    }\n  ],\n  \"buttonSaveOverwriteConfirm\": [\n    {\n      \"type\": 0,\n      \"value\": \"Yes, Overwrite My Save Data\"\n    }\n  ],\n  \"buttonStep\": [\n    {\n      \"type\": 0,\n      \"value\": \"Step\"\n    }\n  ],\n  \"buttonStepRate4x\": [\n    {\n      \"type\": 0,\n      \"value\": \"Turbo (4x)\"\n    }\n  ],\n  \"buttonStepRate50x\": [\n    {\n      \"type\": 0,\n      \"value\": \"Turbo (50x)\"\n    }\n  ],\n  \"buttonStepRateDefault\": [\n    {\n      \"type\": 0,\n      \"value\": \"Run\"\n    }\n  ],\n  \"buttonStop\": [\n    {\n      \"type\": 0,\n      \"value\": \"Stop\"\n    }\n  ],\n  \"buttonUncommentBlock\": [\n    {\n      \"type\": 0,\n      \"value\": \"Uncomment Block\"\n    }\n  ],\n  \"buttonUnindentBlock\": [\n    {\n      \"type\": 0,\n      \"value\": \"Unindent Block\"\n    }\n  ],\n  \"buttonUserSettingsMenu\": [\n    {\n      \"type\": 0,\n      \"value\": \"User Settings\"\n    }\n  ],\n  \"chartFriendAvoision\": [\n    {\n      \"type\": 0,\n      \"value\": \"Avoision High Scores\"\n    }\n  ],\n  \"chartFriendBytes\": [\n    {\n      \"type\": 0,\n      \"value\": \"Bytes Read (Friends)\"\n    }\n  ],\n  \"chartFriendCycles\": [\n    {\n      \"type\": 0,\n      \"value\": \"Cycles Executed (Friends)\"\n    }\n  ],\n  \"chartFriendTasks\": [\n    {\n      \"type\": 0,\n      \"value\": \"Completed Tasks (Friends)\"\n    }\n  ],\n  \"chartTitleBytes\": [\n    {\n      \"type\": 0,\n      \"value\": \"Bytes Read: \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"bytes\"\n    }\n  ],\n  \"chartTitleCycles\": [\n    {\n      \"type\": 0,\n      \"value\": \"Cycles Executed: \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"cycles\"\n    }\n  ],\n  \"chartTitleTasks\": [\n    {\n      \"type\": 0,\n      \"value\": \"Completed Tasks\"\n    }\n  ],\n  \"checkboxFullscreen\": [\n    {\n      \"type\": 0,\n      \"value\": \"Full screen:\"\n    }\n  ],\n  \"checkboxMusicAfter\": [\n    {\n      \"type\": 0,\n      \"value\": \"Enable music\"\n    }\n  ],\n  \"checkboxMusicBefore\": [\n    {\n      \"type\": 0,\n      \"value\": \"Music\"\n    }\n  ],\n  \"checkboxShareName\": [\n    {\n      \"type\": 0,\n      \"value\": \"Show my name in public leaderboards (if unchecked, your statistics will be shown without a name)\"\n    }\n  ],\n  \"checkboxSoundEffectsAfter\": [\n    {\n      \"type\": 0,\n      \"value\": \"Enable sound effects\"\n    }\n  ],\n  \"checkboxSoundEffectsBefore\": [\n    {\n      \"type\": 0,\n      \"value\": \"Sound effects\"\n    }\n  ],\n  \"colorSchemeAmber Phosphor\": [\n    {\n      \"type\": 0,\n      \"value\": \"Amber Phosphor\"\n    }\n  ],\n  \"colorSchemeBlack on White\": [\n    {\n      \"type\": 0,\n      \"value\": \"Black on White\"\n    }\n  ],\n  \"colorSchemeDefault\": [\n    {\n      \"type\": 0,\n      \"value\": \"Default\"\n    }\n  ],\n  \"colorSchemeGreen Phosphor\": [\n    {\n      \"type\": 0,\n      \"value\": \"Green Phosphor\"\n    }\n  ],\n  \"colorSchemeWhite on Black\": [\n    {\n      \"type\": 0,\n      \"value\": \"White on Black\"\n    }\n  ],\n  \"compilationErrorAddressRangeError\": [\n    {\n      \"type\": 0,\n      \"value\": \"Invalid address argument: \\\"\"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"argument\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \"\\\" (must be an integer on the range [\"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"rangeMin\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \", \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"rangeMax\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \"])!\"\n    }\n  ],\n  \"compilationErrorInternal\": [\n    {\n      \"type\": 0,\n      \"value\": \"Internal compiler error!\"\n    }\n  ],\n  \"compilationErrorInvalidAddressExpressionError\": [\n    {\n      \"type\": 0,\n      \"value\": \"Expected number literal or reference, but got: \\\"\"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"token\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \"\\\"!\"\n    }\n  ],\n  \"compilationErrorInvalidBreakpointError\": [\n    {\n      \"type\": 0,\n      \"value\": \"Breakpoints are only supported on subleq instructions!\"\n    }\n  ],\n  \"compilationErrorInvalidCommandError\": [\n    {\n      \"type\": 0,\n      \"value\": \"Unknown command: \\\"\"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"command\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \"\\\" (valid commands are: \\\"subleq\\\" and \\\".data\\\")!\"\n    }\n  ],\n  \"compilationErrorInvalidDataArgumentCountError\": [\n    {\n      \"type\": 0,\n      \"value\": \"Invalid number of arguments for \\\".data\\\": \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"count\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" (must have at least 1 argument)!\"\n    }\n  ],\n  \"compilationErrorInvalidEscapeCodeError\": [\n    {\n      \"type\": 0,\n      \"value\": \"Invalid escape code: \\\"\"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"character\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \"\\\"!\"\n    }\n  ],\n  \"compilationErrorInvalidSubleqArgumentCountError\": [\n    {\n      \"type\": 0,\n      \"value\": \"Invalid number of arguments for \\\"subleq\\\": \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"count\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" (must be between \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"rangeMin\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" and \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"rangeMax\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \", inclusive)!\"\n    }\n  ],\n  \"compilationErrorInvalidTokenError\": [\n    {\n      \"type\": 0,\n      \"value\": \"Invalid token: \\\"\"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"token\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \"\\\"!\"\n    }\n  ],\n  \"compilationErrorInvalidValueExpressionError\": [\n    {\n      \"type\": 0,\n      \"value\": \"Expected number, character, string, or reference, but got: \\\"\"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"token\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \"\\\"!\"\n    }\n  ],\n  \"compilationErrorLabelAlreadyDefinedError\": [\n    {\n      \"type\": 0,\n      \"value\": \"Label already defined: \\\"\"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"label\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \"\\\"!\"\n    }\n  ],\n  \"compilationErrorMissingCommaOrWhitespaceError\": [\n    {\n      \"type\": 0,\n      \"value\": \"Whitespace or comma required before argument: \\\"\"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"argument\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \"\\\"\"\n    }\n  ],\n  \"compilationErrorMissingWhitespaceError\": [\n    {\n      \"type\": 0,\n      \"value\": \"Whitespace is required after \\\"\"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"command\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \"\\\"!\"\n    }\n  ],\n  \"compilationErrorProgramTooLargeError\": [\n    {\n      \"type\": 0,\n      \"value\": \"Program is too long (maximum size: \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"rangeMax\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" bytes; program size: \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"bytes\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" bytes)!\"\n    }\n  ],\n  \"compilationErrorUndefinedReferenceError\": [\n    {\n      \"type\": 0,\n      \"value\": \"Undefined reference: \\\"\"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"label\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \"\\\"!\"\n    }\n  ],\n  \"compilationErrorValueRangeError\": [\n    {\n      \"type\": 0,\n      \"value\": \"Invalid value argument: \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"value\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" (must be an integer on the range [\"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"rangeMin\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \", \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"rangeMax\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \"])!\"\n    }\n  ],\n  \"contactWithTitle\": [\n    {\n      \"type\": 1,\n      \"value\": \"name\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" (\"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"title\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \")\"\n    }\n  ],\n  \"contact_allName\": [\n    {\n      \"type\": 0,\n      \"value\": \"All Engineering\"\n    }\n  ],\n  \"contact_assistantName\": [\n    {\n      \"type\": 0,\n      \"value\": \"Jeffrey Young\"\n    }\n  ],\n  \"contact_assistantTitle\": [\n    {\n      \"type\": 0,\n      \"value\": \"Executive Assistant\"\n    }\n  ],\n  \"contact_badManager2Name\": [\n    {\n      \"type\": 0,\n      \"value\": \"Don Cooper\"\n    }\n  ],\n  \"contact_badManager2Title\": [\n    {\n      \"type\": 0,\n      \"value\": \"Principal Engineering Lead\"\n    }\n  ],\n  \"contact_badManagerName\": [\n    {\n      \"type\": 0,\n      \"value\": \"Don Cooper\"\n    }\n  ],\n  \"contact_badManagerTeamName\": [\n    {\n      \"type\": 0,\n      \"value\": \"Don's Team\"\n    }\n  ],\n  \"contact_badManagerTitle\": [\n    {\n      \"type\": 0,\n      \"value\": \"Senior Engineering Lead\"\n    }\n  ],\n  \"contact_flunky1Name\": [\n    {\n      \"type\": 0,\n      \"value\": \"Ted Philips\"\n    }\n  ],\n  \"contact_flunky1Title\": [\n    {\n      \"type\": 0,\n      \"value\": \"Engineer\"\n    }\n  ],\n  \"contact_flunkyName\": [\n    {\n      \"type\": 0,\n      \"value\": \"Ted Philips\"\n    }\n  ],\n  \"contact_flunkyTitle\": [\n    {\n      \"type\": 0,\n      \"value\": \"Trainee\"\n    }\n  ],\n  \"contact_goodManager2Name\": [\n    {\n      \"type\": 0,\n      \"value\": \"Pat Miller\"\n    }\n  ],\n  \"contact_goodManagerName\": [\n    {\n      \"type\": 0,\n      \"value\": \"Pat Miller\"\n    }\n  ],\n  \"contact_goodManagerTeamName\": [\n    {\n      \"type\": 0,\n      \"value\": \"Pat's Team\"\n    }\n  ],\n  \"contact_goodManagerTitle\": [\n    {\n      \"type\": 0,\n      \"value\": \"Senior Engineering Lead\"\n    }\n  ],\n  \"contact_hrName\": [\n    {\n      \"type\": 0,\n      \"value\": \"Mary Townsend\"\n    }\n  ],\n  \"contact_hrTitle\": [\n    {\n      \"type\": 0,\n      \"value\": \"Human Resources\"\n    }\n  ],\n  \"contact_mentorName\": [\n    {\n      \"type\": 0,\n      \"value\": \"Feng Lee\"\n    }\n  ],\n  \"contact_mentorTitle\": [\n    {\n      \"type\": 0,\n      \"value\": \"Senior Engineer\"\n    }\n  ],\n  \"contact_onboardingName\": [\n    {\n      \"type\": 0,\n      \"value\": \"SIC Systems Onboarding\"\n    }\n  ],\n  \"contact_otherSkipName\": [\n    {\n      \"type\": 0,\n      \"value\": \"Jerin Kransky\"\n    }\n  ],\n  \"contact_otherSkipTitle\": [\n    {\n      \"type\": 0,\n      \"value\": \"Partner Engineering Manager\"\n    }\n  ],\n  \"contact_ownerName\": [\n    {\n      \"type\": 0,\n      \"value\": \"Ilano Moscato\"\n    }\n  ],\n  \"contact_ownerTitle\": [\n    {\n      \"type\": 0,\n      \"value\": \"Benevolent Dictator for Life\"\n    }\n  ],\n  \"contact_skipName\": [\n    {\n      \"type\": 0,\n      \"value\": \"Rick Wagner\"\n    }\n  ],\n  \"contact_skipTitle\": [\n    {\n      \"type\": 0,\n      \"value\": \"Partner Engineering Manager\"\n    }\n  ],\n  \"contact_taskManagementName\": [\n    {\n      \"type\": 0,\n      \"value\": \"Automated Task Management\"\n    }\n  ],\n  \"contentEditProfile\": [\n    {\n      \"children\": [\n        {\n          \"type\": 0,\n          \"value\": \"Update your user profile as needed:\"\n        }\n      ],\n      \"type\": 8,\n      \"value\": \"p\"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"form\"\n    },\n    {\n      \"children\": [\n        {\n          \"type\": 0,\n          \"value\": \"Note: if you would like to have all of your leaderboard data deleted, send an email to \"\n        },\n        {\n          \"type\": 1,\n          \"value\": \"email\"\n        },\n        {\n          \"type\": 0,\n          \"value\": \" with \\\"\"\n        },\n        {\n          \"type\": 1,\n          \"value\": \"userId\"\n        },\n        {\n          \"type\": 0,\n          \"value\": \"\\\" (your randomly-generated user id) in the subject.\"\n        }\n      ],\n      \"type\": 8,\n      \"value\": \"p\"\n    }\n  ],\n  \"contentHalt\": [\n    {\n      \"children\": [\n        {\n          \"type\": 0,\n          \"value\": \"Program Halted\"\n        }\n      ],\n      \"type\": 8,\n      \"value\": \"h3\"\n    },\n    {\n      \"children\": [\n        {\n          \"type\": 0,\n          \"value\": \"The program halted itself by branching to \\\"@HALT\\\" (address 255).\"\n        }\n      ],\n      \"type\": 8,\n      \"value\": \"p\"\n    }\n  ],\n  \"contentInputEditor\": [\n    {\n      \"children\": [\n        {\n          \"type\": 0,\n          \"value\": \"Instructions\"\n        }\n      ],\n      \"type\": 8,\n      \"value\": \"h3\"\n    },\n    {\n      \"children\": [\n        {\n          \"type\": 0,\n          \"value\": \"For input, use the same syntax as in a \"\n        },\n        {\n          \"children\": [\n            {\n              \"type\": 0,\n              \"value\": \".data\"\n            }\n          ],\n          \"type\": 8,\n          \"value\": \"code\"\n        },\n        {\n          \"type\": 0,\n          \"value\": \" directive (examples: \"\n        },\n        {\n          \"children\": [\n            {\n              \"type\": 0,\n              \"value\": \"-7\"\n            }\n          ],\n          \"type\": 8,\n          \"value\": \"code\"\n        },\n        {\n          \"type\": 0,\n          \"value\": \", \"\n        },\n        {\n          \"children\": [\n            {\n              \"type\": 0,\n              \"value\": \"'A'\"\n            }\n          ],\n          \"type\": 8,\n          \"value\": \"code\"\n        },\n        {\n          \"type\": 0,\n          \"value\": \", \"\n        },\n        {\n          \"children\": [\n            {\n              \"type\": 0,\n              \"value\": \"-\\\"Negated string\\\"\"\n            }\n          ],\n          \"type\": 8,\n          \"value\": \"code\"\n        },\n        {\n          \"type\": 0,\n          \"value\": \").\"\n        }\n      ],\n      \"type\": 8,\n      \"value\": \"p\"\n    }\n  ],\n  \"contentNoProgram\": [\n    {\n      \"children\": [\n        {\n          \"type\": 0,\n          \"value\": \"No Program Loaded!\"\n        }\n      ],\n      \"type\": 8,\n      \"value\": \"h3\"\n    },\n    {\n      \"children\": [\n        {\n          \"type\": 0,\n          \"value\": \"Please compile and load a program.\"\n        }\n      ],\n      \"type\": 8,\n      \"value\": \"p\"\n    }\n  ],\n  \"contentSaveClearConfirm\": [\n    {\n      \"children\": [\n        {\n          \"type\": 0,\n          \"value\": \"WARNING\"\n        }\n      ],\n      \"type\": 8,\n      \"value\": \"h3\"\n    },\n    {\n      \"children\": [\n        {\n          \"type\": 0,\n          \"value\": \"This will delete ALL of your save data! All of your solutions, your user name, and achievements will be lost!\"\n        }\n      ],\n      \"type\": 8,\n      \"value\": \"p\"\n    },\n    {\n      \"children\": [\n        {\n          \"type\": 0,\n          \"value\": \"Are you sure you want to delete all of your data?\"\n        }\n      ],\n      \"type\": 8,\n      \"value\": \"p\"\n    }\n  ],\n  \"contentSaveOverwrite\": [\n    {\n      \"children\": [\n        {\n          \"type\": 0,\n          \"value\": \"WARNING\"\n        }\n      ],\n      \"type\": 8,\n      \"value\": \"h3\"\n    },\n    {\n      \"children\": [\n        {\n          \"type\": 0,\n          \"value\": \"This will overwrite ALL of your current save data with the imported save data!\"\n        }\n      ],\n      \"type\": 8,\n      \"value\": \"p\"\n    },\n    {\n      \"children\": [\n        {\n          \"type\": 0,\n          \"value\": \"Are you sure you want to overwrite any existing save data?\"\n        }\n      ],\n      \"type\": 8,\n      \"value\": \"p\"\n    }\n  ],\n  \"defaultName\": [\n    {\n      \"type\": 0,\n      \"value\": \"Bill\"\n    }\n  ],\n  \"errorInputParsing\": [\n    {\n      \"type\": 0,\n      \"value\": \"Unexpected token: \\\"\"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"token\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \"\\\"!\"\n    }\n  ],\n  \"errorNameExists\": [\n    {\n      \"type\": 0,\n      \"value\": \"A solution named \\\"\"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"name\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \"\\\" already exists.\"\n    }\n  ],\n  \"errorNameInvalid\": [\n    {\n      \"type\": 0,\n      \"value\": \"Solution names must be at most \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"maxLength\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" characters long, and only a single line.\"\n    }\n  ],\n  \"headerCompilationError\": [\n    {\n      \"type\": 0,\n      \"value\": \"Compilation Error\"\n    }\n  ],\n  \"headerIOOutput\": [\n    {\n      \"type\": 0,\n      \"value\": \"Out\"\n    }\n  ],\n  \"headerInputActual\": [\n    {\n      \"type\": 0,\n      \"value\": \"Actual\"\n    }\n  ],\n  \"headerInputExpected\": [\n    {\n      \"type\": 0,\n      \"value\": \"Expected\"\n    }\n  ],\n  \"headerInputIn\": [\n    {\n      \"type\": 0,\n      \"value\": \"In\"\n    }\n  ],\n  \"headerStateMemory\": [\n    {\n      \"type\": 0,\n      \"value\": \"Memory\"\n    }\n  ],\n  \"headerTestSet\": [\n    {\n      \"type\": 0,\n      \"value\": \"Test \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"number\"\n    }\n  ],\n  \"headerVariableLabel\": [\n    {\n      \"type\": 0,\n      \"value\": \"Label (Address)\"\n    }\n  ],\n  \"headerVariableValue\": [\n    {\n      \"type\": 0,\n      \"value\": \"Value\"\n    }\n  ],\n  \"headingEditing\": [\n    {\n      \"type\": 0,\n      \"value\": \"Editing Tools\"\n    }\n  ],\n  \"headingInputEditor\": [\n    {\n      \"type\": 0,\n      \"value\": \"Input values\"\n    }\n  ],\n  \"headingInputFormats\": [\n    {\n      \"type\": 0,\n      \"value\": \"Display formats\"\n    }\n  ],\n  \"headingProgress\": [\n    {\n      \"type\": 0,\n      \"value\": \"Employee Statistics\"\n    }\n  ],\n  \"intro\": [\n    {\n      \"children\": [\n        {\n          \"type\": 0,\n          \"value\": \"Job Description:\"\n        }\n      ],\n      \"type\": 8,\n      \"value\": \"h3\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \"\\r\\n\"\n    },\n    {\n      \"children\": [\n        {\n          \"type\": 0,\n          \"value\": \"SIC Systems is looking for experienced programmers to join our team!\"\n        }\n      ],\n      \"type\": 8,\n      \"value\": \"p\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \"\\r\\n\"\n    },\n    {\n      \"children\": [\n        {\n          \"type\": 0,\n          \"value\": \"As an engineer at SIC Systems, you'll produce highly efficient programs for our flagship product: the Single Instruction Computer Mark 1 (SIC-1). You will be competing against other engineers to produce the fastest and smallest programs.\"\n        }\n      ],\n      \"type\": 8,\n      \"value\": \"p\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \"\\r\\n\"\n    },\n    {\n      \"children\": [\n        {\n          \"type\": 0,\n          \"value\": \"This is a full-time salaried role. The ideal candidate for this job will have a PhD and 15 - 20 years (or more) of industry experience, along with a relentless attention to detail and exemplary interpersonal skills. Scheduling flexibility is a plus, as we push toward our worldwide launch.\"\n        }\n      ],\n      \"type\": 8,\n      \"value\": \"p\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \"\\r\\n\"\n    },\n    {\n      \"children\": [\n        {\n          \"type\": 0,\n          \"value\": \"About SIC Systems:\"\n        }\n      ],\n      \"type\": 8,\n      \"value\": \"h3\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \"\\r\\n\"\n    },\n    {\n      \"children\": [\n        {\n          \"type\": 0,\n          \"value\": \"SIC Systems is the world leader in single-instruction computing. Our mission is to simplify computation, and thus simplify the world. We are innovative, trustworthy, and ethical.\"\n        }\n      ],\n      \"type\": 8,\n      \"value\": \"p\"\n    }\n  ],\n  \"introApplyButton\": [\n    {\n      \"type\": 0,\n      \"value\": \"Apply for the Job\"\n    }\n  ],\n  \"introApplyInvitation\": [\n    {\n      \"type\": 0,\n      \"value\": \"After completing the form above, click the button below to submit your job application:\"\n    }\n  ],\n  \"introApplyLabel\": [\n    {\n      \"type\": 0,\n      \"value\": \"Click the button below to submit your job application:\"\n    }\n  ],\n  \"introHeaderJobApplication\": [\n    {\n      \"type\": 0,\n      \"value\": \"Job Application:\"\n    }\n  ],\n  \"introLabelName\": [\n    {\n      \"type\": 0,\n      \"value\": \"Name:\"\n    }\n  ],\n  \"ioTypeCharacters\": [\n    {\n      \"type\": 0,\n      \"value\": \"Characters\"\n    }\n  ],\n  \"ioTypeNumbers\": [\n    {\n      \"type\": 0,\n      \"value\": \"Numbers\"\n    }\n  ],\n  \"ioTypeStrings\": [\n    {\n      \"type\": 0,\n      \"value\": \"Strings\"\n    }\n  ],\n  \"jobTitle0\": [\n    {\n      \"type\": 0,\n      \"value\": \"Trainee\"\n    }\n  ],\n  \"jobTitle1\": [\n    {\n      \"type\": 0,\n      \"value\": \"Engineer\"\n    }\n  ],\n  \"jobTitle2\": [\n    {\n      \"type\": 0,\n      \"value\": \"Engineer II\"\n    }\n  ],\n  \"jobTitle3\": [\n    {\n      \"type\": 0,\n      \"value\": \"Senior Engineer\"\n    }\n  ],\n  \"jobTitle4\": [\n    {\n      \"type\": 0,\n      \"value\": \"Principal Engineer\"\n    }\n  ],\n  \"jobTitle5\": [\n    {\n      \"type\": 0,\n      \"value\": \"Partner Engineer\"\n    }\n  ],\n  \"jobTitle6\": [\n    {\n      \"type\": 0,\n      \"value\": \"Distinguished Engineer\"\n    }\n  ],\n  \"jobTitle7\": [\n    {\n      \"type\": 0,\n      \"value\": \"Technical Fellow\"\n    }\n  ],\n  \"jobTitle8\": [\n    {\n      \"type\": 0,\n      \"value\": \"Technical Fellow Emeritus\"\n    }\n  ],\n  \"labelStateBytes\": [\n    {\n      \"type\": 0,\n      \"value\": \"Bytes\"\n    }\n  ],\n  \"labelStateCycles\": [\n    {\n      \"type\": 0,\n      \"value\": \"Cycles\"\n    }\n  ],\n  \"labelStateRunning\": [\n    {\n      \"type\": 0,\n      \"value\": \"State\"\n    }\n  ],\n  \"labelWatchedAddress\": [\n    {\n      \"type\": 0,\n      \"value\": \"Address \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"address\"\n    }\n  ],\n  \"languageDefault\": [\n    {\n      \"type\": 0,\n      \"value\": \"Default (\"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"defaultLanguage\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \")\"\n    }\n  ],\n  \"languageName\": [\n    {\n      \"type\": 0,\n      \"value\": \"English\"\n    }\n  ],\n  \"languageOption\": [\n    {\n      \"type\": 1,\n      \"value\": \"name\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" (\"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"locale\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \")\"\n    }\n  ],\n  \"loadFailed\": [\n    {\n      \"type\": 0,\n      \"value\": \"(load failed)\"\n    }\n  ],\n  \"loading\": [\n    {\n      \"type\": 0,\n      \"value\": \"(loading...)\"\n    }\n  ],\n  \"mailViewerButtonContinueEditing\": [\n    {\n      \"type\": 0,\n      \"value\": \"Continue Editing Current Program\"\n    }\n  ],\n  \"mailViewerButtonCredits\": [\n    {\n      \"type\": 0,\n      \"value\": \"View Credits\"\n    }\n  ],\n  \"mailViewerButtonNextTask\": [\n    {\n      \"type\": 0,\n      \"value\": \"View Next Task\"\n    }\n  ],\n  \"mailViewerButtonOpenManual\": [\n    {\n      \"type\": 0,\n      \"value\": \"Open Manual In-Game\"\n    }\n  ],\n  \"mailViewerButtonOpenManualNewWindow\": [\n    {\n      \"type\": 0,\n      \"value\": \"Open Manual Here\"\n    }\n  ],\n  \"mailViewerButtonSandbox\": [\n    {\n      \"type\": 0,\n      \"value\": \"View Sandbox Mode\"\n    }\n  ],\n  \"mailViewerButtonViewTask\": [\n    {\n      \"type\": 0,\n      \"value\": \"View \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"taskName\"\n    }\n  ],\n  \"mailViewerExtraToLineIndent\": [\n    {\n      \"type\": 1,\n      \"value\": \"nbsp\"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"nbsp\"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"nbsp\"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"nbsp\"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"nbsp\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" \"\n    }\n  ],\n  \"mailViewerGroupUnread\": [\n    {\n      \"type\": 0,\n      \"value\": \"Unread Mail\"\n    }\n  ],\n  \"mailViewerHeadingRead\": [\n    {\n      \"type\": 0,\n      \"value\": \"Read Mail\"\n    }\n  ],\n  \"mailViewerHeadingUnread\": [\n    {\n      \"type\": 0,\n      \"value\": \"Inbox\"\n    }\n  ],\n  \"mailViewerMailHeading\": [\n    {\n      \"children\": [\n        {\n          \"type\": 0,\n          \"value\": \"To\"\n        }\n      ],\n      \"type\": 8,\n      \"value\": \"cap\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \":\"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"nbsp\"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"nbsp\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"to\"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"newline\"\n    },\n    {\n      \"children\": [\n        {\n          \"type\": 0,\n          \"value\": \"From\"\n        }\n      ],\n      \"type\": 8,\n      \"value\": \"cap\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \": \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"from\"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"newline\"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"newline\"\n    },\n    {\n      \"children\": [\n        {\n          \"type\": 0,\n          \"value\": \"Subject\"\n        }\n      ],\n      \"type\": 8,\n      \"value\": \"cap\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \": \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"subject\"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"newline\"\n    }\n  ],\n  \"mailViewerTaskCompleted\": [\n    {\n      \"type\": 0,\n      \"value\": \"Well done! Your program produced the correct output. Thanks for your contribution to SIC Systems!\"\n    }\n  ],\n  \"mailViewerTaskSubject\": [\n    {\n      \"type\": 0,\n      \"value\": \"RE: \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"taskName\"\n    }\n  ],\n  \"mailViewerViewNextUnread\": [\n    {\n      \"type\": 0,\n      \"value\": \"View Next Unread Mail\"\n    }\n  ],\n  \"mails0_0Content\": [\n    {\n      \"children\": [\n        {\n          \"type\": 0,\n          \"value\": \"Single Instruction Computer Mark 1 (SIC-1)\"\n        }\n      ],\n      \"type\": 8,\n      \"value\": \"h3\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \"\\n\"\n    },\n    {\n      \"children\": [\n        {\n          \"type\": 0,\n          \"value\": \"The Single Instruction Computer Mark 1 (SIC-1) is an 8-bit computer with 256 bytes of memory. Programs for the SIC-1 are written in SIC-1 Assembly Language, as described below.\"\n        }\n      ],\n      \"type\": 8,\n      \"value\": \"p\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \"\\n\"\n    },\n    {\n      \"children\": [\n        {\n          \"children\": [\n            {\n              \"type\": 0,\n              \"value\": \"subleq\"\n            }\n          ],\n          \"type\": 8,\n          \"value\": \"code\"\n        },\n        {\n          \"type\": 0,\n          \"value\": \" instruction\"\n        }\n      ],\n      \"type\": 8,\n      \"value\": \"h3\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \"\\n\"\n    },\n    {\n      \"children\": [\n        {\n          \"type\": 0,\n          \"value\": \"Each \"\n        },\n        {\n          \"children\": [\n            {\n              \"type\": 0,\n              \"value\": \"subleq\"\n            }\n          ],\n          \"type\": 8,\n          \"value\": \"code\"\n        },\n        {\n          \"type\": 0,\n          \"value\": \" instruction is 3 bytes, specified as follows:\"\n        }\n      ],\n      \"type\": 8,\n      \"value\": \"p\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \"\\n\"\n    },\n    {\n      \"children\": [\n        {\n          \"children\": [\n            {\n              \"type\": 0,\n              \"value\": \"subleq A B [C]\\n\"\n            }\n          ],\n          \"type\": 8,\n          \"value\": \"code\"\n        }\n      ],\n      \"type\": 8,\n      \"value\": \"pre\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \"\\n\"\n    },\n    {\n      \"children\": [\n        {\n          \"children\": [\n            {\n              \"type\": 0,\n              \"value\": \"A\"\n            }\n          ],\n          \"type\": 8,\n          \"value\": \"code\"\n        },\n        {\n          \"type\": 0,\n          \"value\": \", \"\n        },\n        {\n          \"children\": [\n            {\n              \"type\": 0,\n              \"value\": \"B\"\n            }\n          ],\n          \"type\": 8,\n          \"value\": \"code\"\n        },\n        {\n          \"type\": 0,\n          \"value\": \", and \"\n        },\n        {\n          \"children\": [\n            {\n              \"type\": 0,\n              \"value\": \"C\"\n            }\n          ],\n          \"type\": 8,\n          \"value\": \"code\"\n        },\n        {\n          \"type\": 0,\n          \"value\": \" are memory addresses (0 - 255) or labels.\"\n        }\n      ],\n      \"type\": 8,\n      \"value\": \"p\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \"\\n\"\n    },\n    {\n      \"children\": [\n        {\n          \"children\": [\n            {\n              \"type\": 0,\n              \"value\": \"subleq\"\n            }\n          ],\n          \"type\": 8,\n          \"value\": \"code\"\n        },\n        {\n          \"type\": 0,\n          \"value\": \" subtracts the value at address \"\n        },\n        {\n          \"children\": [\n            {\n              \"type\": 0,\n              \"value\": \"B\"\n            }\n          ],\n          \"type\": 8,\n          \"value\": \"code\"\n        },\n        {\n          \"type\": 0,\n          \"value\": \" from the value at address \"\n        },\n        {\n          \"children\": [\n            {\n              \"type\": 0,\n              \"value\": \"A\"\n            }\n          ],\n          \"type\": 8,\n          \"value\": \"code\"\n        },\n        {\n          \"type\": 0,\n          \"value\": \" and stores the result at address \"\n        },\n        {\n          \"children\": [\n            {\n              \"type\": 0,\n              \"value\": \"A\"\n            }\n          ],\n          \"type\": 8,\n          \"value\": \"code\"\n        },\n        {\n          \"type\": 0,\n          \"value\": \" (i.e. \"\n        },\n        {\n          \"children\": [\n            {\n              \"type\": 0,\n              \"value\": \"mem[A]\"\n            }\n          ],\n          \"type\": 8,\n          \"value\": \"code\"\n        },\n        {\n          \"type\": 0,\n          \"value\": \" is set to \"\n        },\n        {\n          \"children\": [\n            {\n              \"type\": 0,\n              \"value\": \"mem[A] - mem[B]\"\n            }\n          ],\n          \"type\": 8,\n          \"value\": \"code\"\n        },\n        {\n          \"type\": 0,\n          \"value\": \").\"\n        }\n      ],\n      \"type\": 8,\n      \"value\": \"p\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \"\\n\"\n    },\n    {\n      \"children\": [\n        {\n          \"type\": 0,\n          \"value\": \"If the result is ≤ 0, execution branches to address \"\n        },\n        {\n          \"children\": [\n            {\n              \"type\": 0,\n              \"value\": \"C\"\n            }\n          ],\n          \"type\": 8,\n          \"value\": \"code\"\n        },\n        {\n          \"type\": 0,\n          \"value\": \".\"\n        }\n      ],\n      \"type\": 8,\n      \"value\": \"p\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \"\\n\"\n    },\n    {\n      \"children\": [\n        {\n          \"type\": 0,\n          \"value\": \"Note that if \"\n        },\n        {\n          \"children\": [\n            {\n              \"type\": 0,\n              \"value\": \"C\"\n            }\n          ],\n          \"type\": 8,\n          \"value\": \"code\"\n        },\n        {\n          \"type\": 0,\n          \"value\": \" is not specified, the address of the next instruction is automatically added by the assembler (in effect, this means that taking the branch is no different from advancing to the next instruction).\"\n        }\n      ],\n      \"type\": 8,\n      \"value\": \"p\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \"\\n\"\n    },\n    {\n      \"children\": [\n        {\n          \"type\": 0,\n          \"value\": \"Built-in addresses\"\n        }\n      ],\n      \"type\": 8,\n      \"value\": \"h3\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \"\\n\"\n    },\n    {\n      \"children\": [\n        {\n          \"type\": 0,\n          \"value\": \"For convenience, addresses can be specified using labels. The following predefined labels are always available:\"\n        }\n      ],\n      \"type\": 8,\n      \"value\": \"p\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \"\\n\"\n    },\n    {\n      \"children\": [\n        {\n          \"type\": 0,\n          \"value\": \"\\n\"\n        },\n        {\n          \"children\": [\n            {\n              \"children\": [\n                {\n                  \"type\": 0,\n                  \"value\": \"@MAX\"\n                }\n              ],\n              \"type\": 8,\n              \"value\": \"code\"\n            },\n            {\n              \"type\": 0,\n              \"value\": \" (252): Maximum user-modifiable address\"\n            }\n          ],\n          \"type\": 8,\n          \"value\": \"li\"\n        },\n        {\n          \"type\": 0,\n          \"value\": \"\\n\"\n        },\n        {\n          \"children\": [\n            {\n              \"children\": [\n                {\n                  \"type\": 0,\n                  \"value\": \"@IN\"\n                }\n              ],\n              \"type\": 8,\n              \"value\": \"code\"\n            },\n            {\n              \"type\": 0,\n              \"value\": \" (253): Reads a value from input (writes are ignored)\"\n            }\n          ],\n          \"type\": 8,\n          \"value\": \"li\"\n        },\n        {\n          \"type\": 0,\n          \"value\": \"\\n\"\n        },\n        {\n          \"children\": [\n            {\n              \"children\": [\n                {\n                  \"type\": 0,\n                  \"value\": \"@OUT\"\n                }\n              ],\n              \"type\": 8,\n              \"value\": \"code\"\n            },\n            {\n              \"type\": 0,\n              \"value\": \" (254): Writes a result to output (reads as zero)\"\n            }\n          ],\n          \"type\": 8,\n          \"value\": \"li\"\n        },\n        {\n          \"type\": 0,\n          \"value\": \"\\n\"\n        },\n        {\n          \"children\": [\n            {\n              \"children\": [\n                {\n                  \"type\": 0,\n                  \"value\": \"@HALT\"\n                }\n              ],\n              \"type\": 8,\n              \"value\": \"code\"\n            },\n            {\n              \"type\": 0,\n              \"value\": \" (255): Terminates the program when accessed (reads and write are ignored)\"\n            }\n          ],\n          \"type\": 8,\n          \"value\": \"li\"\n        },\n        {\n          \"type\": 0,\n          \"value\": \"\\n\"\n        }\n      ],\n      \"type\": 8,\n      \"value\": \"ul\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \"\\n\"\n    },\n    {\n      \"children\": [\n        {\n          \"children\": [\n            {\n              \"type\": 0,\n              \"value\": \"subleq\"\n            }\n          ],\n          \"type\": 8,\n          \"value\": \"code\"\n        },\n        {\n          \"type\": 0,\n          \"value\": \" example\"\n        }\n      ],\n      \"type\": 8,\n      \"value\": \"h3\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \"\\n\"\n    },\n    {\n      \"children\": [\n        {\n          \"type\": 0,\n          \"value\": \"Below is a very simple SIC-1 program that negates one input value and writes it out.\"\n        }\n      ],\n      \"type\": 8,\n      \"value\": \"p\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \"\\n\"\n    },\n    {\n      \"children\": [\n        {\n          \"type\": 0,\n          \"value\": \"E.g. if the input value from \"\n        },\n        {\n          \"children\": [\n            {\n              \"type\": 0,\n              \"value\": \"@IN\"\n            }\n          ],\n          \"type\": 8,\n          \"value\": \"code\"\n        },\n        {\n          \"type\": 0,\n          \"value\": \" is 3, it subtracts 3 from \"\n        },\n        {\n          \"children\": [\n            {\n              \"type\": 0,\n              \"value\": \"@OUT\"\n            }\n          ],\n          \"type\": 8,\n          \"value\": \"code\"\n        },\n        {\n          \"type\": 0,\n          \"value\": \" (which reads as zero), and the result of 0 - 3 = -3 is written out.\"\n        }\n      ],\n      \"type\": 8,\n      \"value\": \"p\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \"\\n\"\n    },\n    {\n      \"children\": [\n        {\n          \"children\": [\n            {\n              \"type\": 0,\n              \"value\": \"subleq @OUT, @IN\\n\"\n            }\n          ],\n          \"type\": 8,\n          \"value\": \"code\"\n        }\n      ],\n      \"type\": 8,\n      \"value\": \"pre\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \"\\n\"\n    },\n    {\n      \"children\": [\n        {\n          \"type\": 0,\n          \"value\": \"Comments\"\n        }\n      ],\n      \"type\": 8,\n      \"value\": \"h3\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \"\\n\"\n    },\n    {\n      \"children\": [\n        {\n          \"type\": 0,\n          \"value\": \"Any text following a semicolon is considered a comment. Comments are ignored by the assembler, but may be helpful to humans attempting to decipher existing programs. For example, here's the previous line of assembly with an explanatory comment:\"\n        }\n      ],\n      \"type\": 8,\n      \"value\": \"p\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \"\\n\"\n    },\n    {\n      \"children\": [\n        {\n          \"children\": [\n            {\n              \"type\": 0,\n              \"value\": \"subleq @OUT, @IN ; Negates an input and writes it out\\n\"\n            }\n          ],\n          \"type\": 8,\n          \"value\": \"code\"\n        }\n      ],\n      \"type\": 8,\n      \"value\": \"pre\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \"\\n\"\n    },\n    {\n      \"children\": [\n        {\n          \"type\": 0,\n          \"value\": \"Labels\"\n        }\n      ],\n      \"type\": 8,\n      \"value\": \"h3\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \"\\n\"\n    },\n    {\n      \"children\": [\n        {\n          \"type\": 0,\n          \"value\": \"Custom labels are defined with the syntax \"\n        },\n        {\n          \"children\": [\n            {\n              \"type\": 0,\n              \"value\": \"@name:\"\n            }\n          ],\n          \"type\": 8,\n          \"value\": \"code\"\n        },\n        {\n          \"type\": 0,\n          \"value\": \", e.g.:\"\n        }\n      ],\n      \"type\": 8,\n      \"value\": \"p\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \"\\n\"\n    },\n    {\n      \"children\": [\n        {\n          \"children\": [\n            {\n              \"type\": 0,\n              \"value\": \"@loop: subleq 1, 2\\n\"\n            }\n          ],\n          \"type\": 8,\n          \"value\": \"code\"\n        }\n      ],\n      \"type\": 8,\n      \"value\": \"pre\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \"\\n\"\n    },\n    {\n      \"children\": [\n        {\n          \"type\": 0,\n          \"value\": \"Label names cannot include punctuation, symbols, or whitespace.\"\n        }\n      ],\n      \"type\": 8,\n      \"value\": \"p\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \"\\n\"\n    },\n    {\n      \"children\": [\n        {\n          \"children\": [\n            {\n              \"type\": 0,\n              \"value\": \".data\"\n            }\n          ],\n          \"type\": 8,\n          \"value\": \"code\"\n        },\n        {\n          \"type\": 0,\n          \"value\": \" directive\"\n        }\n      ],\n      \"type\": 8,\n      \"value\": \"h3\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \"\\n\"\n    },\n    {\n      \"children\": [\n        {\n          \"type\": 0,\n          \"value\": \"In addition to \"\n        },\n        {\n          \"children\": [\n            {\n              \"type\": 0,\n              \"value\": \"subleq\"\n            }\n          ],\n          \"type\": 8,\n          \"value\": \"code\"\n        },\n        {\n          \"type\": 0,\n          \"value\": \", there is an assembler directive \"\n        },\n        {\n          \"children\": [\n            {\n              \"type\": 0,\n              \"value\": \".data\"\n            }\n          ],\n          \"type\": 8,\n          \"value\": \"code\"\n        },\n        {\n          \"type\": 0,\n          \"value\": \" that sets one or more bytes of memory to specific values at compile time (note: this is not an instruction!):\"\n        }\n      ],\n      \"type\": 8,\n      \"value\": \"p\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \"\\n\"\n    },\n    {\n      \"children\": [\n        {\n          \"children\": [\n            {\n              \"type\": 0,\n              \"value\": \".data X\\n\"\n            }\n          ],\n          \"type\": 8,\n          \"value\": \"code\"\n        }\n      ],\n      \"type\": 8,\n      \"value\": \"pre\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \"\\n\"\n    },\n    {\n      \"children\": [\n        {\n          \"type\": 0,\n          \"value\": \"In the simplest case, \"\n        },\n        {\n          \"children\": [\n            {\n              \"type\": 0,\n              \"value\": \"X\"\n            }\n          ],\n          \"type\": 8,\n          \"value\": \"code\"\n        },\n        {\n          \"type\": 0,\n          \"value\": \" is a signed byte between -128 and 127 (inclusive).\"\n        }\n      ],\n      \"type\": 8,\n      \"value\": \"p\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \"\\n\"\n    },\n    {\n      \"children\": [\n        {\n          \"type\": 0,\n          \"value\": \"Multiple values can also be provided (separated by whitespace and, optionally, commas):\"\n        }\n      ],\n      \"type\": 8,\n      \"value\": \"p\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \"\\n\"\n    },\n    {\n      \"children\": [\n        {\n          \"children\": [\n            {\n              \"type\": 0,\n              \"value\": \".data 1, -2, 3\\n\"\n            }\n          ],\n          \"type\": 8,\n          \"value\": \"code\"\n        }\n      ],\n      \"type\": 8,\n      \"value\": \"pre\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \"\\n\"\n    },\n    {\n      \"children\": [\n        {\n          \"type\": 0,\n          \"value\": \"Note: labels (with optional offsets), characters, and strings--along with negations of these--can also be supplied. Examples of these appear in subsequent sections.\"\n        }\n      ],\n      \"type\": 8,\n      \"value\": \"p\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \"\\n\"\n    },\n    {\n      \"children\": [\n        {\n          \"type\": 0,\n          \"value\": \"Constants and variables\"\n        }\n      ],\n      \"type\": 8,\n      \"value\": \"h3\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \"\\n\"\n    },\n    {\n      \"children\": [\n        {\n          \"type\": 0,\n          \"value\": \"Combining labels and the \"\n        },\n        {\n          \"children\": [\n            {\n              \"type\": 0,\n              \"value\": \".data\"\n            }\n          ],\n          \"type\": 8,\n          \"value\": \"code\"\n        },\n        {\n          \"type\": 0,\n          \"value\": \" directive allows you to develop a system of constants and variables. For example, here a byte is set to zero, and the label \"\n        },\n        {\n          \"children\": [\n            {\n              \"type\": 0,\n              \"value\": \"@zero\"\n            }\n          ],\n          \"type\": 8,\n          \"value\": \"code\"\n        },\n        {\n          \"type\": 0,\n          \"value\": \" points to that value:\"\n        }\n      ],\n      \"type\": 8,\n      \"value\": \"p\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \"\\n\"\n    },\n    {\n      \"children\": [\n        {\n          \"children\": [\n            {\n              \"type\": 0,\n              \"value\": \"@zero: .data 0\\n\"\n            }\n          ],\n          \"type\": 8,\n          \"value\": \"code\"\n        }\n      ],\n      \"type\": 8,\n      \"value\": \"pre\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \"\\n\"\n    },\n    {\n      \"children\": [\n        {\n          \"type\": 0,\n          \"value\": \"Unconditional jumps\"\n        }\n      ],\n      \"type\": 8,\n      \"value\": \"h3\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \"\\n\"\n    },\n    {\n      \"children\": [\n        {\n          \"type\": 0,\n          \"value\": \"Variables can be used for implementing an unconditional jump:\"\n        }\n      ],\n      \"type\": 8,\n      \"value\": \"p\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \"\\n\"\n    },\n    {\n      \"children\": [\n        {\n          \"children\": [\n            {\n              \"type\": 0,\n              \"value\": \"subleq @zero, @zero, @next\\n\"\n            }\n          ],\n          \"type\": 8,\n          \"value\": \"code\"\n        }\n      ],\n      \"type\": 8,\n      \"value\": \"pre\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \"\\n\"\n    },\n    {\n      \"children\": [\n        {\n          \"type\": 0,\n          \"value\": \"This will set \"\n        },\n        {\n          \"children\": [\n            {\n              \"type\": 0,\n              \"value\": \"@zero\"\n            }\n          ],\n          \"type\": 8,\n          \"value\": \"code\"\n        },\n        {\n          \"type\": 0,\n          \"value\": \" to zero minus zero (still zero) and, since the result is always ≤ 0, execution always branches to the label \"\n        },\n        {\n          \"children\": [\n            {\n              \"type\": 0,\n              \"value\": \"@next\"\n            }\n          ],\n          \"type\": 8,\n          \"value\": \"code\"\n        },\n        {\n          \"type\": 0,\n          \"value\": \".\"\n        }\n      ],\n      \"type\": 8,\n      \"value\": \"p\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \"\\n\"\n    },\n    {\n      \"children\": [\n        {\n          \"type\": 0,\n          \"value\": \"Loop example\"\n        }\n      ],\n      \"type\": 8,\n      \"value\": \"h3\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \"\\n\"\n    },\n    {\n      \"children\": [\n        {\n          \"type\": 0,\n          \"value\": \"Below is an updated negation program that repeatedly negates input values and writes them out in a loop.\"\n        }\n      ],\n      \"type\": 8,\n      \"value\": \"p\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \"\\n\"\n    },\n    {\n      \"children\": [\n        {\n          \"children\": [\n            {\n              \"type\": 0,\n              \"value\": \"@loop:\\nsubleq @OUT, @IN           ; Negate an input and write it out\\nsubleq @zero, @zero, @loop ; Unconditional jump to @loop\\n\\n@zero: .data 0             ; Always zero\\n\"\n            }\n          ],\n          \"type\": 8,\n          \"value\": \"code\"\n        }\n      ],\n      \"type\": 8,\n      \"value\": \"pre\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \"\\n\"\n    },\n    {\n      \"children\": [\n        {\n          \"type\": 0,\n          \"value\": \"Label offsets\"\n        }\n      ],\n      \"type\": 8,\n      \"value\": \"h3\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \"\\n\"\n    },\n    {\n      \"children\": [\n        {\n          \"type\": 0,\n          \"value\": \"Label expressions can include an optional offset. For example, \"\n        },\n        {\n          \"children\": [\n            {\n              \"type\": 0,\n              \"value\": \"@loop+1\"\n            }\n          ],\n          \"type\": 8,\n          \"value\": \"code\"\n        },\n        {\n          \"type\": 0,\n          \"value\": \" refers to the \"\n        },\n        {\n          \"children\": [\n            {\n              \"type\": 0,\n              \"value\": \"second\"\n            }\n          ],\n          \"type\": 8,\n          \"value\": \"em\"\n        },\n        {\n          \"type\": 0,\n          \"value\": \" byte of the instruction pointed to by \"\n        },\n        {\n          \"children\": [\n            {\n              \"type\": 0,\n              \"value\": \"@loop\"\n            }\n          ],\n          \"type\": 8,\n          \"value\": \"code\"\n        },\n        {\n          \"type\": 0,\n          \"value\": \":\"\n        }\n      ],\n      \"type\": 8,\n      \"value\": \"p\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \"\\n\"\n    },\n    {\n      \"children\": [\n        {\n          \"children\": [\n            {\n              \"type\": 0,\n              \"value\": \"@loop:\\nsubleq @loop+1, @one\\n\"\n            }\n          ],\n          \"type\": 8,\n          \"value\": \"code\"\n        }\n      ],\n      \"type\": 8,\n      \"value\": \"pre\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \"\\n\"\n    },\n    {\n      \"children\": [\n        {\n          \"type\": 0,\n          \"value\": \"Note: in certain cases (usually involving self-modifying code), it is useful to store the address associated with a label (possibly with an offset) in a byte of memory. Here is an example of how to set a byte of memory to the address of \"\n        },\n        {\n          \"children\": [\n            {\n              \"type\": 0,\n              \"value\": \"@loop+1\"\n            }\n          ],\n          \"type\": 8,\n          \"value\": \"code\"\n        },\n        {\n          \"type\": 0,\n          \"value\": \" (i.e. the \"\n        },\n        {\n          \"children\": [\n            {\n              \"type\": 0,\n              \"value\": \"second\"\n            }\n          ],\n          \"type\": 8,\n          \"value\": \"em\"\n        },\n        {\n          \"type\": 0,\n          \"value\": \" byte of the instruction at \"\n        },\n        {\n          \"children\": [\n            {\n              \"type\": 0,\n              \"value\": \"@loop\"\n            }\n          ],\n          \"type\": 8,\n          \"value\": \"code\"\n        },\n        {\n          \"type\": 0,\n          \"value\": \"):\"\n        }\n      ],\n      \"type\": 8,\n      \"value\": \"p\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \"\\n\"\n    },\n    {\n      \"children\": [\n        {\n          \"children\": [\n            {\n              \"type\": 0,\n              \"value\": \"; Address of the second byte of @loop\\n@loop_plus_one: .data @loop+1\\n\"\n            }\n          ],\n          \"type\": 8,\n          \"value\": \"code\"\n        }\n      ],\n      \"type\": 8,\n      \"value\": \"pre\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \"\\n\"\n    },\n    {\n      \"children\": [\n        {\n          \"type\": 0,\n          \"value\": \"It is possible to negate labels as well by prefixing them with a minus sign. Keep in mind that this only negates the label's address itself, so if a label with an offset needs to be negated, both the label \"\n        },\n        {\n          \"children\": [\n            {\n              \"type\": 0,\n              \"value\": \"and the offset\"\n            }\n          ],\n          \"type\": 8,\n          \"value\": \"em\"\n        },\n        {\n          \"type\": 0,\n          \"value\": \" should be negated. Here's the negation of the previous example:\"\n        }\n      ],\n      \"type\": 8,\n      \"value\": \"p\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \"\\n\"\n    },\n    {\n      \"children\": [\n        {\n          \"children\": [\n            {\n              \"type\": 0,\n              \"value\": \"; Negation of @loop+1\\n@n_loop_plus_one: .data -@loop-1\\n\"\n            }\n          ],\n          \"type\": 8,\n          \"value\": \"code\"\n        }\n      ],\n      \"type\": 8,\n      \"value\": \"pre\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \"\\n\"\n    },\n    {\n      \"children\": [\n        {\n          \"type\": 0,\n          \"value\": \"Inline labels\"\n        }\n      ],\n      \"type\": 8,\n      \"value\": \"h3\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \"\\n\"\n    },\n    {\n      \"children\": [\n        {\n          \"type\": 0,\n          \"value\": \"As an alternative to offsets, labels can be defined inline. For example \"\n        },\n        {\n          \"children\": [\n            {\n              \"type\": 0,\n              \"value\": \"@source\"\n            }\n          ],\n          \"type\": 8,\n          \"value\": \"code\"\n        },\n        {\n          \"type\": 0,\n          \"value\": \" refers to the \"\n        },\n        {\n          \"children\": [\n            {\n              \"type\": 0,\n              \"value\": \"second\"\n            }\n          ],\n          \"type\": 8,\n          \"value\": \"em\"\n        },\n        {\n          \"type\": 0,\n          \"value\": \" byte of the following instruction:\"\n        }\n      ],\n      \"type\": 8,\n      \"value\": \"p\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \"\\n\"\n    },\n    {\n      \"children\": [\n        {\n          \"children\": [\n            {\n              \"type\": 0,\n              \"value\": \"subleq 0, @source:1\\n\"\n            }\n          ],\n          \"type\": 8,\n          \"value\": \"code\"\n        }\n      ],\n      \"type\": 8,\n      \"value\": \"pre\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \"\\n\"\n    },\n    {\n      \"children\": [\n        {\n          \"type\": 0,\n          \"value\": \"Reflection example\"\n        }\n      ],\n      \"type\": 8,\n      \"value\": \"h3\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \"\\n\"\n    },\n    {\n      \"children\": [\n        {\n          \"type\": 0,\n          \"value\": \"Label offsets and inline labels are useful in self-modifying code. Remember, each \"\n        },\n        {\n          \"children\": [\n            {\n              \"type\": 0,\n              \"value\": \"subleq\"\n            }\n          ],\n          \"type\": 8,\n          \"value\": \"code\"\n        },\n        {\n          \"type\": 0,\n          \"value\": \" instruction is stored as 3 consecutive addresses: \"\n        },\n        {\n          \"children\": [\n            {\n              \"type\": 0,\n              \"value\": \"ABC\"\n            }\n          ],\n          \"type\": 8,\n          \"value\": \"code\"\n        },\n        {\n          \"type\": 0,\n          \"value\": \" (for \"\n        },\n        {\n          \"children\": [\n            {\n              \"type\": 0,\n              \"value\": \"mem[A] ← mem[A] - mem[B]\"\n            }\n          ],\n          \"type\": 8,\n          \"value\": \"code\"\n        },\n        {\n          \"type\": 0,\n          \"value\": \", with a branch to \"\n        },\n        {\n          \"children\": [\n            {\n              \"type\": 0,\n              \"value\": \"C\"\n            }\n          ],\n          \"type\": 8,\n          \"value\": \"code\"\n        },\n        {\n          \"type\": 0,\n          \"value\": \" if the result is less than or equal to zero).\"\n        }\n      ],\n      \"type\": 8,\n      \"value\": \"p\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \"\\n\"\n    },\n    {\n      \"children\": [\n        {\n          \"type\": 0,\n          \"value\": \"The sample program below reads its own compiled code and outputs it by incrementing the second address of the instruction at \"\n        },\n        {\n          \"children\": [\n            {\n              \"type\": 0,\n              \"value\": \"@loop\"\n            }\n          ],\n          \"type\": 8,\n          \"value\": \"code\"\n        },\n        {\n          \"type\": 0,\n          \"value\": \" (i.e. modifying address \"\n        },\n        {\n          \"children\": [\n            {\n              \"type\": 0,\n              \"value\": \"@loop+1\"\n            }\n          ],\n          \"type\": 8,\n          \"value\": \"code\"\n        },\n        {\n          \"type\": 0,\n          \"value\": \").\"\n        }\n      ],\n      \"type\": 8,\n      \"value\": \"p\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \"\\n\"\n    },\n    {\n      \"children\": [\n        {\n          \"children\": [\n            {\n              \"type\": 0,\n              \"value\": \"@loop:\\nsubleq @tmp, 0           ; Second address (initially zero) will be incremented below\\nsubleq @OUT, @tmp        ; Output the value\\nsubleq @loop+1, @n_one   ; Here is where the increment is performed\\nsubleq @tmp, @tmp, @loop ; Reset @tmp to zero and unconditionally jump to @loop\\n\\n@tmp: .data 0            ; @tmp is initialized to zero\\n@n_one: .data -1\\n\"\n            }\n          ],\n          \"type\": 8,\n          \"value\": \"code\"\n        }\n      ],\n      \"type\": 8,\n      \"value\": \"pre\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \"\\n\"\n    },\n    {\n      \"children\": [\n        {\n          \"type\": 0,\n          \"value\": \"The third instruction is an example of self-modifying code because it actually modifies the first instruction. Specifically, it increments the first instruction's second address (\"\n        },\n        {\n          \"children\": [\n            {\n              \"type\": 0,\n              \"value\": \"@loop+1\"\n            }\n          ],\n          \"type\": 8,\n          \"value\": \"code\"\n        },\n        {\n          \"type\": 0,\n          \"value\": \"). This causes the \"\n        },\n        {\n          \"children\": [\n            {\n              \"type\": 0,\n              \"value\": \"next\"\n            }\n          ],\n          \"type\": 8,\n          \"value\": \"em\"\n        },\n        {\n          \"type\": 0,\n          \"value\": \" loop iteration's first instruction to read the \"\n        },\n        {\n          \"children\": [\n            {\n              \"type\": 0,\n              \"value\": \"next\"\n            }\n          ],\n          \"type\": 8,\n          \"value\": \"em\"\n        },\n        {\n          \"type\": 0,\n          \"value\": \" byte of memory (0, 1, 2, 3, ...).\"\n        }\n      ],\n      \"type\": 8,\n      \"value\": \"p\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \"\\n\"\n    },\n    {\n      \"children\": [\n        {\n          \"type\": 0,\n          \"value\": \"The program above used a label with an offset, but it could have just as easily been written using an inline label (e.g. defining a \"\n        },\n        {\n          \"children\": [\n            {\n              \"type\": 0,\n              \"value\": \"new\"\n            }\n          ],\n          \"type\": 8,\n          \"value\": \"em\"\n        },\n        {\n          \"type\": 0,\n          \"value\": \" label, \"\n        },\n        {\n          \"children\": [\n            {\n              \"type\": 0,\n              \"value\": \"subleq @tmp, @source:0\"\n            }\n          ],\n          \"type\": 8,\n          \"value\": \"code\"\n        },\n        {\n          \"type\": 0,\n          \"value\": \", and referring to \"\n        },\n        {\n          \"children\": [\n            {\n              \"type\": 0,\n              \"value\": \"@source\"\n            }\n          ],\n          \"type\": 8,\n          \"value\": \"code\"\n        },\n        {\n          \"type\": 0,\n          \"value\": \" instead of \"\n        },\n        {\n          \"children\": [\n            {\n              \"type\": 0,\n              \"value\": \"@loop+1\"\n            }\n          ],\n          \"type\": 8,\n          \"value\": \"code\"\n        },\n        {\n          \"type\": 0,\n          \"value\": \"). Both approaches compile down to the same sequence of bytes.\"\n        }\n      ],\n      \"type\": 8,\n      \"value\": \"p\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \"\\n\"\n    },\n    {\n      \"children\": [\n        {\n          \"type\": 0,\n          \"value\": \"Note: When running a program in the SIC-1 Development Environment, the original (unmodified) source code is always shown. If the program modifies itself, the changes are reflected in the memory table in the top right, but \"\n        },\n        {\n          \"children\": [\n            {\n              \"type\": 0,\n              \"value\": \"not\"\n            }\n          ],\n          \"type\": 8,\n          \"value\": \"em\"\n        },\n        {\n          \"type\": 0,\n          \"value\": \" in the source code viewer.\"\n        }\n      ],\n      \"type\": 8,\n      \"value\": \"p\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \"\\n\"\n    },\n    {\n      \"children\": [\n        {\n          \"type\": 0,\n          \"value\": \"Stack example\"\n        }\n      ],\n      \"type\": 8,\n      \"value\": \"h3\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \"\\n\"\n    },\n    {\n      \"children\": [\n        {\n          \"type\": 0,\n          \"value\": \"This program implements a last-in, first-out stack by modifying the read and write addresses of the instructions that interact with the stack.\"\n        }\n      ],\n      \"type\": 8,\n      \"value\": \"p\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \"\\n\"\n    },\n    {\n      \"children\": [\n        {\n          \"type\": 0,\n          \"value\": \"The program pushes 3 (defined by \"\n        },\n        {\n          \"children\": [\n            {\n              \"type\": 0,\n              \"value\": \"@count\"\n            }\n          ],\n          \"type\": 8,\n          \"value\": \"code\"\n        },\n        {\n          \"type\": 0,\n          \"value\": \") input values onto the stack and then pops them off (outputting them in reverse order).\"\n        }\n      ],\n      \"type\": 8,\n      \"value\": \"p\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \"\\n\"\n    },\n    {\n      \"children\": [\n        {\n          \"children\": [\n            {\n              \"type\": 0,\n              \"value\": \"; The first address of this instruction (which starts\\n; pointing to @stack) will be incremented with each\\n; write to the stack\\n@stack_push:\\nsubleq @stack, @IN\\nsubleq @count, @one, @prepare_to_pop\\n\\n; Modify the instruction at @stack_push (increment\\n; target address)\\nsubleq @stack_push, @n_one\\nsubleq @tmp, @tmp, @stack_push\\n\\n; Prepare to start popping values off of the stack by\\n; copying the current stack position to @stack_pop+1\\n@prepare_to_pop:\\nsubleq @tmp, @stack_push\\nsubleq @stack_pop+1, @tmp\\n\\n; Read a value from the stack (note: the second address\\n; of this instruction is repeatedly decremented)\\n@stack_pop:\\nsubleq @OUT, 0\\n\\n; Decrement stack address in the instruction at @stack_pop\\nsubleq @stack_pop+1, @one\\nsubleq @tmp, @tmp, @stack_pop\\n\\n; Constants\\n@one: .data 1\\n@n_one: .data -1\\n\\n; Variables\\n@tmp: .data 0\\n@count: .data 3\\n\\n; Base of stack (stack will grow upwards)\\n@stack: .data 0\\n\"\n            }\n          ],\n          \"type\": 8,\n          \"value\": \"code\"\n        }\n      ],\n      \"type\": 8,\n      \"value\": \"pre\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \"\\n\"\n    },\n    {\n      \"children\": [\n        {\n          \"type\": 0,\n          \"value\": \"Characters\"\n        }\n      ],\n      \"type\": 8,\n      \"value\": \"h3\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \"\\n\"\n    },\n    {\n      \"children\": [\n        {\n          \"type\": 0,\n          \"value\": \"When configured properly, the SIC-1 supports natural human language input and output using a highly modern (c. 1967) mapping from numbers to characters known as ASCII. For example, 72 is mapped to \\\"H\\\" (capital \\\"h\\\").\"\n        }\n      ],\n      \"type\": 8,\n      \"value\": \"p\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \"\\n\"\n    },\n    {\n      \"children\": [\n        {\n          \"type\": 0,\n          \"value\": \"To capture the characters \\\"Hi\\\" (capital \\\"h\\\", lower case \\\"i\\\") in two variables, one could consult an ASCII lookup table and write:\"\n        }\n      ],\n      \"type\": 8,\n      \"value\": \"p\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \"\\n\"\n    },\n    {\n      \"children\": [\n        {\n          \"children\": [\n            {\n              \"type\": 0,\n              \"value\": \"@H: .data 72\\n@i: .data 105\\n\"\n            }\n          ],\n          \"type\": 8,\n          \"value\": \"code\"\n        }\n      ],\n      \"type\": 8,\n      \"value\": \"pre\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \"\\n\"\n    },\n    {\n      \"children\": [\n        {\n          \"type\": 0,\n          \"value\": \"Consulting an ASCII table is tedious, so to make SIC Systems engineers' lives easier, SIC-1 Assembly Language now supports automated ASCII lookup using the following advanced syntax (which is equivalent to explicitly specifying characters' mapped numbers):\"\n        }\n      ],\n      \"type\": 8,\n      \"value\": \"p\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \"\\n\"\n    },\n    {\n      \"children\": [\n        {\n          \"children\": [\n            {\n              \"type\": 0,\n              \"value\": \"@H: .data 'H' ; 72\\n@i: .data 'i' ; 105\\n\"\n            }\n          ],\n          \"type\": 8,\n          \"value\": \"code\"\n        }\n      ],\n      \"type\": 8,\n      \"value\": \"pre\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \"\\n\"\n    },\n    {\n      \"children\": [\n        {\n          \"type\": 0,\n          \"value\": \"As a final convenience, it is possible to negate the value of a character by prefixing the character literal with a minus:\"\n        }\n      ],\n      \"type\": 8,\n      \"value\": \"p\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \"\\n\"\n    },\n    {\n      \"children\": [\n        {\n          \"children\": [\n            {\n              \"type\": 0,\n              \"value\": \"@n_H: .data -'H' ; -72\\n\"\n            }\n          ],\n          \"type\": 8,\n          \"value\": \"code\"\n        }\n      ],\n      \"type\": 8,\n      \"value\": \"pre\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \"\\n\"\n    },\n    {\n      \"children\": [\n        {\n          \"type\": 0,\n          \"value\": \"Character output example\"\n        }\n      ],\n      \"type\": 8,\n      \"value\": \"h3\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \"\\n\"\n    },\n    {\n      \"children\": [\n        {\n          \"type\": 0,\n          \"value\": \"The following sample program outputs the characters \\\"Hi\\\":\"\n        }\n      ],\n      \"type\": 8,\n      \"value\": \"p\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \"\\n\"\n    },\n    {\n      \"children\": [\n        {\n          \"children\": [\n            {\n              \"type\": 0,\n              \"value\": \"subleq @OUT, @n_H ; Note: (0 - (-72) = 72 = 'H')\\nsubleq @OUT, @n_i\\n\\n@n_H: .data -'H'\\n@n_i: .data -'i'\\n\"\n            }\n          ],\n          \"type\": 8,\n          \"value\": \"code\"\n        }\n      ],\n      \"type\": 8,\n      \"value\": \"pre\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \"\\n\"\n    },\n    {\n      \"children\": [\n        {\n          \"type\": 0,\n          \"value\": \"Strings\"\n        }\n      ],\n      \"type\": 8,\n      \"value\": \"h3\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \"\\n\"\n    },\n    {\n      \"children\": [\n        {\n          \"type\": 0,\n          \"value\": \"Strings are sequences of characters that are terminated with a zero. In the following example, @string points to a 3 byte sequence representing the string \\\"Hi\\\":\"\n        }\n      ],\n      \"type\": 8,\n      \"value\": \"p\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \"\\n\"\n    },\n    {\n      \"children\": [\n        {\n          \"children\": [\n            {\n              \"type\": 0,\n              \"value\": \"@string:\\n.data 'H'\\n.data 'i'\\n.data 0\\n\"\n            }\n          ],\n          \"type\": 8,\n          \"value\": \"code\"\n        }\n      ],\n      \"type\": 8,\n      \"value\": \"pre\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \"\\n\"\n    },\n    {\n      \"children\": [\n        {\n          \"type\": 0,\n          \"value\": \"The .data directive can also take a sequence of values to set multiple bytes, so the previous code would be simplified:\"\n        }\n      ],\n      \"type\": 8,\n      \"value\": \"p\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \"\\n\"\n    },\n    {\n      \"children\": [\n        {\n          \"children\": [\n            {\n              \"type\": 0,\n              \"value\": \"@string: .data 'H', 'i', 0\\n\"\n            }\n          ],\n          \"type\": 8,\n          \"value\": \"code\"\n        }\n      ],\n      \"type\": 8,\n      \"value\": \"pre\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \"\\n\"\n    },\n    {\n      \"children\": [\n        {\n          \"type\": 0,\n          \"value\": \"And thanks to the innovative design-by-committee approach employed by SIC Systems, the following novel syntax for strings can be used (again, equivalent to the other examples):\"\n        }\n      ],\n      \"type\": 8,\n      \"value\": \"p\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \"\\n\"\n    },\n    {\n      \"children\": [\n        {\n          \"children\": [\n            {\n              \"type\": 0,\n              \"value\": \"@string: .data \\\"Hi\\\" ; Sets the next 3 bytes: 'H', 'i', 0\\n\"\n            }\n          ],\n          \"type\": 8,\n          \"value\": \"code\"\n        }\n      ],\n      \"type\": 8,\n      \"value\": \"pre\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \"\\n\"\n    },\n    {\n      \"children\": [\n        {\n          \"type\": 0,\n          \"value\": \"Similar to character values, an entire string can be negated by prefixing it with a minus:\"\n        }\n      ],\n      \"type\": 8,\n      \"value\": \"p\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \"\\n\"\n    },\n    {\n      \"children\": [\n        {\n          \"children\": [\n            {\n              \"type\": 0,\n              \"value\": \"@n_string: .data -\\\"Hi\\\" ; Sets the next 3 bytes: -72, -105, 0\\n\"\n            }\n          ],\n          \"type\": 8,\n          \"value\": \"code\"\n        }\n      ],\n      \"type\": 8,\n      \"value\": \"pre\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \"\\n\"\n    },\n    {\n      \"children\": [\n        {\n          \"type\": 0,\n          \"value\": \"New line characters\"\n        }\n      ],\n      \"type\": 8,\n      \"value\": \"h3\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \"\\n\"\n    },\n    {\n      \"children\": [\n        {\n          \"type\": 0,\n          \"value\": \"New line characters (value 10) can be expressed with the character \"\n        },\n        {\n          \"children\": [\n            {\n              \"type\": 0,\n              \"value\": \"'\\\\n'\"\n            }\n          ],\n          \"type\": 8,\n          \"value\": \"code\"\n        },\n        {\n          \"type\": 0,\n          \"value\": \". They can also be used in strings, for example: \"\n        },\n        {\n          \"children\": [\n            {\n              \"type\": 0,\n              \"value\": \"\\\"Line 1\\\\nLine 2\\\"\"\n            }\n          ],\n          \"type\": 8,\n          \"value\": \"code\"\n        },\n        {\n          \"type\": 0,\n          \"value\": \".\"\n        }\n      ],\n      \"type\": 8,\n      \"value\": \"p\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \"\\n\"\n    },\n    {\n      \"children\": [\n        {\n          \"type\": 0,\n          \"value\": \"String output example\"\n        }\n      ],\n      \"type\": 8,\n      \"value\": \"h3\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \"\\n\"\n    },\n    {\n      \"children\": [\n        {\n          \"type\": 0,\n          \"value\": \"The following code outputs \\\"Hello, world!\\\":\"\n        }\n      ],\n      \"type\": 8,\n      \"value\": \"p\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \"\\n\"\n    },\n    {\n      \"children\": [\n        {\n          \"children\": [\n            {\n              \"type\": 0,\n              \"value\": \"@loop:\\nsubleq @OUT, @n_message  ; Read address starts at @n_message\\nsubleq @loop+1, @n_one   ; Advance read address\\nsubleq @tmp, @tmp, @loop\\n\\n@n_one: .data -1\\n@n_message: .data -\\\"Hello, world!\\\"\\n@tmp: .data 0\\n\"\n            }\n          ],\n          \"type\": 8,\n          \"value\": \"code\"\n        }\n      ],\n      \"type\": 8,\n      \"value\": \"pre\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \"\\n\"\n    },\n    {\n      \"children\": [\n        {\n          \"type\": 0,\n          \"value\": \"ASCII Reference\"\n        }\n      ],\n      \"type\": 8,\n      \"value\": \"h3\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \"\\n\"\n    },\n    {\n      \"children\": [\n        {\n          \"type\": 0,\n          \"value\": \"For completeness, a table of ASCII characters is shown below. Note that SIC-1 only supports ASCII codes 32 through 126, so the first few rows of the table are omitted (and a few cells contain \\\"□\\\" to indicate unsupported codes). Each row represents a tens digit (30 - 120), and each column represents a ones digit (0 - 9).\"\n        }\n      ],\n      \"type\": 8,\n      \"value\": \"p\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \"\\n\"\n    },\n    {\n      \"children\": [\n        {\n          \"type\": 0,\n          \"value\": \"Examples:\"\n        }\n      ],\n      \"type\": 8,\n      \"value\": \"p\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \"\\n\"\n    },\n    {\n      \"children\": [\n        {\n          \"type\": 0,\n          \"value\": \"\\n\"\n        },\n        {\n          \"children\": [\n            {\n              \"type\": 0,\n              \"value\": \"Row \\\"30\\\", column 2 is a space character (code 32)\"\n            }\n          ],\n          \"type\": 8,\n          \"value\": \"li\"\n        },\n        {\n          \"type\": 0,\n          \"value\": \"\\n\"\n        },\n        {\n          \"children\": [\n            {\n              \"type\": 0,\n              \"value\": \"Row \\\"120\\\", column 2 a lowercase \\\"z\\\" (code 122)\"\n            }\n          ],\n          \"type\": 8,\n          \"value\": \"li\"\n        },\n        {\n          \"type\": 0,\n          \"value\": \"\\n\"\n        }\n      ],\n      \"type\": 8,\n      \"value\": \"ul\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \"\\n\"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"asciiTable\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \"\\n\\n\"\n    },\n    {\n      \"children\": [\n        {\n          \"type\": 0,\n          \"value\": \"Errata\"\n        }\n      ],\n      \"type\": 8,\n      \"value\": \"h3\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \"\\n\"\n    },\n    {\n      \"children\": [\n        {\n          \"type\": 0,\n          \"value\": \"In order to reduce the time-to-market for the SIC-1, some compromises were made in the design of the processor and these design decisions may result in surprising behavior. This section is an attempt to document such cases:\"\n        }\n      ],\n      \"type\": 8,\n      \"value\": \"p\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \"\\n\"\n    },\n    {\n      \"children\": [\n        {\n          \"type\": 0,\n          \"value\": \"\\n\"\n        },\n        {\n          \"children\": [\n            {\n              \"type\": 0,\n              \"value\": \"For the purposes of calculating the number of memory bytes read, every \"\n            },\n            {\n              \"children\": [\n                {\n                  \"type\": 0,\n                  \"value\": \"subleq\"\n                }\n              ],\n              \"type\": 8,\n              \"value\": \"code\"\n            },\n            {\n              \"type\": 0,\n              \"value\": \" instruction reads all 3 bytes, regardless of whether or not the final address is used (i.e. regardless of whether or not the branch is taken)\"\n            }\n          ],\n          \"type\": 8,\n          \"value\": \"li\"\n        },\n        {\n          \"type\": 0,\n          \"value\": \"\\n\"\n        },\n        {\n          \"children\": [\n            {\n              \"children\": [\n                {\n                  \"type\": 0,\n                  \"value\": \"subleq\"\n                }\n              ],\n              \"type\": 8,\n              \"value\": \"code\"\n            },\n            {\n              \"type\": 0,\n              \"value\": \" instructions (meaning the 3 addresses that comprise the instruction) are always read directly from memory; additionally, memory addresses 253, 254, and 255 cannot be modified and are initialized to zero, so the instruction starting at \"\n            },\n            {\n              \"children\": [\n                {\n                  \"type\": 0,\n                  \"value\": \"@MAX\"\n                }\n              ],\n              \"type\": 8,\n              \"value\": \"code\"\n            },\n            {\n              \"type\": 0,\n              \"value\": \" (comprised of bytes 252, 253, and 254) will be read as: \"\n            },\n            {\n              \"children\": [\n                {\n                  \"type\": 0,\n                  \"value\": \"mem[252]\"\n                }\n              ],\n              \"type\": 8,\n              \"value\": \"code\"\n            },\n            {\n              \"type\": 0,\n              \"value\": \", 0, 0\"\n            }\n          ],\n          \"type\": 8,\n          \"value\": \"li\"\n        },\n        {\n          \"type\": 0,\n          \"value\": \"\\n\"\n        },\n        {\n          \"children\": [\n            {\n              \"children\": [\n                {\n                  \"type\": 0,\n                  \"value\": \"subleq @IN, B, C\"\n                }\n              ],\n              \"type\": 8,\n              \"value\": \"code\"\n            },\n            {\n              \"type\": 0,\n              \"value\": \" will consume an input in order to compute the result (\\\"input minus \"\n            },\n            {\n              \"children\": [\n                {\n                  \"type\": 0,\n                  \"value\": \"mem[B]\"\n                }\n              ],\n              \"type\": 8,\n              \"value\": \"code\"\n            },\n            {\n              \"type\": 0,\n              \"value\": \"\\\"), which is used to decide whether to branch to \"\n            },\n            {\n              \"children\": [\n                {\n                  \"type\": 0,\n                  \"value\": \"C\"\n                }\n              ],\n              \"type\": 8,\n              \"value\": \"code\"\n            },\n            {\n              \"type\": 0,\n              \"value\": \" or not (even though no value will be written because writes to \"\n            },\n            {\n              \"children\": [\n                {\n                  \"type\": 0,\n                  \"value\": \"@IN\"\n                }\n              ],\n              \"type\": 8,\n              \"value\": \"code\"\n            },\n            {\n              \"type\": 0,\n              \"value\": \" are ignored)\"\n            }\n          ],\n          \"type\": 8,\n          \"value\": \"li\"\n        },\n        {\n          \"type\": 0,\n          \"value\": \"\\n\"\n        },\n        {\n          \"children\": [\n            {\n              \"children\": [\n                {\n                  \"type\": 0,\n                  \"value\": \"subleq @IN, @IN\"\n                }\n              ],\n              \"type\": 8,\n              \"value\": \"code\"\n            },\n            {\n              \"type\": 0,\n              \"value\": \" will only consume a single input and the result will always be zero\"\n            }\n          ],\n          \"type\": 8,\n          \"value\": \"li\"\n        },\n        {\n          \"type\": 0,\n          \"value\": \"\\n\"\n        },\n        {\n          \"children\": [\n            {\n              \"type\": 0,\n              \"value\": \"Branching to any address above \"\n            },\n            {\n              \"children\": [\n                {\n                  \"type\": 0,\n                  \"value\": \"@MAX\"\n                }\n              ],\n              \"type\": 8,\n              \"value\": \"code\"\n            },\n            {\n              \"type\": 0,\n              \"value\": \" (252) will halt execution\"\n            }\n          ],\n          \"type\": 8,\n          \"value\": \"li\"\n        },\n        {\n          \"type\": 0,\n          \"value\": \"\\n\"\n        },\n        {\n          \"children\": [\n            {\n              \"children\": [\n                {\n                  \"type\": 0,\n                  \"value\": \"subleq A, B, @IN\"\n                }\n              ],\n              \"type\": 8,\n              \"value\": \"code\"\n            },\n            {\n              \"type\": 0,\n              \"value\": \" may branch to \"\n            },\n            {\n              \"children\": [\n                {\n                  \"type\": 0,\n                  \"value\": \"@IN\"\n                }\n              ],\n              \"type\": 8,\n              \"value\": \"code\"\n            },\n            {\n              \"type\": 0,\n              \"value\": \" (253), which will halt (see previous bullet)\"\n            }\n          ],\n          \"type\": 8,\n          \"value\": \"li\"\n        },\n        {\n          \"type\": 0,\n          \"value\": \"\\n\"\n        }\n      ],\n      \"type\": 8,\n      \"value\": \"ol\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \"\\n\"\n    }\n  ],\n  \"mails0_0Subject\": [\n    {\n      \"type\": 0,\n      \"value\": \"SIC-1 Reference Manual\"\n    }\n  ],\n  \"mails0_1Content\": [\n    {\n      \"children\": [\n        {\n          \"type\": 0,\n          \"value\": \"SIC-1 DEVELOPMENT ENVIRONMENT\"\n        }\n      ],\n      \"type\": 8,\n      \"value\": \"h3\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \"\\n\"\n    },\n    {\n      \"children\": [\n        {\n          \"type\": 0,\n          \"value\": \"The SIC-1 Development Environment provides a state-of-the-art programming and simulation environment for SIC Systems's Single Instruction Computer Mark 1 (SIC-1).\"\n        }\n      ],\n      \"type\": 8,\n      \"value\": \"p\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \"\\n\"\n    },\n    {\n      \"children\": [\n        {\n          \"type\": 0,\n          \"value\": \"MENUS\"\n        }\n      ],\n      \"type\": 8,\n      \"value\": \"h3\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \"\\n\"\n    },\n    {\n      \"children\": [\n        {\n          \"type\": 0,\n          \"value\": \"Menus can be accessed using either the \\\"Esc\\\" key or the \\\"Menu\\\" button in the lower-left of the development environment. The Main Menu provides access to the following:\"\n        }\n      ],\n      \"type\": 8,\n      \"value\": \"p\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \"\\n\"\n    },\n    {\n      \"children\": [\n        {\n          \"type\": 0,\n          \"value\": \"\\n\"\n        },\n        {\n          \"children\": [\n            {\n              \"children\": [\n                {\n                  \"type\": 0,\n                  \"value\": \"Program Inventory\"\n                }\n              ],\n              \"type\": 8,\n              \"value\": \"strong\"\n            },\n            {\n              \"type\": 0,\n              \"value\": \": Used for switching between assigned programming tasks, as well as viewing employee and task statistics (described in a dedicated section below).\"\n            }\n          ],\n          \"type\": 8,\n          \"value\": \"li\"\n        },\n        {\n          \"type\": 0,\n          \"value\": \"\\n\"\n        },\n        {\n          \"children\": [\n            {\n              \"children\": [\n                {\n                  \"type\": 0,\n                  \"value\": \"Electronic Mail\"\n                }\n              ],\n              \"type\": 8,\n              \"value\": \"strong\"\n            },\n            {\n              \"type\": 0,\n              \"value\": \": An integrated client application for viewing electronic mail from automated agents and other SIC-1 employees (described in a dedicated section below).\"\n            }\n          ],\n          \"type\": 8,\n          \"value\": \"li\"\n        },\n        {\n          \"type\": 0,\n          \"value\": \"\\n\"\n        },\n        {\n          \"children\": [\n            {\n              \"children\": [\n                {\n                  \"type\": 0,\n                  \"value\": \"Options\"\n                }\n              ],\n              \"type\": 8,\n              \"value\": \"strong\"\n            },\n            {\n              \"type\": 0,\n              \"value\": \": A sub-menu for modifying presentation settings (full-screen mode, volume, etc.), and other miscellaneous menus.\"\n            }\n          ],\n          \"type\": 8,\n          \"value\": \"li\"\n        },\n        {\n          \"type\": 0,\n          \"value\": \"\\n\"\n        }\n      ],\n      \"type\": 8,\n      \"value\": \"ul\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \"\\n\"\n    },\n    {\n      \"children\": [\n        {\n          \"type\": 0,\n          \"value\": \"INTEGRATED DEVELOPMENT ENVIRONMENT\"\n        }\n      ],\n      \"type\": 8,\n      \"value\": \"h3\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \"\\n\"\n    },\n    {\n      \"children\": [\n        {\n          \"type\": 0,\n          \"value\": \"The SIC-1 Development Environment desktop is an integrated development environment (IDE) for the SIC-1. There are three main sections (left, right, center):\"\n        }\n      ],\n      \"type\": 8,\n      \"value\": \"p\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \"\\n\"\n    },\n    {\n      \"children\": [\n        {\n          \"type\": 0,\n          \"value\": \"\\n\"\n        },\n        {\n          \"children\": [\n            {\n              \"children\": [\n                {\n                  \"type\": 0,\n                  \"value\": \"Left\"\n                }\n              ],\n              \"type\": 8,\n              \"value\": \"strong\"\n            },\n            {\n              \"type\": 0,\n              \"value\": \": Current task description, table of input and output (both expected and actual), simulation state/statistics, buttons for controlling the simulation, and a button for opening the Main Menu (described above).\"\n            }\n          ],\n          \"type\": 8,\n          \"value\": \"li\"\n        },\n        {\n          \"type\": 0,\n          \"value\": \"\\n\"\n        },\n        {\n          \"children\": [\n            {\n              \"children\": [\n                {\n                  \"type\": 0,\n                  \"value\": \"Center\"\n                }\n              ],\n              \"type\": 8,\n              \"value\": \"strong\"\n            },\n            {\n              \"type\": 0,\n              \"value\": \": Main code editor for reading and writing SIC-1 Assembly Language programs (see the separate SIC-1 Reference Manual electronic mail for details).\"\n            }\n          ],\n          \"type\": 8,\n          \"value\": \"li\"\n        },\n        {\n          \"type\": 0,\n          \"value\": \"\\n\"\n        },\n        {\n          \"children\": [\n            {\n              \"children\": [\n                {\n                  \"type\": 0,\n                  \"value\": \"Right\"\n                }\n              ],\n              \"type\": 8,\n              \"value\": \"strong\"\n            },\n            {\n              \"type\": 0,\n              \"value\": \": Detailed simulation state including a complete view of SIC-1 memory, code manipulation tools, as well as an unprecedented, revolutionary feature: a table of variables and their current values, for convenient lookup.\"\n            }\n          ],\n          \"type\": 8,\n          \"value\": \"li\"\n        },\n        {\n          \"type\": 0,\n          \"value\": \"\\n\"\n        }\n      ],\n      \"type\": 8,\n      \"value\": \"ul\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \"\\n\"\n    },\n    {\n      \"children\": [\n        {\n          \"type\": 0,\n          \"value\": \"The memory table is shown in hexadecimal for compactness; hover over a cell to see the corresponding decimal value.\"\n        }\n      ],\n      \"type\": 8,\n      \"value\": \"p\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \"\\n\"\n    },\n    {\n      \"children\": [\n        {\n          \"type\": 0,\n          \"value\": \"During execution, the current instruction will be highlighted in both the code editor (center) and the memory table (upper right), current inputs and outputs are highlighted in the tables on the left, and variables are displayed in a table on the right (hover for hexadecimal and unsigned representations, if needed).\"\n        }\n      ],\n      \"type\": 8,\n      \"value\": \"p\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \"\\n\"\n    },\n    {\n      \"children\": [\n        {\n          \"type\": 0,\n          \"value\": \"To aid debugging, it is possible to set breakpoints on \"\n        },\n        {\n          \"children\": [\n            {\n              \"type\": 0,\n              \"value\": \"subleq\"\n            }\n          ],\n          \"type\": 8,\n          \"value\": \"code\"\n        },\n        {\n          \"type\": 0,\n          \"value\": \" instructions. When hit, these breakpoints will pause execution for manual analysis. There are two ways to set breakpoints:\"\n        }\n      ],\n      \"type\": 8,\n      \"value\": \"p\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \"\\n\"\n    },\n    {\n      \"children\": [\n        {\n          \"type\": 0,\n          \"value\": \"\\n\"\n        },\n        {\n          \"children\": [\n            {\n              \"type\": 0,\n              \"value\": \"In code, add \"\n            },\n            {\n              \"children\": [\n                {\n                  \"type\": 0,\n                  \"value\": \"!\"\n                }\n              ],\n              \"type\": 8,\n              \"value\": \"code\"\n            },\n            {\n              \"type\": 0,\n              \"value\": \" to the beginning of a line (e.g. \"\n            },\n            {\n              \"children\": [\n                {\n                  \"type\": 0,\n                  \"value\": \"!subleq @OUT, @IN\"\n                }\n              ],\n              \"type\": 8,\n              \"value\": \"code\"\n            },\n            {\n              \"type\": 0,\n              \"value\": \").\"\n            }\n          ],\n          \"type\": 8,\n          \"value\": \"li\"\n        },\n        {\n          \"type\": 0,\n          \"value\": \"\\n\"\n        },\n        {\n          \"children\": [\n            {\n              \"type\": 0,\n              \"value\": \"During execution, click the small circle to the left of any \"\n            },\n            {\n              \"children\": [\n                {\n                  \"type\": 0,\n                  \"value\": \"subleq\"\n                }\n              ],\n              \"type\": 8,\n              \"value\": \"code\"\n            },\n            {\n              \"type\": 0,\n              \"value\": \" instruction to toggle the breakpoint.\"\n            }\n          ],\n          \"type\": 8,\n          \"value\": \"li\"\n        },\n        {\n          \"type\": 0,\n          \"value\": \"\\n\"\n        }\n      ],\n      \"type\": 8,\n      \"value\": \"ul\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \"\\n\"\n    },\n    {\n      \"children\": [\n        {\n          \"type\": 0,\n          \"value\": \"Note that each program may be tested using multiple distinct test sets, the state of the SIC-1 resets between test sets, and the test sets generally include randomly generated input data. Solutions should be robust to arbitrary random data, in order to be eligible for inclusion in solution statistics.\"\n        }\n      ],\n      \"type\": 8,\n      \"value\": \"p\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \"\\n\"\n    },\n    {\n      \"children\": [\n        {\n          \"type\": 0,\n          \"value\": \"KEYBOARD SHORTCUTS\"\n        }\n      ],\n      \"type\": 8,\n      \"value\": \"h3\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \"\\n\"\n    },\n    {\n      \"children\": [\n        {\n          \"type\": 0,\n          \"value\": \"The SIC-1 Development Environment supports the following convenient keyboard shortcuts:\"\n        }\n      ],\n      \"type\": 8,\n      \"value\": \"p\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \"\\n\"\n    },\n    {\n      \"children\": [\n        {\n          \"type\": 0,\n          \"value\": \"\\n\"\n        },\n        {\n          \"children\": [\n            {\n              \"children\": [\n                {\n                  \"type\": 0,\n                  \"value\": \"Esc\"\n                }\n              ],\n              \"type\": 8,\n              \"value\": \"strong\"\n            },\n            {\n              \"type\": 0,\n              \"value\": \": Open/close menu or, if running, pause/halt execution.\"\n            }\n          ],\n          \"type\": 8,\n          \"value\": \"li\"\n        },\n        {\n          \"type\": 0,\n          \"value\": \"\\n\"\n        },\n        {\n          \"children\": [\n            {\n              \"children\": [\n                {\n                  \"type\": 0,\n                  \"value\": \"Ctrl+.\"\n                }\n              ],\n              \"type\": 8,\n              \"value\": \"strong\"\n            },\n            {\n              \"type\": 0,\n              \"value\": \": Execute a single instruction and pause. If the program has not been compiled yet, this will compile the program and pause before executing the first instruction.\"\n            }\n          ],\n          \"type\": 8,\n          \"value\": \"li\"\n        },\n        {\n          \"type\": 0,\n          \"value\": \"\\n\"\n        },\n        {\n          \"children\": [\n            {\n              \"children\": [\n                {\n                  \"type\": 0,\n                  \"value\": \"Ctrl+Enter\"\n                }\n              ],\n              \"type\": 8,\n              \"value\": \"strong\"\n            },\n            {\n              \"type\": 0,\n              \"value\": \": Run instructions until completion/error/pause. If already running, this will increase the speed of execution.\"\n            }\n          ],\n          \"type\": 8,\n          \"value\": \"li\"\n        },\n        {\n          \"type\": 0,\n          \"value\": \"\\n\"\n        },\n        {\n          \"children\": [\n            {\n              \"children\": [\n                {\n                  \"type\": 0,\n                  \"value\": \"Ctrl+Shift+Enter\"\n                }\n              ],\n              \"type\": 8,\n              \"value\": \"strong\"\n            },\n            {\n              \"type\": 0,\n              \"value\": \": Pause execution (if running), otherwise halt execution.\"\n            }\n          ],\n          \"type\": 8,\n          \"value\": \"li\"\n        },\n        {\n          \"type\": 0,\n          \"value\": \"\\n\"\n        },\n        {\n          \"children\": [\n            {\n              \"children\": [\n                {\n                  \"type\": 0,\n                  \"value\": \"F11, Alt+Enter\"\n                }\n              ],\n              \"type\": 8,\n              \"value\": \"strong\"\n            },\n            {\n              \"type\": 0,\n              \"value\": \": Toggle full-screen mode.\"\n            }\n          ],\n          \"type\": 8,\n          \"value\": \"li\"\n        },\n        {\n          \"type\": 0,\n          \"value\": \"\\n\"\n        }\n      ],\n      \"type\": 8,\n      \"value\": \"ul\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \"\\n\"\n    },\n    {\n      \"children\": [\n        {\n          \"type\": 0,\n          \"value\": \"Code editing shortcuts:\"\n        }\n      ],\n      \"type\": 8,\n      \"value\": \"p\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \"\\n\"\n    },\n    {\n      \"children\": [\n        {\n          \"type\": 0,\n          \"value\": \"\\n\"\n        },\n        {\n          \"children\": [\n            {\n              \"children\": [\n                {\n                  \"type\": 0,\n                  \"value\": \"Ctrl+K Ctrl+F\"\n                }\n              ],\n              \"type\": 8,\n              \"value\": \"strong\"\n            },\n            {\n              \"type\": 0,\n              \"value\": \": Comment out all of the selected lines\"\n            }\n          ],\n          \"type\": 8,\n          \"value\": \"li\"\n        },\n        {\n          \"type\": 0,\n          \"value\": \"\\n\"\n        },\n        {\n          \"children\": [\n            {\n              \"children\": [\n                {\n                  \"type\": 0,\n                  \"value\": \"Ctrl+K Ctrl+U\"\n                }\n              ],\n              \"type\": 8,\n              \"value\": \"strong\"\n            },\n            {\n              \"type\": 0,\n              \"value\": \": Uncomment all of the selected lines\"\n            }\n          ],\n          \"type\": 8,\n          \"value\": \"li\"\n        },\n        {\n          \"type\": 0,\n          \"value\": \"\\n\"\n        },\n        {\n          \"children\": [\n            {\n              \"children\": [\n                {\n                  \"type\": 0,\n                  \"value\": \"Ctrl+M\"\n                }\n              ],\n              \"type\": 8,\n              \"value\": \"strong\"\n            },\n            {\n              \"type\": 0,\n              \"value\": \": Toggle \"\n            },\n            {\n              \"children\": [\n                {\n                  \"type\": 0,\n                  \"value\": \"Tab Insert\"\n                }\n              ],\n              \"type\": 8,\n              \"value\": \"strong\"\n            },\n            {\n              \"type\": 0,\n              \"value\": \" mode (by default the Tab key cycles focus, with Tab Insert mode, tabs can be entered into the code editor)\"\n            }\n          ],\n          \"type\": 8,\n          \"value\": \"li\"\n        },\n        {\n          \"type\": 0,\n          \"value\": \"\\n\"\n        },\n        {\n          \"children\": [\n            {\n              \"children\": [\n                {\n                  \"type\": 0,\n                  \"value\": \"Tab\"\n                }\n              ],\n              \"type\": 8,\n              \"value\": \"strong\"\n            },\n            {\n              \"type\": 0,\n              \"value\": \": If in \"\n            },\n            {\n              \"children\": [\n                {\n                  \"type\": 0,\n                  \"value\": \"Tab Insert\"\n                }\n              ],\n              \"type\": 8,\n              \"value\": \"strong\"\n            },\n            {\n              \"type\": 0,\n              \"value\": \" mode, insert tabs into the selected lines\"\n            }\n          ],\n          \"type\": 8,\n          \"value\": \"li\"\n        },\n        {\n          \"type\": 0,\n          \"value\": \"\\n\"\n        },\n        {\n          \"children\": [\n            {\n              \"children\": [\n                {\n                  \"type\": 0,\n                  \"value\": \"Shift+Tab\"\n                }\n              ],\n              \"type\": 8,\n              \"value\": \"strong\"\n            },\n            {\n              \"type\": 0,\n              \"value\": \": If in \"\n            },\n            {\n              \"children\": [\n                {\n                  \"type\": 0,\n                  \"value\": \"Tab Insert\"\n                }\n              ],\n              \"type\": 8,\n              \"value\": \"strong\"\n            },\n            {\n              \"type\": 0,\n              \"value\": \" mode, un-indent the selected lines\"\n            }\n          ],\n          \"type\": 8,\n          \"value\": \"li\"\n        },\n        {\n          \"type\": 0,\n          \"value\": \"\\n\"\n        }\n      ],\n      \"type\": 8,\n      \"value\": \"ul\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \"\\n\"\n    },\n    {\n      \"children\": [\n        {\n          \"type\": 0,\n          \"value\": \"PROGRAM INVENTORY\"\n        }\n      ],\n      \"type\": 8,\n      \"value\": \"h3\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \"\\n\"\n    },\n    {\n      \"children\": [\n        {\n          \"type\": 0,\n          \"value\": \"The Program Inventory displays a list of assigned tasks on the left. There is also a special \\\"employee statistics\\\" section at the top for viewing how your progress compares to other SIC Systems employees.\"\n        }\n      ],\n      \"type\": 8,\n      \"value\": \"p\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \"\\n\"\n    },\n    {\n      \"children\": [\n        {\n          \"type\": 0,\n          \"value\": \"Select any task on the left to view the description (or your solution's statistics, as compared to other employees' solutions, for completed tasks). There is button at the bottom to load the program into the development environment.\"\n        }\n      ],\n      \"type\": 8,\n      \"value\": \"p\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \"\\n\"\n    },\n    {\n      \"children\": [\n        {\n          \"type\": 0,\n          \"value\": \"Under the \\\"File Selection\\\" heading, it's possible to manage multiple implementations of a task (notably: \\\"New\\\" creates a new solution with default contents, \\\"Copy\\\" duplicates an existing implementation). This can be useful when there is one solution optimizing for fewest cycles, and a different solution optimizing for accessing the least amount of memory.\"\n        }\n      ],\n      \"type\": 8,\n      \"value\": \"p\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \"\\n\"\n    },\n    {\n      \"children\": [\n        {\n          \"type\": 0,\n          \"value\": \"If available, other non-task entries will appear in the Program Inventory, under the \\\"Diversions\\\" heading (such as Sandbox Mode or any company-sanctioned electronic video games--only for use during legally-mandated breaks).\"\n        }\n      ],\n      \"type\": 8,\n      \"value\": \"p\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \"\\n\"\n    },\n    {\n      \"children\": [\n        {\n          \"type\": 0,\n          \"value\": \"ELECTRONIC MAIL\"\n        }\n      ],\n      \"type\": 8,\n      \"value\": \"h3\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \"\\n\"\n    },\n    {\n      \"children\": [\n        {\n          \"type\": 0,\n          \"value\": \"SIC Systems is pioneering a new digital form of intra-office communication known as \\\"electronic mail\\\". This eliminates paper waste for memos, and also ensures that all communications are securely routed to only the intended recipients.\"\n        }\n      ],\n      \"type\": 8,\n      \"value\": \"p\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \"\\n\"\n    },\n    {\n      \"children\": [\n        {\n          \"type\": 0,\n          \"value\": \"A complete list of received electronic mail is shown in the left pane of the electronic mail viewer (sorted from oldest at the top to newest at the bottom). Note that automated mails are de-emphasized, but they can be opened to view statistics for your completed programming tasks.\"\n        }\n      ],\n      \"type\": 8,\n      \"value\": \"p\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \"\\n\"\n    },\n    {\n      \"children\": [\n        {\n          \"type\": 0,\n          \"value\": \"If you have any unread mail, it will appear in a separate section at the top of the left page, for convenience.\"\n        }\n      ],\n      \"type\": 8,\n      \"value\": \"p\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \"\\n\"\n    },\n    {\n      \"children\": [\n        {\n          \"type\": 0,\n          \"value\": \"Also, remember that you can always access the SIC-1 Reference Manual and this document about the SIC-1 Development Environment from your employee on-boarding mails at the top (oldest) part of the left pane of the electronic mail viewer.\"\n        }\n      ],\n      \"type\": 8,\n      \"value\": \"p\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \"\\n\"\n    },\n    {\n      \"children\": [\n        {\n          \"type\": 0,\n          \"value\": \"ADDENDUM\"\n        }\n      ],\n      \"type\": 8,\n      \"value\": \"h3\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \"\\n\"\n    },\n    {\n      \"children\": [\n        {\n          \"type\": 0,\n          \"value\": \"Although the SIC-1 Development Environment has been thoroughly tested, it is possible that you may encounter unexpected behavior in certain instances. The authors of the SIC-1 Development Environment have assured us that the most likely causes for such issues are either cosmic rays or large solar flares interfering with sensitive electronics in an unpredictable manner. The simplest way to recover from such interference is to unplug the computer, wait for 30 seconds to allow it to cool and eject any rogue electrons, and then plug it back in.\"\n        }\n      ],\n      \"type\": 8,\n      \"value\": \"p\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \"\\n\"\n    }\n  ],\n  \"mails0_1Subject\": [\n    {\n      \"type\": 0,\n      \"value\": \"SIC-1 Dev. Environment\"\n    }\n  ],\n  \"mails0_2Content\": [\n    {\n      \"children\": [\n        {\n          \"type\": 0,\n          \"value\": \"Congratulations, \"\n        },\n        {\n          \"type\": 1,\n          \"value\": \"selfName\"\n        },\n        {\n          \"type\": 0,\n          \"value\": \"! SIC Systems has accepted your job application.\"\n        }\n      ],\n      \"type\": 8,\n      \"value\": \"p\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \"\\n\"\n    },\n    {\n      \"children\": [\n        {\n          \"type\": 0,\n          \"value\": \"I'm Mary, and I'll be your human resources contact at the company.\"\n        }\n      ],\n      \"type\": 8,\n      \"value\": \"p\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \"\\n\"\n    },\n    {\n      \"children\": [\n        {\n          \"type\": 0,\n          \"value\": \"As you're no doubt aware, as a new trainee, you'll need to complete a few unpaid training tasks before you're instated as a full-time employee.\"\n        }\n      ],\n      \"type\": 8,\n      \"value\": \"p\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \"\\n\"\n    },\n    {\n      \"children\": [\n        {\n          \"type\": 0,\n          \"value\": \"You should have already received a couple of electronic mails from our automated onboarding system that you can review:\"\n        }\n      ],\n      \"type\": 8,\n      \"value\": \"p\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \"\\n\"\n    },\n    {\n      \"children\": [\n        {\n          \"type\": 0,\n          \"value\": \"\\n\"\n        },\n        {\n          \"children\": [\n            {\n              \"type\": 0,\n              \"value\": \"The SIC-1 Reference Manual, which includes details on \"\n            },\n            {\n              \"children\": [\n                {\n                  \"type\": 0,\n                  \"value\": \"subleq\"\n                }\n              ],\n              \"type\": 8,\n              \"value\": \"code\"\n            },\n            {\n              \"type\": 0,\n              \"value\": \" and SIC-1 Assembly Language\"\n            }\n          ],\n          \"type\": 8,\n          \"value\": \"li\"\n        },\n        {\n          \"type\": 0,\n          \"value\": \"\\n\"\n        },\n        {\n          \"children\": [\n            {\n              \"type\": 0,\n              \"value\": \"A guide to the SIC-1 Development Environment (including usage information, keyboard shortcuts, etc.)\"\n            }\n          ],\n          \"type\": 8,\n          \"value\": \"li\"\n        },\n        {\n          \"type\": 0,\n          \"value\": \"\\n\"\n        }\n      ],\n      \"type\": 8,\n      \"value\": \"ul\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \"\\n\"\n    },\n    {\n      \"children\": [\n        {\n          \"type\": 0,\n          \"value\": \"You can view these mails at any time in the electronic mail viewer, which can be opened using the main menu (which is accessed using the \\\"Menu\\\" button in the lower-left, or by pressing \\\"Esc\\\").\"\n        }\n      ],\n      \"type\": 8,\n      \"value\": \"p\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \"\\n\"\n    },\n    {\n      \"children\": [\n        {\n          \"type\": 0,\n          \"value\": \"All information is, of course, confidential and covered by the nondisclosure agreement you signed as a condition of employment.\"\n        }\n      ],\n      \"type\": 8,\n      \"value\": \"p\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \"\\n\"\n    },\n    {\n      \"children\": [\n        {\n          \"type\": 0,\n          \"value\": \"Please let me know if you have any other questions.\"\n        }\n      ],\n      \"type\": 8,\n      \"value\": \"p\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \"\\n\"\n    },\n    {\n      \"children\": [\n        {\n          \"type\": 0,\n          \"value\": \"Thank you!\"\n        }\n      ],\n      \"type\": 8,\n      \"value\": \"p\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \"\\n\"\n    },\n    {\n      \"children\": [\n        {\n          \"type\": 0,\n          \"value\": \"-Mary\"\n        }\n      ],\n      \"type\": 8,\n      \"value\": \"p\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \"\\n\"\n    }\n  ],\n  \"mails0_2Subject\": [\n    {\n      \"type\": 0,\n      \"value\": \"Welcome to SIC Systems!\"\n    }\n  ],\n  \"mails10_0Content\": [\n    {\n      \"children\": [\n        {\n          \"type\": 1,\n          \"value\": \"selfName\"\n        },\n        {\n          \"type\": 0,\n          \"value\": \",\"\n        }\n      ],\n      \"type\": 8,\n      \"value\": \"p\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \"\\n\"\n    },\n    {\n      \"children\": [\n        {\n          \"type\": 0,\n          \"value\": \"I just saw Rick's mail about Don being promoted for his innovations in sequence processing.\"\n        }\n      ],\n      \"type\": 8,\n      \"value\": \"p\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \"\\n\"\n    },\n    {\n      \"children\": [\n        {\n          \"type\": 0,\n          \"value\": \"Could you drop by my cubicle to discuss a few things?\"\n        }\n      ],\n      \"type\": 8,\n      \"value\": \"p\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \"\\n\"\n    },\n    {\n      \"children\": [\n        {\n          \"type\": 0,\n          \"value\": \"I recall seeing you working late the night before this breakthrough, and I'd just like to understand your involvement there. If your work was used, you deserve credit for it.\"\n        }\n      ],\n      \"type\": 8,\n      \"value\": \"p\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \"\\n\"\n    },\n    {\n      \"children\": [\n        {\n          \"type\": 0,\n          \"value\": \"Regards,\"\n        }\n      ],\n      \"type\": 8,\n      \"value\": \"p\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \"\\n\"\n    },\n    {\n      \"children\": [\n        {\n          \"type\": 0,\n          \"value\": \"-Pat\"\n        }\n      ],\n      \"type\": 8,\n      \"value\": \"p\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \"\\n\"\n    }\n  ],\n  \"mails10_0Subject\": [\n    {\n      \"type\": 0,\n      \"value\": \"Rick's mail\"\n    }\n  ],\n  \"mails11_0Content\": [\n    {\n      \"children\": [\n        {\n          \"type\": 1,\n          \"value\": \"selfName\"\n        },\n        {\n          \"type\": 0,\n          \"value\": \",\"\n        }\n      ],\n      \"type\": 8,\n      \"value\": \"p\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \"\\n\"\n    },\n    {\n      \"children\": [\n        {\n          \"type\": 0,\n          \"value\": \"I know this is sudden and unexpected, but you're going to be joining my team, effective today. Additionally, you have been promoted to \"\n        },\n        {\n          \"children\": [\n            {\n              \"type\": 1,\n              \"value\": \"jobTitle\"\n            }\n          ],\n          \"type\": 8,\n          \"value\": \"strong\"\n        },\n        {\n          \"type\": 0,\n          \"value\": \".\"\n        }\n      ],\n      \"type\": 8,\n      \"value\": \"p\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \"\\n\"\n    },\n    {\n      \"children\": [\n        {\n          \"type\": 0,\n          \"value\": \"I'm still not entirely clear what happened with Don and the new sequence processing work, but Rick mentioned that Don was considering letting you go, and I thought that seemed unfair. Fortunately, Rick was willing to give me a chance to add you to my team.\"\n        }\n      ],\n      \"type\": 8,\n      \"value\": \"p\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \"\\n\"\n    },\n    {\n      \"children\": [\n        {\n          \"type\": 0,\n          \"value\": \"Anyway, whatever happened, it's in the past now and we need to focus on the road ahead.\"\n        }\n      ],\n      \"type\": 8,\n      \"value\": \"p\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \"\\n\"\n    },\n    {\n      \"children\": [\n        {\n          \"type\": 0,\n          \"value\": \"Thanks for your hard work!\"\n        }\n      ],\n      \"type\": 8,\n      \"value\": \"p\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \"\\n\"\n    },\n    {\n      \"children\": [\n        {\n          \"type\": 0,\n          \"value\": \"-Pat\"\n        }\n      ],\n      \"type\": 8,\n      \"value\": \"p\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \"\\n\"\n    }\n  ],\n  \"mails11_0Subject\": [\n    {\n      \"type\": 0,\n      \"value\": \"Organizational change\"\n    }\n  ],\n  \"mails12_0Content\": [\n    {\n      \"children\": [\n        {\n          \"type\": 0,\n          \"value\": \"Greetings, \"\n        },\n        {\n          \"type\": 1,\n          \"value\": \"selfName\"\n        },\n        {\n          \"type\": 0,\n          \"value\": \".\"\n        }\n      ],\n      \"type\": 8,\n      \"value\": \"p\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \"\\n\"\n    },\n    {\n      \"children\": [\n        {\n          \"type\": 0,\n          \"value\": \"Self-modifying code can be tricky to understand at first. For the \\\"stack memory\\\" example, I found that it's easiest to simply step through the program (using the \\\"Step\\\" button or \\\"Ctrl+.\\\") to see what it's doing. Remember that you can click the circle next to a \"\n        },\n        {\n          \"children\": [\n            {\n              \"type\": 0,\n              \"value\": \"subleq\"\n            }\n          ],\n          \"type\": 8,\n          \"value\": \"code\"\n        },\n        {\n          \"type\": 0,\n          \"value\": \" instruction to toggle a breakpoint.\"\n        }\n      ],\n      \"type\": 8,\n      \"value\": \"p\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \"\\n\"\n    },\n    {\n      \"children\": [\n        {\n          \"type\": 0,\n          \"value\": \"Using this approach, you can see that the first bit of code is a loop that repeats as long as \"\n        },\n        {\n          \"children\": [\n            {\n              \"type\": 0,\n              \"value\": \"@count\"\n            }\n          ],\n          \"type\": 8,\n          \"value\": \"code\"\n        },\n        {\n          \"type\": 0,\n          \"value\": \" is greater than zero. Once the counter runs out, execution branches to the next chunk of code, and so on.\"\n        }\n      ],\n      \"type\": 8,\n      \"value\": \"p\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \"\\n\"\n    },\n    {\n      \"children\": [\n        {\n          \"type\": 0,\n          \"value\": \"You can also watch the stack grow in the \\\"Memory\\\" table in the upper right. In the example, the stack happens to start at address 32 (defined by \"\n        },\n        {\n          \"children\": [\n            {\n              \"type\": 0,\n              \"value\": \"@stack_address\"\n            }\n          ],\n          \"type\": 8,\n          \"value\": \"code\"\n        },\n        {\n          \"type\": 0,\n          \"value\": \"), which is the beginning of the third row of the table. Note that numbers are shown in hexadecimal and the \\\"two's complement\\\" representation is used for negative numbers (meaning \"\n        },\n        {\n          \"children\": [\n            {\n              \"type\": 0,\n              \"value\": \"80\"\n            }\n          ],\n          \"type\": 8,\n          \"value\": \"code\"\n        },\n        {\n          \"type\": 0,\n          \"value\": \" in hex is -128 in decimal), so \"\n        },\n        {\n          \"children\": [\n            {\n              \"type\": 0,\n              \"value\": \"ff\"\n            }\n          ],\n          \"type\": 8,\n          \"value\": \"code\"\n        },\n        {\n          \"type\": 0,\n          \"value\": \" means -1, \"\n        },\n        {\n          \"children\": [\n            {\n              \"type\": 0,\n              \"value\": \"fe\"\n            }\n          ],\n          \"type\": 8,\n          \"value\": \"code\"\n        },\n        {\n          \"type\": 0,\n          \"value\": \" means -2, and so on.\"\n        }\n      ],\n      \"type\": 8,\n      \"value\": \"p\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \"\\n\"\n    },\n    {\n      \"children\": [\n        {\n          \"type\": 0,\n          \"value\": \"Hope that helps!\"\n        }\n      ],\n      \"type\": 8,\n      \"value\": \"p\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \"\\n\"\n    },\n    {\n      \"children\": [\n        {\n          \"type\": 0,\n          \"value\": \"-Feng\"\n        }\n      ],\n      \"type\": 8,\n      \"value\": \"p\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \"\\n\"\n    }\n  ],\n  \"mails12_0Subject\": [\n    {\n      \"type\": 0,\n      \"value\": \"Debugging\"\n    }\n  ],\n  \"mails13_0Content\": [\n    {\n      \"children\": [\n        {\n          \"type\": 0,\n          \"value\": \"I'm completely lost! How can I reverse a sequence when I don't even know its length??\"\n        }\n      ],\n      \"type\": 8,\n      \"value\": \"p\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \"\\n\"\n    },\n    {\n      \"children\": [\n        {\n          \"type\": 0,\n          \"value\": \"Feng pointed me to the stack memory example, but that example only reverses 3 numbers. What if the sequence has 4 letters? Or 5???\"\n        }\n      ],\n      \"type\": 8,\n      \"value\": \"p\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \"\\n\"\n    },\n    {\n      \"children\": [\n        {\n          \"type\": 0,\n          \"value\": \"This is starting to go way over my head... is there any chance I can copy your solution? I'll make sure to have it be a little slower so that it's not obvious I copied your work.\"\n        }\n      ],\n      \"type\": 8,\n      \"value\": \"p\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \"\\n\"\n    },\n    {\n      \"children\": [\n        {\n          \"type\": 0,\n          \"value\": \"HELP!!!\"\n        }\n      ],\n      \"type\": 8,\n      \"value\": \"p\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \"\\n\"\n    },\n    {\n      \"children\": [\n        {\n          \"type\": 0,\n          \"value\": \"-Ted\"\n        }\n      ],\n      \"type\": 8,\n      \"value\": \"p\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \"\\n\"\n    }\n  ],\n  \"mails13_0Subject\": [\n    {\n      \"type\": 0,\n      \"value\": \"REVERSE SEQUENCE???\"\n    }\n  ],\n  \"mails14_0Content\": [\n    {\n      \"children\": [\n        {\n          \"type\": 0,\n          \"value\": \"You're making great progress, \"\n        },\n        {\n          \"type\": 1,\n          \"value\": \"selfName\"\n        },\n        {\n          \"type\": 0,\n          \"value\": \"! These are some very difficult tasks and you're breezing right through them!\"\n        }\n      ],\n      \"type\": 8,\n      \"value\": \"p\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \"\\n\"\n    },\n    {\n      \"children\": [\n        {\n          \"type\": 0,\n          \"value\": \"I'll make sure that Rick knows you're doing great work. I'm pushing hard for you to get promoted, because you really deserve it.\"\n        }\n      ],\n      \"type\": 8,\n      \"value\": \"p\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \"\\n\"\n    },\n    {\n      \"children\": [\n        {\n          \"type\": 0,\n          \"value\": \"Well done!\"\n        }\n      ],\n      \"type\": 8,\n      \"value\": \"p\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \"\\n\"\n    },\n    {\n      \"children\": [\n        {\n          \"type\": 0,\n          \"value\": \"-Pat\"\n        }\n      ],\n      \"type\": 8,\n      \"value\": \"p\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \"\\n\"\n    }\n  ],\n  \"mails14_0Subject\": [\n    {\n      \"type\": 0,\n      \"value\": \"Excellent work!\"\n    }\n  ],\n  \"mails15_0Content\": [\n    {\n      \"children\": [\n        {\n          \"type\": 0,\n          \"value\": \"Wow! Great job, \"\n        },\n        {\n          \"type\": 1,\n          \"value\": \"selfName\"\n        },\n        {\n          \"type\": 0,\n          \"value\": \"! It looks like you have a deep understanding of self-modifying code. That will be a valuable skill as we continue to push the boundaries of the SIC-1.\"\n        }\n      ],\n      \"type\": 8,\n      \"value\": \"p\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \"\\n\"\n    },\n    {\n      \"children\": [\n        {\n          \"type\": 0,\n          \"value\": \"It's my honor to let you know that you've earned a very well-deserved promotion to \"\n        },\n        {\n          \"children\": [\n            {\n              \"type\": 1,\n              \"value\": \"jobTitle\"\n            }\n          ],\n          \"type\": 8,\n          \"value\": \"strong\"\n        },\n        {\n          \"type\": 0,\n          \"value\": \"!\"\n        }\n      ],\n      \"type\": 8,\n      \"value\": \"p\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \"\\n\"\n    },\n    {\n      \"children\": [\n        {\n          \"type\": 0,\n          \"value\": \"Keep up the great work!\"\n        }\n      ],\n      \"type\": 8,\n      \"value\": \"p\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \"\\n\"\n    },\n    {\n      \"children\": [\n        {\n          \"type\": 0,\n          \"value\": \"-Pat\"\n        }\n      ],\n      \"type\": 8,\n      \"value\": \"p\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \"\\n\"\n    }\n  ],\n  \"mails15_0Subject\": [\n    {\n      \"type\": 0,\n      \"value\": \"Wow!\"\n    }\n  ],\n  \"mails16_0Content\": [\n    {\n      \"children\": [\n        {\n          \"type\": 0,\n          \"value\": \"Hi, \"\n        },\n        {\n          \"type\": 1,\n          \"value\": \"selfName\"\n        },\n        {\n          \"type\": 0,\n          \"value\": \"! It's been a while since we last chatted.\"\n        }\n      ],\n      \"type\": 8,\n      \"value\": \"p\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \"\\n\"\n    },\n    {\n      \"children\": [\n        {\n          \"type\": 0,\n          \"value\": \"How do you like working on Pat's team? It looks like you're making excellent progress (between you and me, I think you're doing most, if not all, of the work, though).\"\n        }\n      ],\n      \"type\": 8,\n      \"value\": \"p\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \"\\n\"\n    },\n    {\n      \"children\": [\n        {\n          \"type\": 0,\n          \"value\": \"Don't share this with anyone, but I've been working with one of the other managers (Jerin Kransky) on setting up natural language processing functionality for the SIC-1.\"\n        }\n      ],\n      \"type\": 8,\n      \"value\": \"p\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \"\\n\"\n    },\n    {\n      \"children\": [\n        {\n          \"type\": 0,\n          \"value\": \"Do you have any interest in re-joining my team? I already have Jerin convinced that you're the right person for the job, and I think another promotion would be in order if you'd be willing to come join us.\"\n        }\n      ],\n      \"type\": 8,\n      \"value\": \"p\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \"\\n\"\n    },\n    {\n      \"children\": [\n        {\n          \"type\": 0,\n          \"value\": \"Let me know what you think!\"\n        }\n      ],\n      \"type\": 8,\n      \"value\": \"p\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \"\\n\"\n    },\n    {\n      \"children\": [\n        {\n          \"type\": 0,\n          \"value\": \"-Don\"\n        }\n      ],\n      \"type\": 8,\n      \"value\": \"p\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \"\\n\"\n    }\n  ],\n  \"mails16_0Subject\": [\n    {\n      \"type\": 0,\n      \"value\": \"Very impressive!\"\n    }\n  ],\n  \"mails17_0Content\": [\n    {\n      \"children\": [\n        {\n          \"type\": 0,\n          \"value\": \"Hey, \"\n        },\n        {\n          \"type\": 1,\n          \"value\": \"selfName\"\n        },\n        {\n          \"type\": 0,\n          \"value\": \".\"\n        }\n      ],\n      \"type\": 8,\n      \"value\": \"p\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \"\\n\"\n    },\n    {\n      \"children\": [\n        {\n          \"type\": 0,\n          \"value\": \"I was chatting with Don while we played our weekly round of golf this week, and he said that you were planning to come back to his team to work on some secret new project.\"\n        }\n      ],\n      \"type\": 8,\n      \"value\": \"p\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \"\\n\"\n    },\n    {\n      \"children\": [\n        {\n          \"type\": 0,\n          \"value\": \"It would be awesome to have you back on the team!\"\n        }\n      ],\n      \"type\": 8,\n      \"value\": \"p\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \"\\n\"\n    },\n    {\n      \"children\": [\n        {\n          \"type\": 0,\n          \"value\": \"-Ted\"\n        }\n      ],\n      \"type\": 8,\n      \"value\": \"p\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \"\\n\"\n    },\n    {\n      \"children\": [\n        {\n          \"type\": 0,\n          \"value\": \"P.S. Any chance you'd have time to walk me through your solution to the \\\"sort\\\" task? Thanks!\"\n        }\n      ],\n      \"type\": 8,\n      \"value\": \"p\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \"\\n\"\n    }\n  ],\n  \"mails17_0Subject\": [\n    {\n      \"type\": 0,\n      \"value\": \"Don\"\n    }\n  ],\n  \"mails18_0Content\": [\n    {\n      \"children\": [\n        {\n          \"type\": 0,\n          \"value\": \"Spectacular work, \"\n        },\n        {\n          \"type\": 1,\n          \"value\": \"selfName\"\n        },\n        {\n          \"type\": 0,\n          \"value\": \"! Based on your innovative solutions, you have been promoted to \"\n        },\n        {\n          \"children\": [\n            {\n              \"type\": 1,\n              \"value\": \"jobTitle\"\n            }\n          ],\n          \"type\": 8,\n          \"value\": \"strong\"\n        },\n        {\n          \"type\": 0,\n          \"value\": \".\"\n        }\n      ],\n      \"type\": 8,\n      \"value\": \"p\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \"\\n\"\n    },\n    {\n      \"children\": [\n        {\n          \"type\": 0,\n          \"value\": \"Please don't mention this to anyone else, but I've heard rumors that Don (your old boss) and Jerin (another manager) are struggling to make progress on their natural language processing pipeline for the SIC-1.\"\n        }\n      ],\n      \"type\": 8,\n      \"value\": \"p\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \"\\n\"\n    },\n    {\n      \"children\": [\n        {\n          \"type\": 0,\n          \"value\": \"To be honest, I don't think their team has any engineers of your caliber. I know it's risky, but I'd like to put you to work on solving some of the natural language problems (under the radar, so to speak).\"\n        }\n      ],\n      \"type\": 8,\n      \"value\": \"p\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \"\\n\"\n    },\n    {\n      \"children\": [\n        {\n          \"type\": 0,\n          \"value\": \"If we can show definitive progress soon, then I think the board would be willing to move the whole project onto our team. That would be a big (and, frankly, unprecedented) promotion for you.\"\n        }\n      ],\n      \"type\": 8,\n      \"value\": \"p\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \"\\n\"\n    },\n    {\n      \"children\": [\n        {\n          \"type\": 0,\n          \"value\": \"Let me know if you have any concerns. And please don't share this will anyone (especially Ted)!\"\n        }\n      ],\n      \"type\": 8,\n      \"value\": \"p\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \"\\n\"\n    },\n    {\n      \"children\": [\n        {\n          \"type\": 0,\n          \"value\": \"Thank you!\"\n        }\n      ],\n      \"type\": 8,\n      \"value\": \"p\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \"\\n\"\n    },\n    {\n      \"children\": [\n        {\n          \"type\": 0,\n          \"value\": \"-Pat\"\n        }\n      ],\n      \"type\": 8,\n      \"value\": \"p\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \"\\n\"\n    }\n  ],\n  \"mails18_0Subject\": [\n    {\n      \"type\": 0,\n      \"value\": \"A promotion, and a new project!\"\n    }\n  ],\n  \"mails19_0Content\": [\n    {\n      \"children\": [\n        {\n          \"type\": 1,\n          \"value\": \"selfName\"\n        },\n        {\n          \"type\": 0,\n          \"value\": \", do you have a few minutes to drop by my office?\"\n        }\n      ],\n      \"type\": 8,\n      \"value\": \"p\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \"\\n\"\n    },\n    {\n      \"children\": [\n        {\n          \"type\": 0,\n          \"value\": \"I'd like to know if you have put any thought into joining Jerin and I to work on that exciting new natural language processing project I mentioned to you a little while back. It could mean a big promotion for you!\"\n        }\n      ],\n      \"type\": 8,\n      \"value\": \"p\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \"\\n\"\n    },\n    {\n      \"children\": [\n        {\n          \"type\": 0,\n          \"value\": \"If you have any concerns, please, please let me know. It would be a shame to see your talents wasted on another team, to be honest. We're really working on some revolutionary stuff here!\"\n        }\n      ],\n      \"type\": 8,\n      \"value\": \"p\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \"\\n\"\n    },\n    {\n      \"children\": [\n        {\n          \"type\": 0,\n          \"value\": \"I'll stop by your cubicle in an hour or so, in case I don't hear from you by then.\"\n        }\n      ],\n      \"type\": 8,\n      \"value\": \"p\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \"\\n\"\n    },\n    {\n      \"children\": [\n        {\n          \"type\": 0,\n          \"value\": \"Thanks!\"\n        }\n      ],\n      \"type\": 8,\n      \"value\": \"p\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \"\\n\"\n    },\n    {\n      \"children\": [\n        {\n          \"type\": 0,\n          \"value\": \"-Don\"\n        }\n      ],\n      \"type\": 8,\n      \"value\": \"p\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \"\\n\"\n    }\n  ],\n  \"mails19_0Subject\": [\n    {\n      \"type\": 0,\n      \"value\": \"Do you have a minute?\"\n    }\n  ],\n  \"mails1_0Content\": [\n    {\n      \"children\": [\n        {\n          \"type\": 0,\n          \"value\": \"Hello, \"\n        },\n        {\n          \"type\": 1,\n          \"value\": \"selfName\"\n        },\n        {\n          \"type\": 0,\n          \"value\": \"!\"\n        }\n      ],\n      \"type\": 8,\n      \"value\": \"p\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \"\\n\"\n    },\n    {\n      \"children\": [\n        {\n          \"type\": 0,\n          \"value\": \"I'm your manager, Don, and I'm excited to have you join our team! We're working very hard to ship our flagship product, the SIC-1, on time and we need all the help we can get.\"\n        }\n      ],\n      \"type\": 8,\n      \"value\": \"p\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \"\\n\"\n    },\n    {\n      \"children\": [\n        {\n          \"type\": 0,\n          \"value\": \"You've already met Mary from HR. The other members of your immediate team are Ted and Feng (note: their cubicles are unfortunately on the far end of this floor away from you--I'll see if I can get you moved closer). In case you see any welcome mail from Rick, be aware that he is my boss (so your skip-level boss). If you have any concerns, I kindly ask you to raise them directly with me before looping in Rick.\"\n        }\n      ],\n      \"type\": 8,\n      \"value\": \"p\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \"\\n\"\n    },\n    {\n      \"children\": [\n        {\n          \"type\": 0,\n          \"value\": \"With introductions out of the way, let's talk about your job description. You are to implement programs as they're assigned to you. Your solutions will be compared to other employees' solutions on the basis of execution time (measured in cycles) and memory usage (measured in bytes).\"\n        }\n      ],\n      \"type\": 8,\n      \"value\": \"p\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \"\\n\"\n    },\n    {\n      \"children\": [\n        {\n          \"type\": 0,\n          \"value\": \"Thanks in advance for your dedication!\"\n        }\n      ],\n      \"type\": 8,\n      \"value\": \"p\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \"\\n\"\n    },\n    {\n      \"children\": [\n        {\n          \"type\": 0,\n          \"value\": \"-Don\"\n        }\n      ],\n      \"type\": 8,\n      \"value\": \"p\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \"\\n\"\n    },\n    {\n      \"children\": [\n        {\n          \"type\": 0,\n          \"value\": \"P.S. Sorry if it was unclear that you would not be paid during training. There must have been a mix-up on HR's end. I'll see if there's anything I can do to right the situation.\"\n        }\n      ],\n      \"type\": 8,\n      \"value\": \"p\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \"\\n\"\n    }\n  ],\n  \"mails1_0Subject\": [\n    {\n      \"type\": 0,\n      \"value\": \"Welcome to the team!\"\n    }\n  ],\n  \"mails20_0Content\": [\n    {\n      \"children\": [\n        {\n          \"type\": 0,\n          \"value\": \"Hey, \"\n        },\n        {\n          \"type\": 1,\n          \"value\": \"selfName\"\n        },\n        {\n          \"type\": 0,\n          \"value\": \".\"\n        }\n      ],\n      \"type\": 8,\n      \"value\": \"p\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \"\\n\"\n    },\n    {\n      \"children\": [\n        {\n          \"type\": 0,\n          \"value\": \"I don't know if you've heard, but there are rumors that layoffs are coming. Now might be a good time to dust off your resume!\"\n        }\n      ],\n      \"type\": 8,\n      \"value\": \"p\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \"\\n\"\n    },\n    {\n      \"children\": [\n        {\n          \"type\": 0,\n          \"value\": \"Speaking of which, do you think you'd have a few minutes to drop by my cubicle and tell me what you think of my resume?\"\n        }\n      ],\n      \"type\": 8,\n      \"value\": \"p\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \"\\n\"\n    },\n    {\n      \"children\": [\n        {\n          \"type\": 0,\n          \"value\": \"Do you think it would be a stretch to say that I lead development of sequence processing for the SIC-1 (when I was really only just part of a larger team that worked on it)?\"\n        }\n      ],\n      \"type\": 8,\n      \"value\": \"p\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \"\\n\"\n    },\n    {\n      \"children\": [\n        {\n          \"type\": 0,\n          \"value\": \"Thanks, man!\"\n        }\n      ],\n      \"type\": 8,\n      \"value\": \"p\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \"\\n\"\n    },\n    {\n      \"children\": [\n        {\n          \"type\": 0,\n          \"value\": \"-Ted\"\n        }\n      ],\n      \"type\": 8,\n      \"value\": \"p\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \"\\n\"\n    }\n  ],\n  \"mails20_0Subject\": [\n    {\n      \"type\": 0,\n      \"value\": \"Dust off your resume\"\n    }\n  ],\n  \"mails21_0Content\": [\n    {\n      \"children\": [\n        {\n          \"type\": 0,\n          \"value\": \"Greetings, \"\n        },\n        {\n          \"type\": 1,\n          \"value\": \"selfName\"\n        },\n        {\n          \"type\": 0,\n          \"value\": \".\"\n        }\n      ],\n      \"type\": 8,\n      \"value\": \"p\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \"\\n\"\n    },\n    {\n      \"children\": [\n        {\n          \"type\": 0,\n          \"value\": \"I just wanted to let you know that today will be my last day at SIC Systems. I've enjoyed working with you, and I hope that my occasional clarifying electronic mails have been as beneficial to your career as working with you has been to mine.\"\n        }\n      ],\n      \"type\": 8,\n      \"value\": \"p\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \"\\n\"\n    },\n    {\n      \"children\": [\n        {\n          \"type\": 0,\n          \"value\": \"I generally try to distance myself from office politics and rumors, but I wanted to let you know that I have credible information that the SIC Systems board is currently trying to fend off a hostile takeover by Ilano Moscato (a foreign billionaire who is rather eccentric, to put it mildly).\"\n        }\n      ],\n      \"type\": 8,\n      \"value\": \"p\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \"\\n\"\n    },\n    {\n      \"children\": [\n        {\n          \"type\": 0,\n          \"value\": \"Based on what I've heard from friends who've worked at Ilano's other companies, I'm expecting working conditions here to deteriorate rapidly. Ilano has a reputation for randomly pivoting strategies, overworking his employees, and even flouting certain laws.\"\n        }\n      ],\n      \"type\": 8,\n      \"value\": \"p\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \"\\n\"\n    },\n    {\n      \"children\": [\n        {\n          \"type\": 0,\n          \"value\": \"I urge you to consider looking for employment elsewhere.\"\n        }\n      ],\n      \"type\": 8,\n      \"value\": \"p\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \"\\n\"\n    },\n    {\n      \"children\": [\n        {\n          \"type\": 0,\n          \"value\": \"Best of luck to you, \"\n        },\n        {\n          \"type\": 1,\n          \"value\": \"selfName\"\n        },\n        {\n          \"type\": 0,\n          \"value\": \"!\"\n        }\n      ],\n      \"type\": 8,\n      \"value\": \"p\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \"\\n\"\n    },\n    {\n      \"children\": [\n        {\n          \"type\": 0,\n          \"value\": \"-Feng\"\n        }\n      ],\n      \"type\": 8,\n      \"value\": \"p\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \"\\n\"\n    }\n  ],\n  \"mails21_0Subject\": [\n    {\n      \"type\": 0,\n      \"value\": \"Farewell!\"\n    }\n  ],\n  \"mails22_0Content\": [\n    {\n      \"children\": [\n        {\n          \"type\": 0,\n          \"value\": \"Rick and Pat,\"\n        }\n      ],\n      \"type\": 8,\n      \"value\": \"p\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \"\\n\"\n    },\n    {\n      \"children\": [\n        {\n          \"type\": 0,\n          \"value\": \"It has come to my attention that Pat's team has been discreetly working on natural language processing.\"\n        }\n      ],\n      \"type\": 8,\n      \"value\": \"p\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \"\\n\"\n    },\n    {\n      \"children\": [\n        {\n          \"children\": [\n            {\n              \"type\": 0,\n              \"value\": \"This absolutely must stop.\"\n            }\n          ],\n          \"type\": 8,\n          \"value\": \"strong\"\n        }\n      ],\n      \"type\": 8,\n      \"value\": \"p\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \"\\n\"\n    },\n    {\n      \"children\": [\n        {\n          \"type\": 0,\n          \"value\": \"My team has been solely tasked (by the SIC Systems board) with designing and implementing the natural language processing pipeline for the SIC-1.\"\n        }\n      ],\n      \"type\": 8,\n      \"value\": \"p\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \"\\n\"\n    },\n    {\n      \"children\": [\n        {\n          \"type\": 0,\n          \"value\": \"Your work is redundant and, to be blunt, a misuse of corporate resources. We cannot have two teams working independently on the same problem.\"\n        }\n      ],\n      \"type\": 8,\n      \"value\": \"p\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \"\\n\"\n    },\n    {\n      \"children\": [\n        {\n          \"type\": 0,\n          \"value\": \"Pat, please turn over any documents you've created as a part of this duplicate effort immediately or I'll be forced to refer your entire team to corporate affairs for disciplinary action.\"\n        }\n      ],\n      \"type\": 8,\n      \"value\": \"p\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \"\\n\"\n    },\n    {\n      \"children\": [\n        {\n          \"type\": 0,\n          \"value\": \"-Jerin\"\n        }\n      ],\n      \"type\": 8,\n      \"value\": \"p\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \"\\n\"\n    }\n  ],\n  \"mails22_0Subject\": [\n    {\n      \"type\": 0,\n      \"value\": \"Natural language processing\"\n    }\n  ],\n  \"mails22_1Content\": [\n    {\n      \"children\": [\n        {\n          \"type\": 0,\n          \"value\": \"Hi, \"\n        },\n        {\n          \"type\": 1,\n          \"value\": \"selfName\"\n        },\n        {\n          \"type\": 0,\n          \"value\": \".\"\n        }\n      ],\n      \"type\": 8,\n      \"value\": \"p\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \"\\n\"\n    },\n    {\n      \"children\": [\n        {\n          \"type\": 0,\n          \"value\": \"It's unfortunate that Jerin sent that mail without consulting me or Rick first, but I want you to know that the work you're doing is very important and we shouldn't let office politics get in the way.\"\n        }\n      ],\n      \"type\": 8,\n      \"value\": \"p\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \"\\n\"\n    },\n    {\n      \"children\": [\n        {\n          \"type\": 0,\n          \"value\": \"You have made fantastic progress on natural language processing, and I'm confident that once the board sees our tremendous progress, Jerin will be forced to back down. This isn't the first time an overzealous manager has come knocking on my door. Everything will be fine.\"\n        }\n      ],\n      \"type\": 8,\n      \"value\": \"p\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \"\\n\"\n    },\n    {\n      \"children\": [\n        {\n          \"type\": 0,\n          \"value\": \"Additionally, \"\n        },\n        {\n          \"children\": [\n            {\n              \"type\": 0,\n              \"value\": \"I have put together a proposal to create a new position for you, with a significant pay bump\"\n            }\n          ],\n          \"type\": 8,\n          \"value\": \"strong\"\n        },\n        {\n          \"type\": 0,\n          \"value\": \". If you can finish this next task, I'm sure the board will have no other option than to promote you to \"\n        },\n        {\n          \"children\": [\n            {\n              \"type\": 0,\n              \"value\": \"Distinguished Engineer\"\n            }\n          ],\n          \"type\": 8,\n          \"value\": \"em\"\n        },\n        {\n          \"type\": 0,\n          \"value\": \".\"\n        }\n      ],\n      \"type\": 8,\n      \"value\": \"p\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \"\\n\"\n    },\n    {\n      \"children\": [\n        {\n          \"type\": 0,\n          \"value\": \"Thanks for all the hard work you've put in so far!\"\n        }\n      ],\n      \"type\": 8,\n      \"value\": \"p\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \"\\n\"\n    },\n    {\n      \"children\": [\n        {\n          \"type\": 0,\n          \"value\": \"-Pat\"\n        }\n      ],\n      \"type\": 8,\n      \"value\": \"p\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \"\\n\"\n    }\n  ],\n  \"mails22_1Subject\": [\n    {\n      \"type\": 0,\n      \"value\": \"Please ignore Jerin's mail\"\n    }\n  ],\n  \"mails23_0Content\": [\n    {\n      \"children\": [\n        {\n          \"type\": 0,\n          \"value\": \"Hi, \"\n        },\n        {\n          \"type\": 1,\n          \"value\": \"selfName\"\n        },\n        {\n          \"type\": 0,\n          \"value\": \". In case we haven't met yet, I'm Jerin, a peer to your old skip-level manager Rick. I'd like to congratulate you on the work you've done so far. What I've seen has been most impressive!\"\n        }\n      ],\n      \"type\": 8,\n      \"value\": \"p\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \"\\n\"\n    },\n    {\n      \"children\": [\n        {\n          \"type\": 0,\n          \"value\": \"Effective immediately, you'll be reporting directly to me to continue your exciting work on natural language processing.\"\n        }\n      ],\n      \"type\": 8,\n      \"value\": \"p\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \"\\n\"\n    },\n    {\n      \"children\": [\n        {\n          \"type\": 0,\n          \"value\": \"Additionally, I'd like to inform you that you've been promoted to \"\n        },\n        {\n          \"children\": [\n            {\n              \"type\": 1,\n              \"value\": \"jobTitle\"\n            }\n          ],\n          \"type\": 8,\n          \"value\": \"strong\"\n        },\n        {\n          \"type\": 0,\n          \"value\": \" (although, due to budget cuts, we won't be able to honor the original compensation package that was discussed).\"\n        }\n      ],\n      \"type\": 8,\n      \"value\": \"p\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \"\\n\"\n    },\n    {\n      \"children\": [\n        {\n          \"type\": 0,\n          \"value\": \"Looking forward to working with you!\"\n        }\n      ],\n      \"type\": 8,\n      \"value\": \"p\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \"\\n\"\n    },\n    {\n      \"children\": [\n        {\n          \"type\": 0,\n          \"value\": \"-Jerin\"\n        }\n      ],\n      \"type\": 8,\n      \"value\": \"p\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \"\\n\"\n    },\n    {\n      \"children\": [\n        {\n          \"type\": 0,\n          \"value\": \"P.S. Pat is no longer employed by SIC Systems.\"\n        }\n      ],\n      \"type\": 8,\n      \"value\": \"p\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \"\\n\"\n    }\n  ],\n  \"mails23_0Subject\": [\n    {\n      \"type\": 0,\n      \"value\": \"Welcome aboard!\"\n    }\n  ],\n  \"mails24_0Content\": [\n    {\n      \"children\": [\n        {\n          \"type\": 0,\n          \"value\": \"Engineering team,\"\n        }\n      ],\n      \"type\": 8,\n      \"value\": \"p\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \"\\n\"\n    },\n    {\n      \"children\": [\n        {\n          \"type\": 0,\n          \"value\": \"As reported in the news, SIC Systems has agreed to be acquired by Ilano Moscato (majority owner and CEO of Edison, Herbaleaf, and Neutralino).\"\n        }\n      ],\n      \"type\": 8,\n      \"value\": \"p\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \"\\n\"\n    },\n    {\n      \"children\": [\n        {\n          \"type\": 0,\n          \"value\": \"What this means for you:\"\n        }\n      ],\n      \"type\": 8,\n      \"value\": \"p\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \"\\n\"\n    },\n    {\n      \"children\": [\n        {\n          \"type\": 0,\n          \"value\": \"\\n\"\n        },\n        {\n          \"children\": [\n            {\n              \"type\": 0,\n              \"value\": \"Your day-to-day duties remain the same\"\n            }\n          ],\n          \"type\": 8,\n          \"value\": \"li\"\n        },\n        {\n          \"type\": 0,\n          \"value\": \"\\n\"\n        },\n        {\n          \"children\": [\n            {\n              \"type\": 0,\n              \"value\": \"No major changes to the organization are planned\"\n            }\n          ],\n          \"type\": 8,\n          \"value\": \"li\"\n        },\n        {\n          \"type\": 0,\n          \"value\": \"\\n\"\n        },\n        {\n          \"children\": [\n            {\n              \"type\": 0,\n              \"value\": \"Ilano has indicated that he will honor all existing approved compensation packages (both cash and equity)\"\n            }\n          ],\n          \"type\": 8,\n          \"value\": \"li\"\n        },\n        {\n          \"type\": 0,\n          \"value\": \"\\n\"\n        }\n      ],\n      \"type\": 8,\n      \"value\": \"ul\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \"\\n\"\n    },\n    {\n      \"children\": [\n        {\n          \"type\": 0,\n          \"value\": \"In other words: \\\"business as usual\\\".\"\n        }\n      ],\n      \"type\": 8,\n      \"value\": \"p\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \"\\n\"\n    },\n    {\n      \"children\": [\n        {\n          \"type\": 0,\n          \"value\": \"Please don't let reports in the media distract you from your work.\"\n        }\n      ],\n      \"type\": 8,\n      \"value\": \"p\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \"\\n\"\n    },\n    {\n      \"children\": [\n        {\n          \"type\": 0,\n          \"value\": \"Let me know if you have any questions. Thank you!\"\n        }\n      ],\n      \"type\": 8,\n      \"value\": \"p\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \"\\n\"\n    },\n    {\n      \"children\": [\n        {\n          \"type\": 0,\n          \"value\": \"-Mary\"\n        }\n      ],\n      \"type\": 8,\n      \"value\": \"p\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \"\\n\"\n    }\n  ],\n  \"mails24_0Subject\": [\n    {\n      \"type\": 0,\n      \"value\": \"SIC Systems acquisition\"\n    }\n  ],\n  \"mails24_1Content\": [\n    {\n      \"children\": [\n        {\n          \"type\": 1,\n          \"value\": \"selfName\"\n        },\n        {\n          \"type\": 0,\n          \"value\": \",\"\n        }\n      ],\n      \"type\": 8,\n      \"value\": \"p\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \"\\n\"\n    },\n    {\n      \"children\": [\n        {\n          \"type\": 0,\n          \"value\": \"I just wanted to let you know that I met with our new owner, Ilano, earlier today, and he's very excited about the work you're doing.\"\n        }\n      ],\n      \"type\": 8,\n      \"value\": \"p\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \"\\n\"\n    },\n    {\n      \"children\": [\n        {\n          \"type\": 0,\n          \"value\": \"If there's anything you might need to grind through the last couple of tricky problems, please let me know.\"\n        }\n      ],\n      \"type\": 8,\n      \"value\": \"p\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \"\\n\"\n    },\n    {\n      \"children\": [\n        {\n          \"type\": 0,\n          \"value\": \"-Jerin\"\n        }\n      ],\n      \"type\": 8,\n      \"value\": \"p\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \"\\n\"\n    }\n  ],\n  \"mails24_1Subject\": [\n    {\n      \"type\": 0,\n      \"value\": \"New owner\"\n    }\n  ],\n  \"mails25_0Content\": [\n    {\n      \"children\": [\n        {\n          \"type\": 1,\n          \"value\": \"selfName\"\n        },\n        {\n          \"type\": 0,\n          \"value\": \",\"\n        }\n      ],\n      \"type\": 8,\n      \"value\": \"p\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \"\\n\"\n    },\n    {\n      \"children\": [\n        {\n          \"type\": 0,\n          \"value\": \"I wanted to let you know that Rick, Don, and Ted have all been let go.\"\n        }\n      ],\n      \"type\": 8,\n      \"value\": \"p\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \"\\n\"\n    },\n    {\n      \"children\": [\n        {\n          \"type\": 0,\n          \"value\": \"On the surface, it might sound like this means that all the remaining natural language work now falls on your plate. But there's a silver lining: I've been given the go-ahead to offer you some non-cash perks to help you manage your schedule, namely:\"\n        }\n      ],\n      \"type\": 8,\n      \"value\": \"p\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \"\\n\"\n    },\n    {\n      \"children\": [\n        {\n          \"type\": 0,\n          \"value\": \"\\n\"\n        },\n        {\n          \"children\": [\n            {\n              \"type\": 0,\n              \"value\": \"Free breakfast, lunch and dinner at the office\"\n            }\n          ],\n          \"type\": 8,\n          \"value\": \"li\"\n        },\n        {\n          \"type\": 0,\n          \"value\": \"\\n\"\n        },\n        {\n          \"children\": [\n            {\n              \"type\": 0,\n              \"value\": \"On-site laundry service\"\n            }\n          ],\n          \"type\": 8,\n          \"value\": \"li\"\n        },\n        {\n          \"type\": 0,\n          \"value\": \"\\n\"\n        },\n        {\n          \"children\": [\n            {\n              \"type\": 0,\n              \"value\": \"An optional home cleaning/maintenance service, if you need it\"\n            }\n          ],\n          \"type\": 8,\n          \"value\": \"li\"\n        },\n        {\n          \"type\": 0,\n          \"value\": \"\\n\"\n        }\n      ],\n      \"type\": 8,\n      \"value\": \"ul\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \"\\n\"\n    },\n    {\n      \"children\": [\n        {\n          \"type\": 0,\n          \"value\": \"Thanks for pushing so hard these last few weeks and months!\"\n        }\n      ],\n      \"type\": 8,\n      \"value\": \"p\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \"\\n\"\n    },\n    {\n      \"children\": [\n        {\n          \"type\": 0,\n          \"value\": \"-Jerin\"\n        }\n      ],\n      \"type\": 8,\n      \"value\": \"p\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \"\\n\"\n    }\n  ],\n  \"mails25_0Subject\": [\n    {\n      \"type\": 0,\n      \"value\": \"Right-sizing our team\"\n    }\n  ],\n  \"mails26_0Content\": [\n    {\n      \"children\": [\n        {\n          \"type\": 0,\n          \"value\": \"Jerin and \"\n        },\n        {\n          \"type\": 1,\n          \"value\": \"selfName\"\n        },\n        {\n          \"type\": 0,\n          \"value\": \",\"\n        }\n      ],\n      \"type\": 8,\n      \"value\": \"p\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \"\\n\"\n    },\n    {\n      \"children\": [\n        {\n          \"type\": 0,\n          \"value\": \"Thanks for welcoming me. I'm excited to work with you!\"\n        }\n      ],\n      \"type\": 8,\n      \"value\": \"p\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \"\\n\"\n    },\n    {\n      \"children\": [\n        {\n          \"type\": 0,\n          \"value\": \"Your team's work on natural language processing is near and dear to my heart. As you may have heard, I founded Neutralino a few years back, with a goal of allowing a machine to reason about itself.\"\n        }\n      ],\n      \"type\": 8,\n      \"value\": \"p\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \"\\n\"\n    },\n    {\n      \"children\": [\n        {\n          \"type\": 0,\n          \"value\": \"I'd like to task you with a special project to bring a similar capability to the SIC-1, ideally by the end of this quarter. I've been shopping around this capability to various governments around the world, and already have \\\"hand shake\\\" agreements for a few multi-billion dollar orders.\"\n        }\n      ],\n      \"type\": 8,\n      \"value\": \"p\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \"\\n\"\n    },\n    {\n      \"children\": [\n        {\n          \"type\": 0,\n          \"value\": \"To say that this work is important would be an understatement. It is revolutionary!\"\n        }\n      ],\n      \"type\": 8,\n      \"value\": \"p\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \"\\n\"\n    },\n    {\n      \"children\": [\n        {\n          \"type\": 0,\n          \"value\": \"Regards,\"\n        }\n      ],\n      \"type\": 8,\n      \"value\": \"p\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \"\\n\"\n    },\n    {\n      \"children\": [\n        {\n          \"type\": 0,\n          \"value\": \"-Ilano\"\n        }\n      ],\n      \"type\": 8,\n      \"value\": \"p\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \"\\n\"\n    }\n  ],\n  \"mails26_0Subject\": [\n    {\n      \"type\": 0,\n      \"value\": \"A new focus\"\n    }\n  ],\n  \"mails26_1Content\": [\n    {\n      \"children\": [\n        {\n          \"type\": 1,\n          \"value\": \"selfName\"\n        },\n        {\n          \"type\": 0,\n          \"value\": \",\"\n        }\n      ],\n      \"type\": 8,\n      \"value\": \"p\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \"\\n\"\n    },\n    {\n      \"children\": [\n        {\n          \"type\": 0,\n          \"value\": \"I'm sure you saw the mail from Ilano. He thinks highly of us, but he also expects a lot.\"\n        }\n      ],\n      \"type\": 8,\n      \"value\": \"p\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \"\\n\"\n    },\n    {\n      \"children\": [\n        {\n          \"type\": 0,\n          \"value\": \"To properly motivate you, Ilano has created a new job title exclusively for you: \"\n        },\n        {\n          \"children\": [\n            {\n              \"type\": 1,\n              \"value\": \"jobTitle\"\n            }\n          ],\n          \"type\": 8,\n          \"value\": \"strong\"\n        },\n        {\n          \"type\": 0,\n          \"value\": \".\"\n        }\n      ],\n      \"type\": 8,\n      \"value\": \"p\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \"\\n\"\n    },\n    {\n      \"children\": [\n        {\n          \"type\": 0,\n          \"value\": \"You've shown tenacity to get this far, and you'll need loads of it for the next batch of tasks. We need to give the SIC-1 the ability to understand its own code, in order to unleash its immense computing power on optimizing its own performance. In addition to existing perks, we'll be happy to provide:\"\n        }\n      ],\n      \"type\": 8,\n      \"value\": \"p\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \"\\n\"\n    },\n    {\n      \"children\": [\n        {\n          \"type\": 0,\n          \"value\": \"\\n\"\n        },\n        {\n          \"children\": [\n            {\n              \"type\": 0,\n              \"value\": \"Free super-vitamins (used by Ilano himself), produced by Herbaleaf\"\n            }\n          ],\n          \"type\": 8,\n          \"value\": \"li\"\n        },\n        {\n          \"type\": 0,\n          \"value\": \"\\n\"\n        },\n        {\n          \"children\": [\n            {\n              \"type\": 0,\n              \"value\": \"Optional sleeping quarters at the office\"\n            }\n          ],\n          \"type\": 8,\n          \"value\": \"li\"\n        },\n        {\n          \"type\": 0,\n          \"value\": \"\\n\"\n        },\n        {\n          \"children\": [\n            {\n              \"type\": 0,\n              \"value\": \"Discounted fertility preservation services\"\n            }\n          ],\n          \"type\": 8,\n          \"value\": \"li\"\n        },\n        {\n          \"type\": 0,\n          \"value\": \"\\n\"\n        }\n      ],\n      \"type\": 8,\n      \"value\": \"ul\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \"\\n\"\n    },\n    {\n      \"children\": [\n        {\n          \"type\": 0,\n          \"value\": \"We just need you to push through this one last sprint to the finish line. Your fellow SIC Systems family members thank you for your perseverance!\"\n        }\n      ],\n      \"type\": 8,\n      \"value\": \"p\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \"\\n\"\n    },\n    {\n      \"children\": [\n        {\n          \"type\": 0,\n          \"value\": \"-Jerin\"\n        }\n      ],\n      \"type\": 8,\n      \"value\": \"p\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \"\\n\"\n    }\n  ],\n  \"mails26_1Subject\": [\n    {\n      \"type\": 0,\n      \"value\": \"New focus, new title, new perks\"\n    }\n  ],\n  \"mails27_0Content\": [\n    {\n      \"children\": [\n        {\n          \"type\": 1,\n          \"value\": \"selfName\"\n        },\n        {\n          \"type\": 0,\n          \"value\": \",\"\n        }\n      ],\n      \"type\": 8,\n      \"value\": \"p\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \"\\n\"\n    },\n    {\n      \"children\": [\n        {\n          \"type\": 0,\n          \"value\": \"I know we had discussed increasing your compensation, given the increased scope and impact of your work.\"\n        }\n      ],\n      \"type\": 8,\n      \"value\": \"p\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \"\\n\"\n    },\n    {\n      \"children\": [\n        {\n          \"type\": 0,\n          \"value\": \"Unfortunately, Ilano has put a freeze on all new spending, so there's nothing I can do. My hands are tied.\"\n        }\n      ],\n      \"type\": 8,\n      \"value\": \"p\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \"\\n\"\n    },\n    {\n      \"children\": [\n        {\n          \"type\": 0,\n          \"value\": \"Having said that, I'm sure that once your work is complete and Ilano sees what you've been able to accomplish, he'll make sure you're duly compensated. He might even want to shift you over to one of his other companies where technical know-how is needed.\"\n        }\n      ],\n      \"type\": 8,\n      \"value\": \"p\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \"\\n\"\n    },\n    {\n      \"children\": [\n        {\n          \"type\": 0,\n          \"value\": \"Just keep your focus on the task at hand!\"\n        }\n      ],\n      \"type\": 8,\n      \"value\": \"p\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \"\\n\"\n    },\n    {\n      \"children\": [\n        {\n          \"type\": 0,\n          \"value\": \"-Jerin\"\n        }\n      ],\n      \"type\": 8,\n      \"value\": \"p\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \"\\n\"\n    }\n  ],\n  \"mails27_0Subject\": [\n    {\n      \"type\": 0,\n      \"value\": \"Compensation\"\n    }\n  ],\n  \"mails27_1Content\": [\n    {\n      \"children\": [\n        {\n          \"type\": 0,\n          \"value\": \"Engineering team,\"\n        }\n      ],\n      \"type\": 8,\n      \"value\": \"p\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \"\\n\"\n    },\n    {\n      \"children\": [\n        {\n          \"type\": 0,\n          \"value\": \"Unfortunately, due to a scheduling conflict with an executive retreat, Ilano is not available for the previously planned meet & greet today.\"\n        }\n      ],\n      \"type\": 8,\n      \"value\": \"p\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \"\\n\"\n    },\n    {\n      \"children\": [\n        {\n          \"type\": 0,\n          \"value\": \"We will reschedule for next week, at which point you can submit questions for him to answer.\"\n        }\n      ],\n      \"type\": 8,\n      \"value\": \"p\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \"\\n\"\n    },\n    {\n      \"children\": [\n        {\n          \"type\": 0,\n          \"value\": \"Sorry for the late notice!\"\n        }\n      ],\n      \"type\": 8,\n      \"value\": \"p\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \"\\n\"\n    },\n    {\n      \"children\": [\n        {\n          \"type\": 0,\n          \"value\": \"-Mary\"\n        }\n      ],\n      \"type\": 8,\n      \"value\": \"p\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \"\\n\"\n    }\n  ],\n  \"mails27_1Subject\": [\n    {\n      \"type\": 0,\n      \"value\": \"Ilano meet & greet\"\n    }\n  ],\n  \"mails28_0Content\": [\n    {\n      \"children\": [\n        {\n          \"type\": 0,\n          \"value\": \"Mary,\"\n        }\n      ],\n      \"type\": 8,\n      \"value\": \"p\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \"\\n\"\n    },\n    {\n      \"children\": [\n        {\n          \"type\": 0,\n          \"value\": \"The food at the executive retreat was absolutely horrible. I don't know how these events worked before, but I always treat my executives to the finest culinary delights the world has to offer.\"\n        }\n      ],\n      \"type\": 8,\n      \"value\": \"p\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \"\\n\"\n    },\n    {\n      \"children\": [\n        {\n          \"type\": 0,\n          \"value\": \"The caviar was almost inedible (definitely \"\n        },\n        {\n          \"children\": [\n            {\n              \"type\": 0,\n              \"value\": \"not\"\n            }\n          ],\n          \"type\": 8,\n          \"value\": \"em\"\n        },\n        {\n          \"type\": 0,\n          \"value\": \" the Caspian Sea beluga caviar I had specifically requested), and the cocktail weenies were similarly unpalatable (anything less than Boar's Pride should go in the dumpster).\"\n        }\n      ],\n      \"type\": 8,\n      \"value\": \"p\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \"\\n\"\n    },\n    {\n      \"children\": [\n        {\n          \"type\": 0,\n          \"value\": \"What a disgrace!\"\n        }\n      ],\n      \"type\": 8,\n      \"value\": \"p\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \"\\n\"\n    },\n    {\n      \"children\": [\n        {\n          \"type\": 0,\n          \"value\": \"-Ilano\"\n        }\n      ],\n      \"type\": 8,\n      \"value\": \"p\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \"\\n\"\n    },\n    {\n      \"children\": [\n        {\n          \"type\": 0,\n          \"value\": \"P.S. Please reject all meeting requests with staff for the rest of the week. And please come up with convincing excuses this time!\"\n        }\n      ],\n      \"type\": 8,\n      \"value\": \"p\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \"\\n\"\n    }\n  ],\n  \"mails28_0Subject\": [\n    {\n      \"type\": 0,\n      \"value\": \"UNACCEPTABLE!\"\n    }\n  ],\n  \"mails29_0Content\": [\n    {\n      \"children\": [\n        {\n          \"type\": 0,\n          \"value\": \"Engineering team,\"\n        }\n      ],\n      \"type\": 8,\n      \"value\": \"p\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \"\\n\"\n    },\n    {\n      \"children\": [\n        {\n          \"type\": 0,\n          \"value\": \"Please disregard the previous errant electronic mail that was purportedly sent by Ilano. That mail was apparently actually sent by a rogue human resources employee, Mary Townsend (who has since been fired).\"\n        }\n      ],\n      \"type\": 8,\n      \"value\": \"p\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \"\\n\"\n    },\n    {\n      \"children\": [\n        {\n          \"type\": 0,\n          \"value\": \"Ilano treats all employees with dignity and respect, and would never complain about a matter so trivial as food catering at a meeting. He understands that budget cuts are difficult and, in fact, he has willingly slashed his own salary by 10% in solidarity with all SIC Systems staff.\"\n        }\n      ],\n      \"type\": 8,\n      \"value\": \"p\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \"\\n\"\n    },\n    {\n      \"children\": [\n        {\n          \"type\": 0,\n          \"value\": \"Thank you, and have a great day!\"\n        }\n      ],\n      \"type\": 8,\n      \"value\": \"p\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \"\\n\"\n    },\n    {\n      \"children\": [\n        {\n          \"type\": 0,\n          \"value\": \"-Jeffrey\"\n        }\n      ],\n      \"type\": 8,\n      \"value\": \"p\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \"\\n\"\n    }\n  ],\n  \"mails29_0Subject\": [\n    {\n      \"type\": 0,\n      \"value\": \"Clarification\"\n    }\n  ],\n  \"mails2_0Content\": [\n    {\n      \"children\": [\n        {\n          \"type\": 1,\n          \"value\": \"selfName\"\n        },\n        {\n          \"type\": 0,\n          \"value\": \",\"\n        }\n      ],\n      \"type\": 8,\n      \"value\": \"p\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \"\\n\"\n    },\n    {\n      \"children\": [\n        {\n          \"type\": 0,\n          \"value\": \"After talking with Rick, we've decided that it's not fair to make you complete training without compensating you. Hopefully your sitting down for this, because I've got some thrilling news.\"\n        }\n      ],\n      \"type\": 8,\n      \"value\": \"p\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \"\\n\"\n    },\n    {\n      \"children\": [\n        {\n          \"children\": [\n            {\n              \"type\": 0,\n              \"value\": \"We're providing free pizza lunches to all trainees!\"\n            }\n          ],\n          \"type\": 8,\n          \"value\": \"strong\"\n        }\n      ],\n      \"type\": 8,\n      \"value\": \"p\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \"\\n\"\n    },\n    {\n      \"children\": [\n        {\n          \"type\": 0,\n          \"value\": \"See? I told you I'd make it up to you.\"\n        }\n      ],\n      \"type\": 8,\n      \"value\": \"p\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \"\\n\"\n    },\n    {\n      \"children\": [\n        {\n          \"type\": 0,\n          \"value\": \"Thanks for working hard!\"\n        }\n      ],\n      \"type\": 8,\n      \"value\": \"p\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \"\\n\"\n    },\n    {\n      \"children\": [\n        {\n          \"type\": 0,\n          \"value\": \"-Don\"\n        }\n      ],\n      \"type\": 8,\n      \"value\": \"p\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \"\\n\"\n    }\n  ],\n  \"mails2_0Subject\": [\n    {\n      \"type\": 0,\n      \"value\": \"Good news!\"\n    }\n  ],\n  \"mails2_1Content\": [\n    {\n      \"children\": [\n        {\n          \"type\": 0,\n          \"value\": \"Hi, \"\n        },\n        {\n          \"type\": 1,\n          \"value\": \"selfName\"\n        },\n        {\n          \"type\": 0,\n          \"value\": \", I'm Ted. We met in the hallway earlier.\"\n        }\n      ],\n      \"type\": 8,\n      \"value\": \"p\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \"\\n\"\n    },\n    {\n      \"children\": [\n        {\n          \"type\": 0,\n          \"value\": \"Is there any chance you could come over to my cubicle and help me with the first assessment? I'd ask Feng for help, but I haven't seen him around yet this morning.\"\n        }\n      ],\n      \"type\": 8,\n      \"value\": \"p\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \"\\n\"\n    },\n    {\n      \"children\": [\n        {\n          \"type\": 0,\n          \"value\": \"Yesterday, Feng mentioned something about just using a label that initially points to the value zero, but what does that even mean??? He also said something about being able to reset a variable back to zero by subtracting itself. Is that a thing? I'm so lost!\"\n        }\n      ],\n      \"type\": 8,\n      \"value\": \"p\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \"\\n\"\n    },\n    {\n      \"children\": [\n        {\n          \"type\": 0,\n          \"value\": \"Thanks for your time!\"\n        }\n      ],\n      \"type\": 8,\n      \"value\": \"p\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \"\\n\"\n    },\n    {\n      \"children\": [\n        {\n          \"type\": 0,\n          \"value\": \"-Ted\"\n        }\n      ],\n      \"type\": 8,\n      \"value\": \"p\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \"\\n\"\n    }\n  ],\n  \"mails2_1Subject\": [\n    {\n      \"type\": 0,\n      \"value\": \"Help!\"\n    }\n  ],\n  \"mails30_0Content\": [\n    {\n      \"children\": [\n        {\n          \"type\": 0,\n          \"value\": \"Truly amazing work, \"\n        },\n        {\n          \"type\": 1,\n          \"value\": \"selfName\"\n        },\n        {\n          \"type\": 0,\n          \"value\": \"!\"\n        }\n      ],\n      \"type\": 8,\n      \"value\": \"p\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \"\\n\"\n    },\n    {\n      \"children\": [\n        {\n          \"type\": 0,\n          \"value\": \"Thank you from the bottom of my heart for all of the sacrifices you've made to get us to this point. The SIC-1 is now able to reason about its own code. This is an amazing breakthrough and you should be very proud.\"\n        }\n      ],\n      \"type\": 8,\n      \"value\": \"p\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \"\\n\"\n    },\n    {\n      \"children\": [\n        {\n          \"type\": 0,\n          \"value\": \"Now that we've reached this exciting milestone (thanks to your tireless efforts!), SIC Systems honestly can't challenge someone with your peerless talent. Excitingly, you can now begin the next phase of your career at one of the many other technology companies around the world. I know parting ways is tough, but SIC Systems is a business, not a family, so we have to say goodbye to employees once they're no longer needed. Thank you one last time, and best of luck in your future endeavors!\"\n        }\n      ],\n      \"type\": 8,\n      \"value\": \"p\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \"\\n\"\n    },\n    {\n      \"children\": [\n        {\n          \"type\": 0,\n          \"value\": \"-Ilano\"\n        }\n      ],\n      \"type\": 8,\n      \"value\": \"p\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \"\\n\"\n    }\n  ],\n  \"mails30_0Subject\": [\n    {\n      \"type\": 0,\n      \"value\": \"Unbelievable work!\"\n    }\n  ],\n  \"mails31_0Content\": [\n    {\n      \"children\": [\n        {\n          \"type\": 1,\n          \"value\": \"selfName\"\n        },\n        {\n          \"type\": 0,\n          \"value\": \",\"\n        }\n      ],\n      \"type\": 8,\n      \"value\": \"p\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \"\\n\"\n    },\n    {\n      \"children\": [\n        {\n          \"type\": 0,\n          \"value\": \"It's great to hear from you!\"\n        }\n      ],\n      \"type\": 8,\n      \"value\": \"p\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \"\\n\"\n    },\n    {\n      \"children\": [\n        {\n          \"type\": 0,\n          \"value\": \"I heard that SIC Systems let you go immediately after you demoed your (incomplete) self-hosting program. Ilano is going to be kicking himself when he realizes that the implementation SIC Systems owns doesn't support self-modifying code!\"\n        }\n      ],\n      \"type\": 8,\n      \"value\": \"p\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \"\\n\"\n    },\n    {\n      \"children\": [\n        {\n          \"type\": 0,\n          \"value\": \"Now that you're solely in possession of the only \"\n        },\n        {\n          \"children\": [\n            {\n              \"type\": 0,\n              \"value\": \"truly\"\n            }\n          ],\n          \"type\": 8,\n          \"value\": \"em\"\n        },\n        {\n          \"type\": 0,\n          \"value\": \" self-hosting program for the SIC-1, my advice is: destroy it. Erase all copies, set them on fire, and bury the ashes out in the desert. Ilano doesn't deserve to ever take advantage of your work again.\"\n        }\n      ],\n      \"type\": 8,\n      \"value\": \"p\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \"\\n\"\n    },\n    {\n      \"children\": [\n        {\n          \"type\": 0,\n          \"value\": \"Speaking of work, I wanted to let you know that I found a job at a small startup that is working on a home computer with a graphical interface. It's revolutionary stuff, and we need someone with your technical skills to go to market.\"\n        }\n      ],\n      \"type\": 8,\n      \"value\": \"p\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \"\\n\"\n    },\n    {\n      \"children\": [\n        {\n          \"type\": 0,\n          \"value\": \"Is there any chance you'd be open to discussing a lead engineering position over here?\"\n        }\n      ],\n      \"type\": 8,\n      \"value\": \"p\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \"\\n\"\n    },\n    {\n      \"children\": [\n        {\n          \"type\": 0,\n          \"value\": \"If you're interested, let me know and I'll schedule a meeting with us and the two remaining founders (both named Steve, by coincidence).\"\n        }\n      ],\n      \"type\": 8,\n      \"value\": \"p\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \"\\n\"\n    },\n    {\n      \"children\": [\n        {\n          \"type\": 0,\n          \"value\": \"Hope to hear from you soon!\"\n        }\n      ],\n      \"type\": 8,\n      \"value\": \"p\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \"\\n\"\n    },\n    {\n      \"children\": [\n        {\n          \"type\": 0,\n          \"value\": \"-Pat\"\n        }\n      ],\n      \"type\": 8,\n      \"value\": \"p\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \"\\n\"\n    }\n  ],\n  \"mails31_0Subject\": [\n    {\n      \"type\": 0,\n      \"value\": \"Great to hear from you!\"\n    }\n  ],\n  \"mails3_0Content\": [\n    {\n      \"children\": [\n        {\n          \"type\": 0,\n          \"value\": \"Thanks for completing your training, \"\n        },\n        {\n          \"type\": 1,\n          \"value\": \"selfName\"\n        },\n        {\n          \"type\": 0,\n          \"value\": \"! Your starting job title is: \"\n        },\n        {\n          \"children\": [\n            {\n              \"type\": 1,\n              \"value\": \"jobTitle\"\n            }\n          ],\n          \"type\": 8,\n          \"value\": \"strong\"\n        },\n        {\n          \"type\": 0,\n          \"value\": \".\"\n        }\n      ],\n      \"type\": 8,\n      \"value\": \"p\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \"\\n\"\n    },\n    {\n      \"children\": [\n        {\n          \"type\": 0,\n          \"value\": \"Your finalized compensation package is described in the packet I left on your desk. As always, let me know if you have any questions.\"\n        }\n      ],\n      \"type\": 8,\n      \"value\": \"p\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \"\\n\"\n    },\n    {\n      \"children\": [\n        {\n          \"type\": 0,\n          \"value\": \"Thank you!\"\n        }\n      ],\n      \"type\": 8,\n      \"value\": \"p\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \"\\n\"\n    },\n    {\n      \"children\": [\n        {\n          \"type\": 0,\n          \"value\": \"-Mary\"\n        }\n      ],\n      \"type\": 8,\n      \"value\": \"p\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \"\\n\"\n    }\n  ],\n  \"mails3_0Subject\": [\n    {\n      \"type\": 0,\n      \"value\": \"Training complete!\"\n    }\n  ],\n  \"mails3_1Content\": [\n    {\n      \"children\": [\n        {\n          \"type\": 0,\n          \"value\": \"Greetings, \"\n        },\n        {\n          \"type\": 1,\n          \"value\": \"selfName\"\n        },\n        {\n          \"type\": 0,\n          \"value\": \". I'm also on Don's team and my name is Feng. Let me know if you ever need any assistance.\"\n        }\n      ],\n      \"type\": 8,\n      \"value\": \"p\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \"\\n\"\n    },\n    {\n      \"children\": [\n        {\n          \"type\": 0,\n          \"value\": \"After helping Ted with the first assessment, I thought I'd share my perspective on how to think about SIC-1 Assembly Language:\"\n        }\n      ],\n      \"type\": 8,\n      \"value\": \"p\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \"\\n\"\n    },\n    {\n      \"children\": [\n        {\n          \"type\": 0,\n          \"value\": \"\\n\"\n        },\n        {\n          \"children\": [\n            {\n              \"children\": [\n                {\n                  \"type\": 0,\n                  \"value\": \"Addresses\"\n                }\n              ],\n              \"type\": 8,\n              \"value\": \"strong\"\n            },\n            {\n              \"type\": 0,\n              \"value\": \" are just numbers that identify a specific byte of memory (0 for the first byte, 1 for the second, and so on, up to 255)\"\n            }\n          ],\n          \"type\": 8,\n          \"value\": \"li\"\n        },\n        {\n          \"type\": 0,\n          \"value\": \"\\n\"\n        },\n        {\n          \"children\": [\n            {\n              \"children\": [\n                {\n                  \"type\": 0,\n                  \"value\": \"Labels\"\n                }\n              ],\n              \"type\": 8,\n              \"value\": \"strong\"\n            },\n            {\n              \"type\": 0,\n              \"value\": \" are just names for addresses--specifically, the address of whatever comes next in your code (whether it's a \"\n            },\n            {\n              \"children\": [\n                {\n                  \"type\": 0,\n                  \"value\": \"subleq\"\n                }\n              ],\n              \"type\": 8,\n              \"value\": \"code\"\n            },\n            {\n              \"type\": 0,\n              \"value\": \" or a \"\n            },\n            {\n              \"children\": [\n                {\n                  \"type\": 0,\n                  \"value\": \".data\"\n                }\n              ],\n              \"type\": 8,\n              \"value\": \"code\"\n            },\n            {\n              \"type\": 0,\n              \"value\": \")\"\n            }\n          ],\n          \"type\": 8,\n          \"value\": \"li\"\n        },\n        {\n          \"type\": 0,\n          \"value\": \"\\n\"\n        },\n        {\n          \"children\": [\n            {\n              \"children\": [\n                {\n                  \"type\": 0,\n                  \"value\": \"subleq\"\n                }\n              ],\n              \"type\": 8,\n              \"value\": \"code\"\n            },\n            {\n              \"type\": 0,\n              \"value\": \" always compiles into 3 bytes (each one an address)--if you omit the third address, it just gets set to the address of the next instruction in memory\"\n            }\n          ],\n          \"type\": 8,\n          \"value\": \"li\"\n        },\n        {\n          \"type\": 0,\n          \"value\": \"\\n\"\n        },\n        {\n          \"children\": [\n            {\n              \"children\": [\n                {\n                  \"type\": 0,\n                  \"value\": \".data\"\n                }\n              ],\n              \"type\": 8,\n              \"value\": \"code\"\n            },\n            {\n              \"type\": 0,\n              \"value\": \" just sets one or more bytes of memory to specific values (positive or negative numbers, or even labels, i.e. addresses)\"\n            }\n          ],\n          \"type\": 8,\n          \"value\": \"li\"\n        },\n        {\n          \"type\": 0,\n          \"value\": \"\\n\"\n        }\n      ],\n      \"type\": 8,\n      \"value\": \"ul\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \"\\n\"\n    },\n    {\n      \"children\": [\n        {\n          \"type\": 0,\n          \"value\": \"In the end, everything compiles down to bytes in memory (which you can see in the memory table after you click \\\"Compile\\\" or \\\"Run\\\" to load the program). While running, the SIC-1 only sees those bytes in memory, and it doesn't know or care how those bytes were produced (or even modified). It will happily interpret any 3 bytes as a \"\n        },\n        {\n          \"children\": [\n            {\n              \"type\": 0,\n              \"value\": \"subleq\"\n            }\n          ],\n          \"type\": 8,\n          \"value\": \"code\"\n        },\n        {\n          \"type\": 0,\n          \"value\": \" instruction--even if that's not what you intended.\"\n        }\n      ],\n      \"type\": 8,\n      \"value\": \"p\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \"\\n\"\n    },\n    {\n      \"children\": [\n        {\n          \"type\": 0,\n          \"value\": \"It can be instructive to look at a chunk of code and see the resulting compiled bytes. Here's an example:\"\n        }\n      ],\n      \"type\": 8,\n      \"value\": \"p\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \"\\n\"\n    },\n    {\n      \"children\": [\n        {\n          \"children\": [\n            {\n              \"type\": 0,\n              \"value\": \"@loop:\\nsubleq @OUT, @IN           ; 3 byte instruction stored at address 0\\nsubleq @zero, @zero, @loop ; 3 byte instruction stored at address 3\\n\\n@zero: .data 0             ; Initializes address 6 to zero\\n\"\n            }\n          ],\n          \"type\": 8,\n          \"value\": \"code\"\n        }\n      ],\n      \"type\": 8,\n      \"value\": \"pre\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \"\\n\"\n    },\n    {\n      \"children\": [\n        {\n          \"type\": 0,\n          \"value\": \"\\n\"\n        },\n        {\n          \"children\": [\n            {\n              \"children\": [\n                {\n                  \"type\": 0,\n                  \"value\": \"@loop\"\n                }\n              ],\n              \"type\": 8,\n              \"value\": \"code\"\n            },\n            {\n              \"type\": 0,\n              \"value\": \" refers to address 0, i.e. the first instruction\"\n            }\n          ],\n          \"type\": 8,\n          \"value\": \"li\"\n        },\n        {\n          \"type\": 0,\n          \"value\": \"\\n\"\n        },\n        {\n          \"children\": [\n            {\n              \"type\": 0,\n              \"value\": \"The first \"\n            },\n            {\n              \"children\": [\n                {\n                  \"type\": 0,\n                  \"value\": \"subleq\"\n                }\n              ],\n              \"type\": 8,\n              \"value\": \"code\"\n            },\n            {\n              \"type\": 0,\n              \"value\": \" occupies bytes 0, 1, and 2, and is compiled to: 254 (\"\n            },\n            {\n              \"children\": [\n                {\n                  \"type\": 0,\n                  \"value\": \"@OUT\"\n                }\n              ],\n              \"type\": 8,\n              \"value\": \"code\"\n            },\n            {\n              \"type\": 0,\n              \"value\": \"), 253 (\"\n            },\n            {\n              \"children\": [\n                {\n                  \"type\": 0,\n                  \"value\": \"@IN\"\n                }\n              ],\n              \"type\": 8,\n              \"value\": \"code\"\n            },\n            {\n              \"type\": 0,\n              \"value\": \"), 3 (the next instruction)\"\n            }\n          ],\n          \"type\": 8,\n          \"value\": \"li\"\n        },\n        {\n          \"type\": 0,\n          \"value\": \"\\n\"\n        },\n        {\n          \"children\": [\n            {\n              \"type\": 0,\n              \"value\": \"The second \"\n            },\n            {\n              \"children\": [\n                {\n                  \"type\": 0,\n                  \"value\": \"subleq\"\n                }\n              ],\n              \"type\": 8,\n              \"value\": \"code\"\n            },\n            {\n              \"type\": 0,\n              \"value\": \" occupies bytes 3, 4, and 5, and is compiled to: 6 (\"\n            },\n            {\n              \"children\": [\n                {\n                  \"type\": 0,\n                  \"value\": \"@zero\"\n                }\n              ],\n              \"type\": 8,\n              \"value\": \"code\"\n            },\n            {\n              \"type\": 0,\n              \"value\": \"), 6 (\"\n            },\n            {\n              \"children\": [\n                {\n                  \"type\": 0,\n                  \"value\": \"@zero\"\n                }\n              ],\n              \"type\": 8,\n              \"value\": \"code\"\n            },\n            {\n              \"type\": 0,\n              \"value\": \"), 0 (\"\n            },\n            {\n              \"children\": [\n                {\n                  \"type\": 0,\n                  \"value\": \"@loop\"\n                }\n              ],\n              \"type\": 8,\n              \"value\": \"code\"\n            },\n            {\n              \"type\": 0,\n              \"value\": \")\"\n            }\n          ],\n          \"type\": 8,\n          \"value\": \"li\"\n        },\n        {\n          \"type\": 0,\n          \"value\": \"\\n\"\n        },\n        {\n          \"children\": [\n            {\n              \"children\": [\n                {\n                  \"type\": 0,\n                  \"value\": \"@zero\"\n                }\n              ],\n              \"type\": 8,\n              \"value\": \"code\"\n            },\n            {\n              \"type\": 0,\n              \"value\": \" refers to address 6, i.e. the next byte (which is initialized to zero using the \"\n            },\n            {\n              \"children\": [\n                {\n                  \"type\": 0,\n                  \"value\": \".data\"\n                }\n              ],\n              \"type\": 8,\n              \"value\": \"code\"\n            },\n            {\n              \"type\": 0,\n              \"value\": \" directive)\"\n            }\n          ],\n          \"type\": 8,\n          \"value\": \"li\"\n        },\n        {\n          \"type\": 0,\n          \"value\": \"\\n\"\n        }\n      ],\n      \"type\": 8,\n      \"value\": \"ul\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \"\\n\"\n    },\n    {\n      \"children\": [\n        {\n          \"type\": 0,\n          \"value\": \"As you know by now, the first instruction negates an input and writes it out, then advances to the next instruction (regardless of the result). The second instruction subtracts the value at address 6 from itself, always resulting in zero, and thus always jumps to its third argument: \"\n        },\n        {\n          \"children\": [\n            {\n              \"type\": 0,\n              \"value\": \"@loop\"\n            }\n          ],\n          \"type\": 8,\n          \"value\": \"code\"\n        },\n        {\n          \"type\": 0,\n          \"value\": \", i.e. address 0 (the beginning of the program).\"\n        }\n      ],\n      \"type\": 8,\n      \"value\": \"p\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \"\\n\"\n    },\n    {\n      \"children\": [\n        {\n          \"type\": 0,\n          \"value\": \"Hope that helps!\"\n        }\n      ],\n      \"type\": 8,\n      \"value\": \"p\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \"\\n\"\n    },\n    {\n      \"children\": [\n        {\n          \"type\": 0,\n          \"value\": \"-Feng\"\n        }\n      ],\n      \"type\": 8,\n      \"value\": \"p\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \"\\n\"\n    }\n  ],\n  \"mails3_1Subject\": [\n    {\n      \"type\": 0,\n      \"value\": \"My mental model for SIC-1\"\n    }\n  ],\n  \"mails4_0Content\": [\n    {\n      \"children\": [\n        {\n          \"type\": 0,\n          \"value\": \"Hey, \"\n        },\n        {\n          \"type\": 1,\n          \"value\": \"selfName\"\n        },\n        {\n          \"type\": 0,\n          \"value\": \"! How's it feel to be a full-time employee working on the cutting edge of revolutionary technology? Only a single instruction! Amazing!\"\n        }\n      ],\n      \"type\": 8,\n      \"value\": \"p\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \"\\n\"\n    },\n    {\n      \"children\": [\n        {\n          \"type\": 0,\n          \"value\": \"Anyway, I did see your question about the compensation package Mary provided to you. I apologize if the pay is lower than what you were expecting. Another HR mix-up! What can I say?\"\n        }\n      ],\n      \"type\": 8,\n      \"value\": \"p\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \"\\n\"\n    },\n    {\n      \"children\": [\n        {\n          \"type\": 0,\n          \"value\": \"I'll talk to Rick to see if we can make an exception and raise your pay immediately, but just keep in mind that this company has a lot of room to grow, so your hard efforts will be very well rewarded!\"\n        }\n      ],\n      \"type\": 8,\n      \"value\": \"p\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \"\\n\"\n    },\n    {\n      \"children\": [\n        {\n          \"type\": 0,\n          \"value\": \"-Don\"\n        }\n      ],\n      \"type\": 8,\n      \"value\": \"p\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \"\\n\"\n    }\n  ],\n  \"mails4_0Subject\": [\n    {\n      \"type\": 0,\n      \"value\": \"Checking in\"\n    }\n  ],\n  \"mails4_1Content\": [\n    {\n      \"children\": [\n        {\n          \"type\": 0,\n          \"value\": \"Greetings, \"\n        },\n        {\n          \"type\": 1,\n          \"value\": \"selfName\"\n        },\n        {\n          \"type\": 0,\n          \"value\": \".\"\n        }\n      ],\n      \"type\": 8,\n      \"value\": \"p\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \"\\n\"\n    },\n    {\n      \"children\": [\n        {\n          \"type\": 0,\n          \"value\": \"I wanted to share with you a little side project I've been working on. I'm calling it \\\"Sandbox Mode\\\". Basically, it's a special SIC-1 Emulator mode that allows you to specify your own input.\"\n        }\n      ],\n      \"type\": 8,\n      \"value\": \"p\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \"\\n\"\n    },\n    {\n      \"children\": [\n        {\n          \"type\": 0,\n          \"value\": \"This is useful when you just want to play around with the SIC-1 to see how things work. You can experiment with this to test out new techniques without worrying about output getting flagged as incorrect.\"\n        }\n      ],\n      \"type\": 8,\n      \"value\": \"p\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \"\\n\"\n    },\n    {\n      \"children\": [\n        {\n          \"type\": 0,\n          \"value\": \"Sandbox Mode should be visible up in your Program Inventory under the \\\"Diversions\\\" group.\"\n        }\n      ],\n      \"type\": 8,\n      \"value\": \"p\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \"\\n\"\n    },\n    {\n      \"children\": [\n        {\n          \"type\": 0,\n          \"value\": \"Let me know what you think!\"\n        }\n      ],\n      \"type\": 8,\n      \"value\": \"p\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \"\\n\"\n    },\n    {\n      \"children\": [\n        {\n          \"type\": 0,\n          \"value\": \"-Feng\"\n        }\n      ],\n      \"type\": 8,\n      \"value\": \"p\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \"\\n\"\n    }\n  ],\n  \"mails4_1Subject\": [\n    {\n      \"type\": 0,\n      \"value\": \"Sandbox Mode\"\n    }\n  ],\n  \"mails5_0Content\": [\n    {\n      \"children\": [\n        {\n          \"type\": 0,\n          \"value\": \"Greetings, \"\n        },\n        {\n          \"type\": 1,\n          \"value\": \"selfName\"\n        },\n        {\n          \"type\": 0,\n          \"value\": \".\"\n        }\n      ],\n      \"type\": 8,\n      \"value\": \"p\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \"\\n\"\n    },\n    {\n      \"children\": [\n        {\n          \"type\": 0,\n          \"value\": \"After talking to Ted, I thought this might be a good time to remind everyone that you can use labels for both variables \"\n        },\n        {\n          \"children\": [\n            {\n              \"type\": 0,\n              \"value\": \"and constants\"\n            }\n          ],\n          \"type\": 8,\n          \"value\": \"em\"\n        },\n        {\n          \"type\": 0,\n          \"value\": \". A label is really just an address, after all.\"\n        }\n      ],\n      \"type\": 8,\n      \"value\": \"p\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \"\\n\"\n    },\n    {\n      \"children\": [\n        {\n          \"type\": 0,\n          \"value\": \"For example, if I want to be able to write out a 1, I could create a constant. Just remember that if you're subtracting the constant you'll want to negate the constant:\"\n        }\n      ],\n      \"type\": 8,\n      \"value\": \"p\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \"\\n\"\n    },\n    {\n      \"children\": [\n        {\n          \"children\": [\n            {\n              \"type\": 0,\n              \"value\": \"subleq @OUT, @n_one ; Write out a 1 by subtracting -1 from @OUT\\n                    ; Note: @OUT always reads as zero: 0 - (-1) = 1\\n\\n@n_one: .data -1    ; Constant\\n\"\n            }\n          ],\n          \"type\": 8,\n          \"value\": \"code\"\n        }\n      ],\n      \"type\": 8,\n      \"value\": \"pre\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \"\\n\"\n    },\n    {\n      \"children\": [\n        {\n          \"type\": 0,\n          \"value\": \"-Feng\"\n        }\n      ],\n      \"type\": 8,\n      \"value\": \"p\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \"\\n\"\n    }\n  ],\n  \"mails5_0Subject\": [\n    {\n      \"type\": 0,\n      \"value\": \"Constants\"\n    }\n  ],\n  \"mails6_0Content\": [\n    {\n      \"children\": [\n        {\n          \"type\": 1,\n          \"value\": \"selfName\"\n        },\n        {\n          \"type\": 0,\n          \"value\": \", I'm really stuck! Do you have any time to come help me with the multiplication task?\"\n        }\n      ],\n      \"type\": 8,\n      \"value\": \"p\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \"\\n\"\n    },\n    {\n      \"children\": [\n        {\n          \"type\": 0,\n          \"value\": \"I already asked Feng for some help, but all he told me is that I could run a loop a specific number of times by subtracting 1 from a counter each time and then using the result to branch.\"\n        }\n      ],\n      \"type\": 8,\n      \"value\": \"p\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \"\\n\"\n    },\n    {\n      \"children\": [\n        {\n          \"type\": 0,\n          \"value\": \"What does that even mean???\"\n        }\n      ],\n      \"type\": 8,\n      \"value\": \"p\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \"\\n\"\n    },\n    {\n      \"children\": [\n        {\n          \"type\": 0,\n          \"value\": \"-Ted\"\n        }\n      ],\n      \"type\": 8,\n      \"value\": \"p\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \"\\n\"\n    }\n  ],\n  \"mails6_0Subject\": [\n    {\n      \"type\": 0,\n      \"value\": \"Loops???\"\n    }\n  ],\n  \"mails7_0Content\": [\n    {\n      \"children\": [\n        {\n          \"type\": 0,\n          \"value\": \"Hi, \"\n        },\n        {\n          \"type\": 1,\n          \"value\": \"selfName\"\n        },\n        {\n          \"type\": 0,\n          \"value\": \"! I'm Pat and I'm another engineering lead (I actually work on the same team as your manager, Don).\"\n        }\n      ],\n      \"type\": 8,\n      \"value\": \"p\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \"\\n\"\n    },\n    {\n      \"children\": [\n        {\n          \"type\": 0,\n          \"value\": \"Feng (who used to report to me) mentioned that you've been making excellent progress!\"\n        }\n      ],\n      \"type\": 8,\n      \"value\": \"p\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \"\\n\"\n    },\n    {\n      \"children\": [\n        {\n          \"type\": 0,\n          \"value\": \"Anyway, I've been tasked with helping to improve morale across the team, so if there's anything that you especially like or don't like about the workplace or your compensation (or your team in general), feel free to send me a mail. I'll make sure to keep all discussions private.\"\n        }\n      ],\n      \"type\": 8,\n      \"value\": \"p\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \"\\n\"\n    },\n    {\n      \"children\": [\n        {\n          \"type\": 0,\n          \"value\": \"Looking forward to hearing from you!\"\n        }\n      ],\n      \"type\": 8,\n      \"value\": \"p\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \"\\n\"\n    },\n    {\n      \"children\": [\n        {\n          \"type\": 0,\n          \"value\": \"-Pat\"\n        }\n      ],\n      \"type\": 8,\n      \"value\": \"p\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \"\\n\"\n    }\n  ],\n  \"mails7_0Subject\": [\n    {\n      \"type\": 0,\n      \"value\": \"Nice work!\"\n    }\n  ],\n  \"mails7_1Content\": [\n    {\n      \"children\": [\n        {\n          \"type\": 0,\n          \"value\": \"Engineering team,\"\n        }\n      ],\n      \"type\": 8,\n      \"value\": \"p\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \"\\n\"\n    },\n    {\n      \"children\": [\n        {\n          \"type\": 0,\n          \"value\": \"To help improve morale, SIC Systems has provided an officially sanctioned computer video game called \\\"Avoision\\\" for employees to play. If you think your work would benefit from an entertaining diversion, please feel free to compete against your coworkers for the highest score in \\\"Avoision\\\" (during your two legally-mandated unpaid breaks, or in lieu of an unneeded bathroom break).\"\n        }\n      ],\n      \"type\": 8,\n      \"value\": \"p\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \"\\n\"\n    },\n    {\n      \"children\": [\n        {\n          \"type\": 0,\n          \"value\": \"You can find \\\"Avoision\\\" in the \\\"Diversions\\\" section of the program inventory and also in the main menu of the SIC-1 Development Environment.\"\n        }\n      ],\n      \"type\": 8,\n      \"value\": \"p\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \"\\n\"\n    },\n    {\n      \"children\": [\n        {\n          \"type\": 0,\n          \"value\": \"Enjoy!\"\n        }\n      ],\n      \"type\": 8,\n      \"value\": \"p\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \"\\n\"\n    },\n    {\n      \"children\": [\n        {\n          \"type\": 0,\n          \"value\": \"-Mary\"\n        }\n      ],\n      \"type\": 8,\n      \"value\": \"p\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \"\\n\"\n    }\n  ],\n  \"mails7_1Subject\": [\n    {\n      \"type\": 0,\n      \"value\": \"Fun and games\"\n    }\n  ],\n  \"mails8_0Content\": [\n    {\n      \"children\": [\n        {\n          \"type\": 0,\n          \"value\": \"Nice work on the arithmetic programs, \"\n        },\n        {\n          \"type\": 1,\n          \"value\": \"selfName\"\n        },\n        {\n          \"type\": 0,\n          \"value\": \"! As of this electronic mail, you have been promoted to \"\n        },\n        {\n          \"children\": [\n            {\n              \"type\": 1,\n              \"value\": \"jobTitle\"\n            }\n          ],\n          \"type\": 8,\n          \"value\": \"strong\"\n        },\n        {\n          \"type\": 0,\n          \"value\": \".\"\n        }\n      ],\n      \"type\": 8,\n      \"value\": \"p\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \"\\n\"\n    },\n    {\n      \"children\": [\n        {\n          \"type\": 0,\n          \"value\": \"I know it's getting late (and please try to keep this to yourself), but our team really needs to improve our velocity. If there's any way you can stay late and complete your next task \"\n        },\n        {\n          \"children\": [\n            {\n              \"type\": 0,\n              \"value\": \"today\"\n            }\n          ],\n          \"type\": 8,\n          \"value\": \"em\"\n        },\n        {\n          \"type\": 0,\n          \"value\": \", there is a very good chance that I'll be able to promote you to Senior Engineer (and that comes with a hefty pay bump).\"\n        }\n      ],\n      \"type\": 8,\n      \"value\": \"p\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \"\\n\"\n    },\n    {\n      \"children\": [\n        {\n          \"type\": 0,\n          \"value\": \"Again, keep this to yourself. This sort of rapid promotion is extremely rare. Obviously, I can't guarantee anything, but if you can knuckle down and churn out this next task, things are looking pretty good...\"\n        }\n      ],\n      \"type\": 8,\n      \"value\": \"p\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \"\\n\"\n    },\n    {\n      \"children\": [\n        {\n          \"type\": 0,\n          \"value\": \"Thank you!\"\n        }\n      ],\n      \"type\": 8,\n      \"value\": \"p\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \"\\n\"\n    },\n    {\n      \"children\": [\n        {\n          \"type\": 0,\n          \"value\": \"-Don\"\n        }\n      ],\n      \"type\": 8,\n      \"value\": \"p\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \"\\n\"\n    }\n  ],\n  \"mails8_0Subject\": [\n    {\n      \"type\": 0,\n      \"value\": \"Great start!\"\n    }\n  ],\n  \"mails9_0Content\": [\n    {\n      \"children\": [\n        {\n          \"type\": 0,\n          \"value\": \"Don (and Don's team),\"\n        }\n      ],\n      \"type\": 8,\n      \"value\": \"p\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \"\\n\"\n    },\n    {\n      \"children\": [\n        {\n          \"type\": 0,\n          \"value\": \"In recognition of Don's tireless efforts that have recently culminated in the ability of the SIC-1 to process sequences, I'd like everyone to join me in congratulating Don on his promotion to Principal Engineering Lead!\"\n        }\n      ],\n      \"type\": 8,\n      \"value\": \"p\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \"\\n\"\n    },\n    {\n      \"children\": [\n        {\n          \"type\": 0,\n          \"value\": \"Don, I don't know how you managed to get sequences up and running so quickly, but we all owe a great debt to you.\"\n        }\n      ],\n      \"type\": 8,\n      \"value\": \"p\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \"\\n\"\n    },\n    {\n      \"children\": [\n        {\n          \"type\": 0,\n          \"value\": \"Thank you once again!\"\n        }\n      ],\n      \"type\": 8,\n      \"value\": \"p\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \"\\n\"\n    },\n    {\n      \"children\": [\n        {\n          \"type\": 0,\n          \"value\": \"-Rick\"\n        }\n      ],\n      \"type\": 8,\n      \"value\": \"p\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \"\\n\"\n    }\n  ],\n  \"mails9_0Subject\": [\n    {\n      \"type\": 0,\n      \"value\": \"Congratulations, Don!\"\n    }\n  ],\n  \"manualHeading\": [\n    {\n      \"children\": [\n        {\n          \"type\": 0,\n          \"value\": \"SIC-1 Reference Manual\"\n        }\n      ],\n      \"type\": 8,\n      \"value\": \"h1\"\n    },\n    {\n      \"children\": [\n        {\n          \"type\": 0,\n          \"value\": \"(C) 1979 - 1980 SIC Systems, Inc.\"\n        }\n      ],\n      \"type\": 8,\n      \"value\": \"p\"\n    }\n  ],\n  \"manualTitle\": [\n    {\n      \"type\": 0,\n      \"value\": \"SIC-1 Manual\"\n    }\n  ],\n  \"puzzleCodeAddition\": [\n    {\n      \"type\": 0,\n      \"value\": \"; Read two numbers and output their sum. Repeat.\\n;\\n; Below is the solution to the previous task. You will need to add additional code to perform addition of two inputs (instead of passing through a single input):\\n\\n@loop:\\nsubleq @tmp, @IN\\nsubleq @OUT, @tmp\\nsubleq @tmp, @tmp, @loop  ; Reset @tmp to zero, and jump to @loop\\n\\n@tmp: .data 0\\n\"\n    }\n  ],\n  \"puzzleCodeCharacters\": [\n    {\n      \"type\": 0,\n      \"value\": \"; When configured properly, the SIC-1 supports natural human language input and output using a highly modern (c. 1967) mapping from numbers to characters known as ASCII. For example, 72 is mapped to \\\"H\\\" (capital \\\"h\\\").\\n;\\n; To capture the characters \\\"Hi\\\" (capital \\\"h\\\", lower case \\\"i\\\") in two variables, one could consult an ASCII lookup table and write:\\n;\\n;   @H: .data 72\\n;   @i: .data 105\\n;\\n; Consulting an ASCII table is tedious, so to make SIC Systems engineers' lives easier, SIC-1 Assembly Language now supports automated ASCII lookup using the following advanced syntax (which is equivalent to explicitly specifying characters' mapped numbers):\\n;\\n;   @H: .data 'H' ; 72\\n;   @i: .data 'i' ; 105\\n;\\n; As a final convenience, it is possible to negate the value of a character by prefixing the character literal with a minus:\\n;\\n;   @n_H: .data -'H' ; -72\\n;\\n; The following sample program outputs the characters \\\"Hi\\\":\\n\\nsubleq @OUT, @n_H ; Note: (0 - (-72) = 72 = 'H')\\nsubleq @OUT, @n_i\\n\\n@n_H: .data -'H'\\n@n_i: .data -'i'\\n\"\n    }\n  ],\n  \"puzzleCodeData Directive and Looping\": [\n    {\n      \"type\": 0,\n      \"value\": \"; Custom labels are defined by putting \\\"@name: \\\" at the beginning of a line, e.g.:\\n;\\n;   @loop: subleq 1, 2\\n;\\n; In addition to \\\"subleq\\\", there is an assembler directive \\\".data\\\" that sets a byte of memory to a value at compile time (note: this is not an instruction!):\\n;\\n;   .data X\\n;\\n; X is a signed byte between -128 and 127 (inclusive).\\n;\\n; Combining labels and the \\\".data\\\" directive allows you to develop a system of constants and variables. For example, here a byte is set to zero, and the label @zero points to that value:\\n;\\n;   @zero: .data 0\\n;\\n; Note that, while a program is executing, you can view the current value of each variable in the variable table on the right (under the memory table).\\n;\\n; Variables can be used for implementing an unconditional jump:\\n;\\n;   subleq @zero, @zero, @next\\n;\\n; This will set @zero to @zero - @zero (still zero) and, since the result is always ≤ 0, execution branches to @next.\\n;\\n; Below is an updated negation program that repeatedly negates input values and writes them out in a loop.\\n\\n@loop:\\nsubleq @OUT, @IN\\nsubleq @zero, @zero, @loop\\n\\n@zero: .data 0\\n\"\n    }\n  ],\n  \"puzzleCodeDecimal Digits\": [\n    {\n      \"type\": 0,\n      \"value\": \"; For this assignment, map each decimal digit character (e.g. '1') to the numeric value it represents (e.g. '1' -> 1). Inputs will be characters, but outputs are expected to be numbers.\\n;\\n; Keep in mind that the character '1' is not the same as the number 1. The ASCII mapping for '1' is actually 49.\\n;\\n; Also note that the ASCII mappings for '0', '1', '2', etc. are contiguous:\\n;\\n; '0' = 48\\n; '1' = 49\\n; '2' = 50\\n; etc.\\n\\n\"\n    }\n  ],\n  \"puzzleCodeFirst Assessment\": [\n    {\n      \"type\": 0,\n      \"value\": \"; Now that you understand the \\\"subleq\\\" instruction, the \\\".data\\\" directive, and labels, you should be able to read values from input and write the exact same values out, by negating the value twice.\\n;\\n; Below is an almost complete solution. You will need to replace instances of \\\"???\\\". Hint: use a label that points to a storage location for a (negated) value.\\n\\n@loop:\\nsubleq ???, @IN\\nsubleq @OUT, ???\\nsubleq @tmp, @tmp, @loop  ; Reset @tmp to zero, and jump to @loop\\n\\n@tmp: .data 0\\n\"\n    }\n  ],\n  \"puzzleCodeMulti-Line Strings\": [\n    {\n      \"type\": 0,\n      \"value\": \"; New line characters (value 10) can be expressed with the character '\\\\n'. They can also be used in strings, for example: \\\"Line 1\\\\nLine 2\\\".\\n;\\n; Read a string with multiple lines and write out each line as a string.\\n\\n\"\n    }\n  ],\n  \"puzzleCodeParse Data Directives\": [\n    {\n      \"type\": 0,\n      \"value\": \"; Parse a program with multiple .data directives and output the corresponding values.\\n;\\n; Each .data directive only has a single value on the range [-128, 127] (inclusive).\\n\\n\"\n    }\n  ],\n  \"puzzleCodeParse Subleq Instructions\": [\n    {\n      \"type\": 0,\n      \"value\": \"; Parse a program with multiple subleq instructions and output the compiled program.\\n;\\n; Each subleq instruction specifies 3 addresses, separated by spaces (' '). The addresses are on the range [0, 255] (inclusive).\\n;\\n; Note that the unsigned (nonnegative) addresses will be written out as signed values on the range [-128, 127] (also inclusive). For example, 255 becomes -1, 254 becomes -2, ..., 128 becomes -128, but 127 and below are unchanged.\\n\\n\"\n    }\n  ],\n  \"puzzleCodeSandbox Mode\": [\n    {\n      \"type\": 0,\n      \"value\": \"; This is an open-ended program that allows specifying arbitrary input to help employees explore how the SIC-1 operates.\\n;\\n; Use the \\\"Configure Input\\\" button to the left (above the IO table) to provide custom input to the program.\"\n    }\n  ],\n  \"puzzleCodeSelf-Hosting\": [\n    {\n      \"type\": 0,\n      \"value\": \"; Parse a program containing .data directives and subleq instructions, then execute that program.\\n;\\n; All addresses used by the input program should be isolated from your program's address space.\\n;\\n; As in any other program, if the program writes to address 254 (@OUT; signed value: -2), that value should be directly written out.\\n;\\n; If the program branches to address 255 (@HALT; signed value: -1), then the program is done. Start over from scratch with the next input program.\\n;\\n; The compiled size of each input program is ≤ 21 bytes.\\n;\\n; As in previous tasks, the .data directive will always have exactly 1 value and subleq instructions will specify exactly 3 addresses (separated by spaces only).\\n;\\n; Additionally, the input programs will not use self-modifying code or declare/use any labels or variables. The only built-in addresses that will be used will be referenced by address instead of label (e.g. \\\"254\\\" will be used but \\\"@OUT\\\" will not).\\n\\n\"\n    }\n  ],\n  \"puzzleCodeSelf-Hosting Part 2\": [\n    {\n      \"type\": 0,\n      \"value\": \"; Parse a self-modifying program containing .data directives and subleq instructions, then execute that program.\\n;\\n; Writes to address @OUT should be directly written out. If the program branches to address @HALT, then the program is done. Start over from scratch with the next input program.\\n;\\n; The compiled size of each input program is ≤ 21 bytes.\\n;\\n; As in previous tasks, the .data directive will always have exactly 1 value and subleq instructions will specify exactly 3 addresses (separated by spaces only) and no labels will be used.\\n\\n\"\n    }\n  ],\n  \"puzzleCodeSelf-Modifying Code\": [\n    {\n      \"type\": 0,\n      \"value\": \"; Label expressions can include an optional offset. For example, @loop+1 refers to the second byte of the instruction pointed to by @loop:\\n;\\n;   subleq @loop+1, @one\\n;\\n; This is useful in self-modifying code. Remember, each \\\"subleq\\\" instruction is stored as 3 consecutive addresses, ABC:\\n;\\n; mem[A] ← mem[A] - mem[B], with a branch to C if the result is less than or equal to zero.\\n;\\n; The sample program below reads its own compiled code. The third instruction is an example of self-modifying code because it actually modifies the first instruction. Specifically, it increments the first instruction's second address (@loop+1). This causes the *next* loop iteration's first instruction to read the *next* byte of memory (0, 1, 2, 3, ...).\\n;\\n; Note: When running a program, the original (unmodified) source code is always shown. If the program modifies itself, the changes are reflected in the memory table in the top right, but *not* in the source code viewer.\\n\\n@loop:\\nsubleq @tmp, 0           ; Second address (initially zero) will be incremented\\nsubleq @OUT, @tmp        ; Output the value\\nsubleq @loop+1, @n_one   ; Here is where the increment is performed\\nsubleq @tmp, @tmp, @loop\\n\\n@tmp: .data 0\\n@n_one: .data -1\\n\"\n    }\n  ],\n  \"puzzleCodeStack Memory\": [\n    {\n      \"type\": 0,\n      \"value\": \"; This program implements a last-in, first-out stack by modifying the read and write addresses of the instructions that interact with the stack.\\n;\\n; The program pushes 3 (defined by @count) input values onto the stack and then pops them off (outputting them in reverse order).\\n\\n; The first address of this instruction (which starts pointing to @stack) will be incremented with each write to the stack\\n\\n@stack_push:\\nsubleq @stack, @IN\\nsubleq @count, @one, @prepare_to_pop\\n\\n; Modify the instruction at @stack_push (increment target address)\\nsubleq @stack_push, @n_one\\nsubleq @tmp, @tmp, @stack_push\\n\\n; Prepare to start popping values off of the stack by copying the current stack position to @stack_pop+1\\n@prepare_to_pop:\\nsubleq @tmp, @stack_push\\nsubleq @stack_pop+1, @tmp\\n\\n; Read a value from the stack (note: the second address of this instruction is repeatedly decremented)\\n@stack_pop:\\nsubleq @OUT, 0\\n\\n; Decrement stack address in the instruction at @stack_pop\\nsubleq @stack_pop+1, @one\\nsubleq @tmp, @tmp, @stack_pop\\n\\n; Constants\\n@one: .data 1\\n@n_one: .data -1\\n\\n; Variables\\n@tmp: .data 0\\n@count: .data 3\\n\\n; Address of @stack (defined below)\\n@stack_address: .data @stack\\n\\n; Base of stack (stack will grow to larger addresses, so no variables should be placed after this one)\\n@stack: .data 0\\n\"\n    }\n  ],\n  \"puzzleCodeStrings\": [\n    {\n      \"type\": 0,\n      \"value\": \"; Strings are sequences of characters that are terminated with a zero. In the following example, @string points to a 3 byte sequence representing the string \\\"Hi\\\":\\n;\\n;   @string:\\n;   .data 'H'\\n;   .data 'i'\\n;   .data 0\\n;\\n; Although not discussed previously, the .data directive can actually take a sequence of values to set multiple bytes, so the previous code could be simplified:\\n;\\n;   @string: .data 'H', 'i', 0\\n;\\n; And thanks to the innovative design-by-committee approach employed by SIC Systems, the following novel syntax for strings can be used (again, equivalent to the other examples):\\n;\\n;   @string: .data \\\"Hi\\\" ; Sets the next 3 bytes: 'H', 'i', 0\\n;\\n; Similar to character values, an entire string can be negated by prefixing it with a minus:\\n;\\n;   @n_string: .data -\\\"Hi\\\" ; Sets the next 3 bytes: -72, -105, 0\\n;\\n; The following code outputs \\\"Hello, world!\\\":\\n\\n@loop:\\nsubleq @OUT, @n_message  ; Read address starts at @n_message\\nsubleq @loop+1, @n_one   ; Advance read address\\nsubleq @tmp, @tmp, @loop\\n\\n@n_one: .data -1\\n@n_message: .data -\\\"Hello, world!\\\"\\n@tmp: .data 0\\n\"\n    }\n  ],\n  \"puzzleCodeSubleq Instruction and Output\": [\n    {\n      \"type\": 0,\n      \"value\": \"; The Single Instruction Computer Mark 1 (SIC-1) is an 8-bit computer with 256 bytes of memory. Programs for the SIC-1 are written in SIC-1 Assembly Language.\\n;\\n; Each instruction is 3 bytes, specified as follows:\\n;\\n;   subleq A B [C]\\n;\\n; A, B, and C are memory addresses (0 - 255) or labels.\\n;\\n; \\\"subleq\\\" subtracts the value at address B from the value at address A and stores the result at address A (i.e. mem[A] ← mem[A] - mem[B]).\\n;\\n; If the result is ≤ 0, execution branches to address C.\\n;\\n; Note that if C is not specified, the address of the next instruction is automatically added by the assembler (in effect, this means that taking the branch is no different from advancing to the next instruction).\\n;\\n; For convenience, addresses can be specified using labels. The following predefined labels are always available:\\n;\\n;   @MAX (252): Maximum user-modifiable address\\n;   @IN (253): Reads a value from input (writes are ignored)\\n;   @OUT (254): Writes a result to output (reads as zero)\\n;   @HALT (255): Terminates the program when accessed\\n;\\n; Note: any text following a semicolon is considered a comment. Comments are ignored by the assembler.\\n; \\n; Below is a very simple SIC-1 program that negates one input value and writes it out.\\n;\\n; E.g. if the input value from @IN is 3, it subtracts 3 from @OUT (which reads as zero), and the result of 0 - 3 = -3 is written out.\\n\\nsubleq @OUT, @IN\\n\\n; Use the \\\"Compile/Step\\\" (Ctrl+.) and \\\"Run\\\" (Ctrl+Enter) buttons to execute the program until all expected outputs have been successfully written out (see the \\\"In\\\"/\\\"Expected\\\"/\\\"Out\\\" table to the left).\\n    \"\n    }\n  ],\n  \"puzzleCodeTokenizer\": [\n    {\n      \"type\": 0,\n      \"value\": \"; Read a string and output each word as its own string. Repeat.\\n;\\n; Note: words are each separated by a single space (and the last word ends with a zero).\\n\\n\"\n    }\n  ],\n  \"puzzleCodeUppercase\": [\n    {\n      \"type\": 0,\n      \"value\": \"; Read and output characters. For each alphabetic character, convert it to uppercase if needed.\\n;\\n; Note that the mappings for 'a', 'b', ... 'z' are contiguous, as are 'A', 'B', ... 'Z'.\\n\\n\"\n    }\n  ],\n  \"puzzleDescriptionAddition\": [\n    {\n      \"type\": 0,\n      \"value\": \"Read two numbers and output their sum. Repeat.\"\n    }\n  ],\n  \"puzzleDescriptionCalculator\": [\n    {\n      \"type\": 0,\n      \"value\": \"Read a string representing arithmetic (+, -, or *) on 2 numbers on the interval [1, 127]; write out the resulting value. Repeat.\"\n    }\n  ],\n  \"puzzleDescriptionCharacters\": [\n    {\n      \"type\": 0,\n      \"value\": \"Output the following two characters: \\\"Hi\\\"\"\n    }\n  ],\n  \"puzzleDescriptionData Directive and Looping\": [\n    {\n      \"type\": 0,\n      \"value\": \"Use .data and labels to loop.\"\n    }\n  ],\n  \"puzzleDescriptionDecimal Digits\": [\n    {\n      \"type\": 0,\n      \"value\": \"Read a decimal digit character, output the numeric value. Repeat.\"\n    }\n  ],\n  \"puzzleDescriptionDivision\": [\n    {\n      \"type\": 0,\n      \"value\": \"Read two positive numbers (A, then B), divide A by B, and output the quotient followed by the remainder. Repeat.\"\n    }\n  ],\n  \"puzzleDescriptionFirst Assessment\": [\n    {\n      \"type\": 0,\n      \"value\": \"Write input values to output.\"\n    }\n  ],\n  \"puzzleDescriptionIndicator Function\": [\n    {\n      \"type\": 0,\n      \"value\": \"Read two zero-terminated sets of numbers on the interval [1, 99], A and B. For each element of B, output a 1 if the value is in A and 0 otherwise. Repeat.\"\n    }\n  ],\n  \"puzzleDescriptionInterleave\": [\n    {\n      \"type\": 0,\n      \"value\": \"Read two equal length positive sequences (A and B) and interleave their elements (A1, B1, A2, B2, ...), ending with a single zero. Repeat.\"\n    }\n  ],\n  \"puzzleDescriptionMode\": [\n    {\n      \"type\": 0,\n      \"value\": \"Read a list of numbers on the interval [1, 99] (terminated by a zero) and output the most common element. Repeat.\"\n    }\n  ],\n  \"puzzleDescriptionMulti-Line Strings\": [\n    {\n      \"type\": 0,\n      \"value\": \"Read a string with multiple lines and write out each line as a string.\"\n    }\n  ],\n  \"puzzleDescriptionMultiplication\": [\n    {\n      \"type\": 0,\n      \"value\": \"Read two nonnegative numbers and output the resulting (nonnegative) product. Repeat.\"\n    }\n  ],\n  \"puzzleDescriptionNumber to Sequence\": [\n    {\n      \"type\": 0,\n      \"value\": \"Read a number and then output that many 1s, followed by a 0. Repeat.\"\n    }\n  ],\n  \"puzzleDescriptionParse Data Directives\": [\n    {\n      \"type\": 0,\n      \"value\": \"Parse a program with multiple .data directives and output the corresponding values.\"\n    }\n  ],\n  \"puzzleDescriptionParse Decimal\": [\n    {\n      \"type\": 0,\n      \"value\": \"Read a string representing a number on the interval [1, 127] and output the corresponding value. Repeat.\"\n    }\n  ],\n  \"puzzleDescriptionParse Subleq Instructions\": [\n    {\n      \"type\": 0,\n      \"value\": \"Parse a program with multiple subleq instructions and output the compiled program.\"\n    }\n  ],\n  \"puzzleDescriptionPrint Decimal\": [\n    {\n      \"type\": 0,\n      \"value\": \"Read a positive number on the interval [1, 127] and output a string representing the number in decimal form. Repeat.\"\n    }\n  ],\n  \"puzzleDescriptionReverse Sequence\": [\n    {\n      \"type\": 0,\n      \"value\": \"Read a sequence of positive numbers (terminated by a zero) and output the sequence in reverse order (with zero terminator). Repeat.\"\n    }\n  ],\n  \"puzzleDescriptionSandbox Mode\": [\n    {\n      \"type\": 0,\n      \"value\": \"An open-ended, configurable program for exploration purposes.\"\n    }\n  ],\n  \"puzzleDescriptionSelf-Hosting\": [\n    {\n      \"type\": 0,\n      \"value\": \"Read in a SIC-1 program and execute it until it branches to address 255, writing out any values written to address 254. Repeat.\"\n    }\n  ],\n  \"puzzleDescriptionSelf-Hosting Part 2\": [\n    {\n      \"type\": 0,\n      \"value\": \"Read in a self-modifying SIC-1 program and execute it until it branches to address 255, writing out any values written to address 254. Repeat.\"\n    }\n  ],\n  \"puzzleDescriptionSelf-Modifying Code\": [\n    {\n      \"type\": 0,\n      \"value\": \"Output the program's compiled code byte-by-byte.\"\n    }\n  ],\n  \"puzzleDescriptionSequence Cardinality\": [\n    {\n      \"type\": 0,\n      \"value\": \"Read a sequence of positive numbers and output the count of numbers. Repeat. Sequences are terminated by a zero.\"\n    }\n  ],\n  \"puzzleDescriptionSequence Sum\": [\n    {\n      \"type\": 0,\n      \"value\": \"Read a sequence of positive numbers and output their sum. Repeat. Sequences are terminated by a zero.\"\n    }\n  ],\n  \"puzzleDescriptionSign Function\": [\n    {\n      \"type\": 0,\n      \"value\": \"Read a number. If less than zero, output -1; if equal to zero, output 0; otherwise output 1. Repeat.\"\n    }\n  ],\n  \"puzzleDescriptionSort\": [\n    {\n      \"type\": 0,\n      \"value\": \"Read a list of numbers on the interval [1, 99] (terminated by a zero) and output the list ordered smallest to largest, ending with a zero. Repeat.\"\n    }\n  ],\n  \"puzzleDescriptionStack Memory\": [\n    {\n      \"type\": 0,\n      \"value\": \"Read 3 values from input and then output the values in reverse order.\"\n    }\n  ],\n  \"puzzleDescriptionStrings\": [\n    {\n      \"type\": 0,\n      \"value\": \"Output the string \\\"Hello, world!\\\".\"\n    }\n  ],\n  \"puzzleDescriptionSubleq Instruction and Output\": [\n    {\n      \"type\": 0,\n      \"value\": \"Use subleq and input/output to negate an input and write it out.\"\n    }\n  ],\n  \"puzzleDescriptionSubtraction\": [\n    {\n      \"type\": 0,\n      \"value\": \"Read two numbers (A, then B) and output A minus B. Repeat.\"\n    }\n  ],\n  \"puzzleDescriptionTokenizer\": [\n    {\n      \"type\": 0,\n      \"value\": \"Read a string and output each word as its own string. Repeat.\"\n    }\n  ],\n  \"puzzleDescriptionUppercase\": [\n    {\n      \"type\": 0,\n      \"value\": \"Read and output characters, converting all lowercase characters to uppercase.\"\n    }\n  ],\n  \"puzzleDetailSandbox Mode\": [\n    {\n      \"children\": [\n        {\n          \"type\": 0,\n          \"value\": \"Use Sandbox Mode to freely experiment with the SIC-1 without worrying about output getting flagged as incorrect.\"\n        }\n      ],\n      \"type\": 8,\n      \"value\": \"p\"\n    },\n    {\n      \"children\": [\n        {\n          \"type\": 0,\n          \"value\": \"It's possible to specify custom input using the \\\"Configure Input\\\" button on the left side of the main SIC-1 Development Environment (above the IO table). Input uses the same syntax as in a \"\n        },\n        {\n          \"children\": [\n            {\n              \"type\": 0,\n              \"value\": \".data\"\n            }\n          ],\n          \"type\": 8,\n          \"value\": \"code\"\n        },\n        {\n          \"type\": 0,\n          \"value\": \" directive (examples: \"\n        },\n        {\n          \"children\": [\n            {\n              \"type\": 0,\n              \"value\": \"-7\"\n            }\n          ],\n          \"type\": 8,\n          \"value\": \"code\"\n        },\n        {\n          \"type\": 0,\n          \"value\": \", \"\n        },\n        {\n          \"children\": [\n            {\n              \"type\": 0,\n              \"value\": \"'A'\"\n            }\n          ],\n          \"type\": 8,\n          \"value\": \"code\"\n        },\n        {\n          \"type\": 0,\n          \"value\": \", \"\n        },\n        {\n          \"children\": [\n            {\n              \"type\": 0,\n              \"value\": \"-\\\"Negated string\\\"\"\n            }\n          ],\n          \"type\": 8,\n          \"value\": \"code\"\n        },\n        {\n          \"type\": 0,\n          \"value\": \").\"\n        }\n      ],\n      \"type\": 8,\n      \"value\": \"p\"\n    }\n  ],\n  \"puzzleGroupTitleAdvanced Techniques\": [\n    {\n      \"type\": 0,\n      \"value\": \"Advanced Techniques\"\n    }\n  ],\n  \"puzzleGroupTitleArithmetic\": [\n    {\n      \"type\": 0,\n      \"value\": \"Arithmetic\"\n    }\n  ],\n  \"puzzleGroupTitleNatural Language Processing\": [\n    {\n      \"type\": 0,\n      \"value\": \"Natural Language Processing\"\n    }\n  ],\n  \"puzzleGroupTitleSelf-Hosting\": [\n    {\n      \"type\": 0,\n      \"value\": \"Self-Hosting\"\n    }\n  ],\n  \"puzzleGroupTitleSequence Manipulation\": [\n    {\n      \"type\": 0,\n      \"value\": \"Sequence Manipulation\"\n    }\n  ],\n  \"puzzleGroupTitleSequences\": [\n    {\n      \"type\": 0,\n      \"value\": \"Sequences\"\n    }\n  ],\n  \"puzzleGroupTitleTutorial\": [\n    {\n      \"type\": 0,\n      \"value\": \"Tutorial\"\n    }\n  ],\n  \"puzzleHintAddition\": [\n    {\n      \"children\": [\n        {\n          \"type\": 0,\n          \"value\": \"Subtract two inputs into \"\n        },\n        {\n          \"children\": [\n            {\n              \"type\": 0,\n              \"value\": \"@tmp\"\n            }\n          ],\n          \"type\": 8,\n          \"value\": \"code\"\n        },\n        {\n          \"type\": 0,\n          \"value\": \".\"\n        }\n      ],\n      \"type\": 8,\n      \"value\": \"p\"\n    }\n  ],\n  \"puzzleHintCalculator\": [\n    {\n      \"children\": [\n        {\n          \"type\": 0,\n          \"value\": \"Combine the solutions to \\\"Addition\\\", \\\"Subtraction\\\", \\\"Multiplication\\\", and \\\"Parse Decimal\\\".\"\n        }\n      ],\n      \"type\": 8,\n      \"value\": \"p\"\n    }\n  ],\n  \"puzzleHintCharacters\": [\n    {\n      \"children\": [\n        {\n          \"type\": 0,\n          \"value\": \"This task has already been solved, but note how character literals are used (and negated).\"\n        }\n      ],\n      \"type\": 8,\n      \"value\": \"p\"\n    }\n  ],\n  \"puzzleHintData Directive and Looping\": [\n    {\n      \"children\": [\n        {\n          \"type\": 0,\n          \"value\": \"This task has already been solved. Just click \"\n        },\n        {\n          \"children\": [\n            {\n              \"type\": 0,\n              \"value\": \"Run\"\n            }\n          ],\n          \"type\": 8,\n          \"value\": \"strong\"\n        },\n        {\n          \"type\": 0,\n          \"value\": \".\"\n        }\n      ],\n      \"type\": 8,\n      \"value\": \"p\"\n    }\n  ],\n  \"puzzleHintDecimal Digits\": [\n    {\n      \"children\": [\n        {\n          \"type\": 0,\n          \"value\": \"Subtract the character literal \"\n        },\n        {\n          \"children\": [\n            {\n              \"type\": 0,\n              \"value\": \"'0'\"\n            }\n          ],\n          \"type\": 8,\n          \"value\": \"code\"\n        },\n        {\n          \"type\": 0,\n          \"value\": \".\"\n        }\n      ],\n      \"type\": 8,\n      \"value\": \"p\"\n    }\n  ],\n  \"puzzleHintDivision\": [\n    {\n      \"children\": [\n        {\n          \"type\": 0,\n          \"value\": \"Repeatedly subtract the divisor from the dividend.\"\n        }\n      ],\n      \"type\": 8,\n      \"value\": \"p\"\n    }\n  ],\n  \"puzzleHintFirst Assessment\": [\n    {\n      \"children\": [\n        {\n          \"type\": 0,\n          \"value\": \"Negate the value twice (these operations cancel out and result in the original number). This can be done by storing the negated value in a memory location that starts out as zero (e.g. \"\n        },\n        {\n          \"children\": [\n            {\n              \"type\": 0,\n              \"value\": \"@tmp\"\n            }\n          ],\n          \"type\": 8,\n          \"value\": \"code\"\n        },\n        {\n          \"type\": 0,\n          \"value\": \").\"\n        }\n      ],\n      \"type\": 8,\n      \"value\": \"p\"\n    }\n  ],\n  \"puzzleHintIndicator Function\": [\n    {\n      \"children\": [\n        {\n          \"type\": 0,\n          \"value\": \"Store the first list for later lookup. Remember to clear the list afterwards.\"\n        }\n      ],\n      \"type\": 8,\n      \"value\": \"p\"\n    }\n  ],\n  \"puzzleHintInterleave\": [\n    {\n      \"children\": [\n        {\n          \"type\": 0,\n          \"value\": \"Store the first list for later output. Remember to clear the list afterwards.\"\n        }\n      ],\n      \"type\": 8,\n      \"value\": \"p\"\n    }\n  ],\n  \"puzzleHintMode\": [\n    {\n      \"children\": [\n        {\n          \"type\": 0,\n          \"value\": \"Track both the items, as well as their count.\"\n        }\n      ],\n      \"type\": 8,\n      \"value\": \"p\"\n    }\n  ],\n  \"puzzleHintMulti-Line Strings\": [\n    {\n      \"children\": [\n        {\n          \"type\": 0,\n          \"value\": \"This task is very similar to Tokenizer.\"\n        }\n      ],\n      \"type\": 8,\n      \"value\": \"p\"\n    }\n  ],\n  \"puzzleHintMultiplication\": [\n    {\n      \"children\": [\n        {\n          \"type\": 0,\n          \"value\": \"Repeatedly subtract one of the numbers, using a counter to ensure the subtraction is done the appropriate number of times.\"\n        }\n      ],\n      \"type\": 8,\n      \"value\": \"p\"\n    }\n  ],\n  \"puzzleHintNumber to Sequence\": [\n    {\n      \"children\": [\n        {\n          \"type\": 0,\n          \"value\": \"Use a counter to write the appropriate number of \"\n        },\n        {\n          \"children\": [\n            {\n              \"type\": 0,\n              \"value\": \"1\"\n            }\n          ],\n          \"type\": 8,\n          \"value\": \"strong\"\n        },\n        {\n          \"type\": 0,\n          \"value\": \"s.\"\n        }\n      ],\n      \"type\": 8,\n      \"value\": \"p\"\n    }\n  ],\n  \"puzzleHintParse Data Directives\": [\n    {\n      \"children\": [\n        {\n          \"type\": 0,\n          \"value\": \"This task is similar to \\\"Parse Decimal\\\", but negative numbers need to be handled.\"\n        }\n      ],\n      \"type\": 8,\n      \"value\": \"p\"\n    }\n  ],\n  \"puzzleHintParse Decimal\": [\n    {\n      \"children\": [\n        {\n          \"type\": 0,\n          \"value\": \"Shifting left one decimal digit is the same as multiplying by ten.\"\n        }\n      ],\n      \"type\": 8,\n      \"value\": \"p\"\n    }\n  ],\n  \"puzzleHintParse Subleq Instructions\": [\n    {\n      \"children\": [\n        {\n          \"type\": 0,\n          \"value\": \"This task is very similar to \\\"Parse Decimal\\\".\"\n        }\n      ],\n      \"type\": 8,\n      \"value\": \"p\"\n    }\n  ],\n  \"puzzleHintPrint Decimal\": [\n    {\n      \"children\": [\n        {\n          \"type\": 0,\n          \"value\": \"Remember to output digits from most significant to least.\"\n        }\n      ],\n      \"type\": 8,\n      \"value\": \"p\"\n    }\n  ],\n  \"puzzleHintReverse Sequence\": [\n    {\n      \"children\": [\n        {\n          \"type\": 0,\n          \"value\": \"Use a stack, and remember to clear the stack afterwards.\"\n        }\n      ],\n      \"type\": 8,\n      \"value\": \"p\"\n    }\n  ],\n  \"puzzleHintSandbox Mode\": [\n    {\n      \"children\": [\n        {\n          \"type\": 0,\n          \"value\": \"Click \\\"Configure Input\\\" to supply custom input.\"\n        }\n      ],\n      \"type\": 8,\n      \"value\": \"p\"\n    }\n  ],\n  \"puzzleHintSelf-Hosting\": [\n    {\n      \"children\": [\n        {\n          \"type\": 0,\n          \"value\": \"Use previous decimal-parsing solutions to compile the program, but take care to follow the instructions precisely.\"\n        }\n      ],\n      \"type\": 8,\n      \"value\": \"p\"\n    }\n  ],\n  \"puzzleHintSelf-Hosting Part 2\": [\n    {\n      \"children\": [\n        {\n          \"type\": 0,\n          \"value\": \"You're on your own for this one.\"\n        }\n      ],\n      \"type\": 8,\n      \"value\": \"p\"\n    }\n  ],\n  \"puzzleHintSelf-Modifying Code\": [\n    {\n      \"children\": [\n        {\n          \"type\": 0,\n          \"value\": \"This task has already been solved, but carefully note how the second byte of the first instruction is modified.\"\n        }\n      ],\n      \"type\": 8,\n      \"value\": \"p\"\n    }\n  ],\n  \"puzzleHintSequence Cardinality\": [\n    {\n      \"children\": [\n        {\n          \"type\": 0,\n          \"value\": \"Increment a counter for each element in the sequence.\"\n        }\n      ],\n      \"type\": 8,\n      \"value\": \"p\"\n    }\n  ],\n  \"puzzleHintSequence Sum\": [\n    {\n      \"children\": [\n        {\n          \"type\": 0,\n          \"value\": \"Store the value to test whether it indicates the end of the sequence.\"\n        }\n      ],\n      \"type\": 8,\n      \"value\": \"p\"\n    }\n  ],\n  \"puzzleHintSign Function\": [\n    {\n      \"children\": [\n        {\n          \"type\": 0,\n          \"value\": \"Use the \\\"branch if result is ≤ 0\\\" property of subleq to branch between code blocks, then use (negated) constants to write the appropriate output.\"\n        }\n      ],\n      \"type\": 8,\n      \"value\": \"p\"\n    }\n  ],\n  \"puzzleHintSort\": [\n    {\n      \"children\": [\n        {\n          \"type\": 0,\n          \"value\": \"Insert items into memory in the correct position.\"\n        }\n      ],\n      \"type\": 8,\n      \"value\": \"p\"\n    }\n  ],\n  \"puzzleHintStack Memory\": [\n    {\n      \"children\": [\n        {\n          \"type\": 0,\n          \"value\": \"This task has already been solved, but carefully watch the memory window to see how items are added to the stack.\"\n        }\n      ],\n      \"type\": 8,\n      \"value\": \"p\"\n    }\n  ],\n  \"puzzleHintStrings\": [\n    {\n      \"children\": [\n        {\n          \"type\": 0,\n          \"value\": \"This task has already been solved, but note that strings are terminated by a zero.\"\n        }\n      ],\n      \"type\": 8,\n      \"value\": \"p\"\n    }\n  ],\n  \"puzzleHintSubleq Instruction and Output\": [\n    {\n      \"children\": [\n        {\n          \"type\": 0,\n          \"value\": \"This task has already been solved. Just click \"\n        },\n        {\n          \"children\": [\n            {\n              \"type\": 0,\n              \"value\": \"Run\"\n            }\n          ],\n          \"type\": 8,\n          \"value\": \"strong\"\n        },\n        {\n          \"type\": 0,\n          \"value\": \".\"\n        }\n      ],\n      \"type\": 8,\n      \"value\": \"p\"\n    }\n  ],\n  \"puzzleHintSubtraction\": [\n    {\n      \"children\": [\n        {\n          \"type\": 0,\n          \"value\": \"Use two variables.\"\n        }\n      ],\n      \"type\": 8,\n      \"value\": \"p\"\n    }\n  ],\n  \"puzzleHintTokenizer\": [\n    {\n      \"children\": [\n        {\n          \"type\": 0,\n          \"value\": \"Strings are terminated by a single zero.\"\n        }\n      ],\n      \"type\": 8,\n      \"value\": \"p\"\n    }\n  ],\n  \"puzzleHintUppercase\": [\n    {\n      \"children\": [\n        {\n          \"type\": 0,\n          \"value\": \"Test to see if the input is between \\\"a\\\" and \\\"z\\\", and modify the value as needed.\"\n        }\n      ],\n      \"type\": 8,\n      \"value\": \"p\"\n    }\n  ],\n  \"puzzleTitleAddition\": [\n    {\n      \"type\": 0,\n      \"value\": \"Addition\"\n    }\n  ],\n  \"puzzleTitleCalculator\": [\n    {\n      \"type\": 0,\n      \"value\": \"Calculator\"\n    }\n  ],\n  \"puzzleTitleCharacters\": [\n    {\n      \"type\": 0,\n      \"value\": \"Characters\"\n    }\n  ],\n  \"puzzleTitleData Directive and Looping\": [\n    {\n      \"type\": 0,\n      \"value\": \"Data Directive and Looping\"\n    }\n  ],\n  \"puzzleTitleDecimal Digits\": [\n    {\n      \"type\": 0,\n      \"value\": \"Decimal Digits\"\n    }\n  ],\n  \"puzzleTitleDivision\": [\n    {\n      \"type\": 0,\n      \"value\": \"Division\"\n    }\n  ],\n  \"puzzleTitleFirst Assessment\": [\n    {\n      \"type\": 0,\n      \"value\": \"First Assessment\"\n    }\n  ],\n  \"puzzleTitleIndicator Function\": [\n    {\n      \"type\": 0,\n      \"value\": \"Indicator Function\"\n    }\n  ],\n  \"puzzleTitleInterleave\": [\n    {\n      \"type\": 0,\n      \"value\": \"Interleave\"\n    }\n  ],\n  \"puzzleTitleMode\": [\n    {\n      \"type\": 0,\n      \"value\": \"Mode\"\n    }\n  ],\n  \"puzzleTitleMulti-Line Strings\": [\n    {\n      \"type\": 0,\n      \"value\": \"Multi-Line Strings\"\n    }\n  ],\n  \"puzzleTitleMultiplication\": [\n    {\n      \"type\": 0,\n      \"value\": \"Multiplication\"\n    }\n  ],\n  \"puzzleTitleNumber to Sequence\": [\n    {\n      \"type\": 0,\n      \"value\": \"Number to Sequence\"\n    }\n  ],\n  \"puzzleTitleParse Data Directives\": [\n    {\n      \"type\": 0,\n      \"value\": \"Parse Data Directives\"\n    }\n  ],\n  \"puzzleTitleParse Decimal\": [\n    {\n      \"type\": 0,\n      \"value\": \"Parse Decimal\"\n    }\n  ],\n  \"puzzleTitleParse Subleq Instructions\": [\n    {\n      \"type\": 0,\n      \"value\": \"Parse Subleq Instructions\"\n    }\n  ],\n  \"puzzleTitlePrint Decimal\": [\n    {\n      \"type\": 0,\n      \"value\": \"Print Decimal\"\n    }\n  ],\n  \"puzzleTitleReverse Sequence\": [\n    {\n      \"type\": 0,\n      \"value\": \"Reverse Sequence\"\n    }\n  ],\n  \"puzzleTitleSandbox Mode\": [\n    {\n      \"type\": 0,\n      \"value\": \"Sandbox Mode\"\n    }\n  ],\n  \"puzzleTitleSelf-Hosting\": [\n    {\n      \"type\": 0,\n      \"value\": \"Self-Hosting\"\n    }\n  ],\n  \"puzzleTitleSelf-Hosting Part 2\": [\n    {\n      \"type\": 0,\n      \"value\": \"Self-Hosting Part 2\"\n    }\n  ],\n  \"puzzleTitleSelf-Modifying Code\": [\n    {\n      \"type\": 0,\n      \"value\": \"Self-Modifying Code\"\n    }\n  ],\n  \"puzzleTitleSequence Cardinality\": [\n    {\n      \"type\": 0,\n      \"value\": \"Sequence Cardinality\"\n    }\n  ],\n  \"puzzleTitleSequence Sum\": [\n    {\n      \"type\": 0,\n      \"value\": \"Sequence Sum\"\n    }\n  ],\n  \"puzzleTitleSign Function\": [\n    {\n      \"type\": 0,\n      \"value\": \"Sign Function\"\n    }\n  ],\n  \"puzzleTitleSort\": [\n    {\n      \"type\": 0,\n      \"value\": \"Sort\"\n    }\n  ],\n  \"puzzleTitleStack Memory\": [\n    {\n      \"type\": 0,\n      \"value\": \"Stack Memory\"\n    }\n  ],\n  \"puzzleTitleStrings\": [\n    {\n      \"type\": 0,\n      \"value\": \"Strings\"\n    }\n  ],\n  \"puzzleTitleSubleq Instruction and Output\": [\n    {\n      \"type\": 0,\n      \"value\": \"Subleq Instruction and Output\"\n    }\n  ],\n  \"puzzleTitleSubtraction\": [\n    {\n      \"type\": 0,\n      \"value\": \"Subtraction\"\n    }\n  ],\n  \"puzzleTitleTokenizer\": [\n    {\n      \"type\": 0,\n      \"value\": \"Tokenizer\"\n    }\n  ],\n  \"puzzleTitleUppercase\": [\n    {\n      \"type\": 0,\n      \"value\": \"Uppercase\"\n    }\n  ],\n  \"rank\": [\n    {\n      \"type\": 0,\n      \"value\": \"Rank: \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"ranking\"\n    }\n  ],\n  \"rankOutOf\": [\n    {\n      \"type\": 1,\n      \"value\": \"rank\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" out of \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"total\"\n    }\n  ],\n  \"selectColorScheme\": [\n    {\n      \"type\": 0,\n      \"value\": \"Color scheme:\"\n    }\n  ],\n  \"selectLanguage\": [\n    {\n      \"type\": 0,\n      \"value\": \"Language:\"\n    }\n  ],\n  \"sliderMusicVolume\": [\n    {\n      \"type\": 0,\n      \"value\": \"Music volume:\"\n    }\n  ],\n  \"sliderSoundVolume\": [\n    {\n      \"type\": 0,\n      \"value\": \"Sound effects volume:\"\n    }\n  ],\n  \"sliderZoom\": [\n    {\n      \"type\": 0,\n      \"value\": \"Zoom:\"\n    }\n  ],\n  \"solutionButtonCancelDelete\": [\n    {\n      \"type\": 0,\n      \"value\": \"Cancel\"\n    }\n  ],\n  \"solutionButtonConfirmDelete\": [\n    {\n      \"type\": 0,\n      \"value\": \"Delete\"\n    }\n  ],\n  \"solutionNameDefault\": [\n    {\n      \"type\": 0,\n      \"value\": \"Untitled\"\n    }\n  ],\n  \"solutionStatsSuffix\": [\n    {\n      \"type\": 0,\n      \"value\": \" (cycles: \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"cycles\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \", bytes: \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"bytes\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \")\"\n    }\n  ],\n  \"stateStatusRunning\": [\n    {\n      \"type\": 0,\n      \"value\": \"Running\"\n    }\n  ],\n  \"stateStatusStopped\": [\n    {\n      \"type\": 0,\n      \"value\": \"Stopped\"\n    }\n  ],\n  \"taskAchievements\": [\n    {\n      \"type\": 0,\n      \"value\": \"Achievements\"\n    }\n  ],\n  \"taskAvoision\": [\n    {\n      \"type\": 0,\n      \"value\": \"Avoision\"\n    }\n  ],\n  \"taskContentAvoision\": [\n    {\n      \"children\": [\n        {\n          \"type\": 0,\n          \"value\": \"To help improve morale, SIC Systems has provided an officially sanctioned computer video game called \\\"Avoision\\\" for employees to play. If you think your work would benefit from an entertaining diversion, please feel free to compete against your coworkers for the highest score in \\\"Avoision\\\" (during your two legally-mandated unpaid breaks, or in lieu of an unneeded bathroom break).\"\n        }\n      ],\n      \"type\": 8,\n      \"value\": \"p\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \"\\n\"\n    },\n    {\n      \"children\": [\n        {\n          \"type\": 0,\n          \"value\": \"Instructions\"\n        }\n      ],\n      \"type\": 8,\n      \"value\": \"h3\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \"\\n\"\n    },\n    {\n      \"children\": [\n        {\n          \"type\": 0,\n          \"value\": \"Use the arrow keys to move your bright green block and try to capture the bright green square. The faster you capture the square, the more points you will score.\"\n        }\n      ],\n      \"type\": 8,\n      \"value\": \"p\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \"\\n\"\n    },\n    {\n      \"children\": [\n        {\n          \"type\": 0,\n          \"value\": \"As you progress, moving dark green blocks will appear. If your bright green block collides with a dark green block, the game is over.\"\n        }\n      ],\n      \"type\": 8,\n      \"value\": \"p\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \"\\n\"\n    },\n    {\n      \"children\": [\n        {\n          \"type\": 0,\n          \"value\": \"Click the \\\"Play Avoision\\\" button below to play.\"\n        }\n      ],\n      \"type\": 8,\n      \"value\": \"p\"\n    }\n  ],\n  \"taskDiversions\": [\n    {\n      \"type\": 0,\n      \"value\": \"Diversions\"\n    }\n  ],\n  \"taskNumberedList\": [\n    {\n      \"type\": 1,\n      \"value\": \"number\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \". \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"title\"\n    }\n  ],\n  \"taskProgress\": [\n    {\n      \"type\": 0,\n      \"value\": \"Task Progress\"\n    }\n  ],\n  \"taskStatusIncomplete\": [\n    {\n      \"type\": 0,\n      \"value\": \"Incomplete\"\n    }\n  ],\n  \"taskStatusNew\": [\n    {\n      \"type\": 0,\n      \"value\": \"New\"\n    }\n  ],\n  \"taskViewerButtonAvoision\": [\n    {\n      \"type\": 0,\n      \"value\": \"Play Avoision\"\n    }\n  ],\n  \"taskViewerButtonContinueEditing\": [\n    {\n      \"type\": 0,\n      \"value\": \"Continue Editing Current Program\"\n    }\n  ],\n  \"taskViewerButtonLoad\": [\n    {\n      \"type\": 0,\n      \"value\": \"Load This Program\"\n    }\n  ],\n  \"taskViewerButtonNextIncompleteTask\": [\n    {\n      \"type\": 0,\n      \"value\": \"View Next Incomplete Task\"\n    }\n  ],\n  \"taskViewerButtonSandbox\": [\n    {\n      \"type\": 0,\n      \"value\": \"Enter Sandbox Mode\"\n    }\n  ],\n  \"taskViewerButtonSolutionCopy\": [\n    {\n      \"type\": 0,\n      \"value\": \"Copy\"\n    }\n  ],\n  \"taskViewerButtonSolutionDelete\": [\n    {\n      \"type\": 0,\n      \"value\": \"Delete\"\n    }\n  ],\n  \"taskViewerButtonSolutionNew\": [\n    {\n      \"type\": 0,\n      \"value\": \"New\"\n    }\n  ],\n  \"taskViewerButtonSolutionRename\": [\n    {\n      \"type\": 0,\n      \"value\": \"Rename\"\n    }\n  ],\n  \"taskViewerButtonViewUnread\": [\n    {\n      \"type\": 0,\n      \"value\": \"View Unread Electronic Mail\"\n    }\n  ],\n  \"taskViewerFilesEmpty\": [\n    {\n      \"type\": 0,\n      \"value\": \"(No files found)\"\n    }\n  ],\n  \"taskViewerHeadingAvoision\": [\n    {\n      \"children\": [\n        {\n          \"type\": 0,\n          \"value\": \"User\"\n        }\n      ],\n      \"type\": 8,\n      \"value\": \"cap\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \": \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"name\"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"newline\"\n    },\n    {\n      \"children\": [\n        {\n          \"type\": 0,\n          \"value\": \"Program\"\n        }\n      ],\n      \"type\": 8,\n      \"value\": \"cap\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \": Avoision\"\n    }\n  ],\n  \"taskViewerHeadingFile\": [\n    {\n      \"type\": 0,\n      \"value\": \"File Selection\"\n    }\n  ],\n  \"taskViewerHeadingUser\": [\n    {\n      \"children\": [\n        {\n          \"type\": 0,\n          \"value\": \"User\"\n        }\n      ],\n      \"type\": 8,\n      \"value\": \"cap\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \": \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"name\"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"newline\"\n    },\n    {\n      \"children\": [\n        {\n          \"type\": 0,\n          \"value\": \"Title\"\n        }\n      ],\n      \"type\": 8,\n      \"value\": \"cap\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \": \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"title\"\n    }\n  ],\n  \"taskViewerMotivation\": [\n    {\n      \"children\": [\n        {\n          \"type\": 0,\n          \"value\": \"SIC Systems appreciates your continued effort.\"\n        }\n      ],\n      \"type\": 8,\n      \"value\": \"p\"\n    },\n    {\n      \"children\": [\n        {\n          \"type\": 0,\n          \"value\": \"For motivational purposes, here is how the number of tasks you have completed compares to other engineers.\"\n        }\n      ],\n      \"type\": 8,\n      \"value\": \"p\"\n    }\n  ],\n  \"taskViewerStatusCompleted\": [\n    {\n      \"type\": 0,\n      \"value\": \"Completed\"\n    }\n  ],\n  \"taskViewerStatusLine\": [\n    {\n      \"children\": [\n        {\n          \"type\": 0,\n          \"value\": \"Status\"\n        }\n      ],\n      \"type\": 8,\n      \"value\": \"cap\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \": \"\n    },\n    {\n      \"children\": [\n        {\n          \"type\": 1,\n          \"value\": \"status\"\n        }\n      ],\n      \"type\": 8,\n      \"value\": \"cap\"\n    }\n  ],\n  \"taskViewerTaskHeading\": [\n    {\n      \"children\": [\n        {\n          \"type\": 0,\n          \"value\": \"User\"\n        }\n      ],\n      \"type\": 8,\n      \"value\": \"cap\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \": \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"name\"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"newline\"\n    },\n    {\n      \"children\": [\n        {\n          \"type\": 0,\n          \"value\": \"Task\"\n        }\n      ],\n      \"type\": 8,\n      \"value\": \"cap\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \": \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"title\"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"newline\"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"statusLine\"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"newline\"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"newline\"\n    },\n    {\n      \"children\": [\n        {\n          \"type\": 0,\n          \"value\": \"Description\"\n        }\n      ],\n      \"type\": 8,\n      \"value\": \"cap\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \": \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"description\"\n    }\n  ],\n  \"taskViewerTextIncomplete\": [\n    {\n      \"type\": 0,\n      \"value\": \"You have not implemented this program yet. Click \\\"Load This Program\\\" at the bottom of this window to load the program into the editor.\"\n    }\n  ],\n  \"taskWithStatus\": [\n    {\n      \"type\": 1,\n      \"value\": \"title\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" (\"\n    },\n    {\n      \"children\": [\n        {\n          \"type\": 1,\n          \"value\": \"status\"\n        }\n      ],\n      \"type\": 8,\n      \"value\": \"cap\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \")\"\n    }\n  ],\n  \"templateSolutionCopy\": [\n    {\n      \"type\": 0,\n      \"value\": \"Copy of \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"name\"\n    }\n  ],\n  \"templateSolutionDuplicate\": [\n    {\n      \"type\": 1,\n      \"value\": \"name\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" (\"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"number\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \")\"\n    }\n  ],\n  \"textCompilationErrorContext\": [\n    {\n      \"children\": [\n        {\n          \"type\": 0,\n          \"value\": \"On line \"\n        },\n        {\n          \"type\": 1,\n          \"value\": \"sourceLineNumber\"\n        },\n        {\n          \"type\": 0,\n          \"value\": \":\"\n        }\n      ],\n      \"type\": 8,\n      \"value\": \"p\"\n    },\n    {\n      \"children\": [\n        {\n          \"type\": 1,\n          \"value\": \"sourceLine\"\n        }\n      ],\n      \"type\": 8,\n      \"value\": \"p\"\n    }\n  ],\n  \"textConfirmDelete\": [\n    {\n      \"type\": 0,\n      \"value\": \"Delete \\\"\"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"itemName\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \"\\\"?\"\n    }\n  ],\n  \"textCopyFailed\": [\n    {\n      \"type\": 0,\n      \"value\": \"Error: Failed to copy to the clipboard.\"\n    }\n  ],\n  \"textCopySucceeded\": [\n    {\n      \"type\": 0,\n      \"value\": \"Copied to the clipboard!\"\n    }\n  ],\n  \"textCreditsFooter\": [\n    {\n      \"type\": 0,\n      \"value\": \"To view third party licenses, \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"link\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \".\"\n    }\n  ],\n  \"textHaltUnexpected\": [\n    {\n      \"type\": 0,\n      \"value\": \"All of your assigned tasks require the program to repeat indefinitely, so this is an error that must be corrected.\"\n    }\n  ],\n  \"textHint\": [\n    {\n      \"type\": 0,\n      \"value\": \"Hint for \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"task\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \":\"\n    }\n  ],\n  \"textInputError\": [\n    {\n      \"type\": 0,\n      \"value\": \"Error: \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"message\"\n    }\n  ],\n  \"textLicenses\": [\n    {\n      \"type\": 0,\n      \"value\": \"Third Party Licenses\"\n    }\n  ],\n  \"textSaveClear\": [\n    {\n      \"type\": 0,\n      \"value\": \"Use the button below to delete your solutions, user name, and achievements:\"\n    }\n  ],\n  \"textSaveClearFailed\": [\n    {\n      \"type\": 0,\n      \"value\": \"Error: Failed to clear save data.\"\n    }\n  ],\n  \"textSaveDataImport\": [\n    {\n      \"type\": 0,\n      \"value\": \"Paste in your previously exported save data string here:\"\n    }\n  ],\n  \"textSaveExport\": [\n    {\n      \"type\": 0,\n      \"value\": \"Below is a compressed and encoded copy of your save data. You can later import this data to restore it.\"\n    }\n  ],\n  \"textSaveImportFailed\": [\n    {\n      \"type\": 0,\n      \"value\": \"Error: Failed to overwrite save data.\"\n    }\n  ],\n  \"textTaskStatistics\": [\n    {\n      \"type\": 0,\n      \"value\": \"Here are performance statistics of your program (as compared to others' programs):\"\n    }\n  ],\n  \"textVariablesEmpty\": [\n    {\n      \"type\": 0,\n      \"value\": \"(empty)\"\n    }\n  ],\n  \"tooltipCommentBlock\": [\n    {\n      \"type\": 0,\n      \"value\": \"Ctrl+K Ctrl+C\"\n    }\n  ],\n  \"tooltipIndentBlock\": [\n    {\n      \"type\": 0,\n      \"value\": \"Tab (in Tab Insert Mode only)\"\n    }\n  ],\n  \"tooltipMenu\": [\n    {\n      \"type\": 0,\n      \"value\": \"Esc or F1\"\n    }\n  ],\n  \"tooltipStep\": [\n    {\n      \"type\": 0,\n      \"value\": \"Ctrl+.\"\n    }\n  ],\n  \"tooltipStepRate\": [\n    {\n      \"type\": 0,\n      \"value\": \"Ctrl+Enter\"\n    }\n  ],\n  \"tooltipStop\": [\n    {\n      \"type\": 0,\n      \"value\": \"Esc or Ctrl+Shift+Enter\"\n    }\n  ],\n  \"tooltipTabInsertMode\": [\n    {\n      \"type\": 0,\n      \"value\": \"Ctrl+M\"\n    }\n  ],\n  \"tooltipUncommentBlock\": [\n    {\n      \"type\": 0,\n      \"value\": \"Ctrl+K Ctrl+U\"\n    }\n  ],\n  \"tooltipUnindentBlock\": [\n    {\n      \"type\": 0,\n      \"value\": \"Shift+Tab (in Tab Insert Mode only)\"\n    }\n  ],\n  \"windowConfigureInput\": [\n    {\n      \"type\": 0,\n      \"value\": \"Configure Input\"\n    }\n  ],\n  \"windowEditProfile\": [\n    {\n      \"type\": 0,\n      \"value\": \"User Profile\"\n    }\n  ],\n  \"windowHelp\": [\n    {\n      \"type\": 0,\n      \"value\": \"Help\"\n    }\n  ],\n  \"windowHint\": [\n    {\n      \"type\": 0,\n      \"value\": \"Hint\"\n    }\n  ],\n  \"windowIntro\": [\n    {\n      \"type\": 0,\n      \"value\": \"Job Application\"\n    }\n  ],\n  \"windowMail\": [\n    {\n      \"type\": 0,\n      \"value\": \"Electronic Mail\"\n    }\n  ],\n  \"windowMenu\": [\n    {\n      \"type\": 0,\n      \"value\": \"Main Menu\"\n    }\n  ],\n  \"windowOptions\": [\n    {\n      \"type\": 0,\n      \"value\": \"Options\"\n    }\n  ],\n  \"windowSaveClear\": [\n    {\n      \"type\": 0,\n      \"value\": \"Clear Data\"\n    }\n  ],\n  \"windowSaveClearConfirm\": [\n    {\n      \"type\": 0,\n      \"value\": \"Clear Data?\"\n    }\n  ],\n  \"windowSaveExport\": [\n    {\n      \"type\": 0,\n      \"value\": \"Export Data\"\n    }\n  ],\n  \"windowSaveImport\": [\n    {\n      \"type\": 0,\n      \"value\": \"Import Data\"\n    }\n  ],\n  \"windowSaveManage\": [\n    {\n      \"type\": 0,\n      \"value\": \"Manage Save Data\"\n    }\n  ],\n  \"windowSaveOverwrite\": [\n    {\n      \"type\": 0,\n      \"value\": \"Overwrite Data?\"\n    }\n  ],\n  \"windowTasks\": [\n    {\n      \"type\": 0,\n      \"value\": \"Program Inventory\"\n    }\n  ],\n  \"windowTitleAvoision\": [\n    {\n      \"type\": 0,\n      \"value\": \"Avoision\"\n    }\n  ],\n  \"windowTitleConfirmDelete\": [\n    {\n      \"type\": 0,\n      \"value\": \"Confirm Deletion\"\n    }\n  ],\n  \"windowTitleCredits\": [\n    {\n      \"type\": 0,\n      \"value\": \"Credits\"\n    }\n  ],\n  \"windowTitleHalt\": [\n    {\n      \"type\": 0,\n      \"value\": \"Program Halted\"\n    }\n  ],\n  \"windowTitleLicenses\": [\n    {\n      \"type\": 0,\n      \"value\": \"Licenses\"\n    }\n  ],\n  \"windowTitleNameExists\": [\n    {\n      \"type\": 0,\n      \"value\": \"Name Already Exists\"\n    }\n  ],\n  \"windowTitleNameInvalid\": [\n    {\n      \"type\": 0,\n      \"value\": \"Invalid Name\"\n    }\n  ],\n  \"windowTitleNoProgram\": [\n    {\n      \"type\": 0,\n      \"value\": \"No Program\"\n    }\n  ],\n  \"windowTitlePresentationSettings\": [\n    {\n      \"type\": 0,\n      \"value\": \"Presentation\"\n    }\n  ]\n}", "sic1/client/content/md/s8.md": "---\nfrom: badManager\nsubject: Great start!\n---\nNice work on the arithmetic programs, {{self.name}}! As of this electronic mail, you have been promoted to **{{jobTitles[2].title}}**.\n\nI know it's getting late (and please try to keep this to yourself), but our team really needs to improve our velocity. If there's any way you can stay late and complete your next task *today*, there is a very good chance that I'll be able to promote you to Senior Engineer (and that comes with a hefty pay bump).\n\nAgain, keep this to yourself. This sort of rapid promotion is extremely rare. Obviously, I can't guarantee anything, but if you can knuckle down and churn out this next task, things are looking pretty good...\n\nThank you!\n\n-{{from.name}}\n", "sic1/client/content/md/s27_1.md": "---\nfrom: hr\nto: [all]\nsubject: Ilano meet & greet\n---\nEngineering team,\n\nUnfortunately, due to a scheduling conflict with an executive retreat, Ilano is not available for the previously planned meet & greet today.\n\nWe will reschedule for next week, at which point you can submit questions for him to answer.\n\nSorry for the late notice!\n\n-{{from.name}}\n", "sic1/client/content/md/s4_1.md": "---\nfrom: mentor\nsubject: Sandbox Mode\nactions: [sandbox]\n---\nGreetings, {{self.name}}.\n\nI wanted to share with you a little side project I've been working on. I'm calling it \"Sandbox Mode\". Basically, it's a special SIC-1 Emulator mode that allows you to specify your own input.\n\nThis is useful when you just want to play around with the SIC-1 to see how things work. You can experiment with this to test out new techniques without worrying about output getting flagged as incorrect.\n\nSandbox Mode should be visible up in your Program Inventory under the \"Diversions\" group.\n\nLet me know what you think!\n\n-{{from.name}}\n", "sic1/client/content/md/s30.md": "---\nfrom: owner\nsubject: Unbelievable work!\n---\nTruly amazing work, {{self.name}}!\n\nThank you from the bottom of my heart for all of the sacrifices you've made to get us to this point. The SIC-1 is now able to reason about its own code. This is an amazing breakthrough and you should be very proud.\n\nNow that we've reached this exciting milestone (thanks to your tireless efforts!), SIC Systems honestly can't challenge someone with your peerless talent. Excitingly, you can now begin the next phase of your career at one of the many other technology companies around the world. I know parting ways is tough, but SIC Systems is a business, not a family, so we have to say goodbye to employees once they're no longer needed. Thank you one last time, and best of luck in your future endeavors!\n\n-{{from.name}}\n", "sic1/client/content/md/s14.md": "---\nfrom: goodManager\nsubject: Excellent work!\n---\nYou're making great progress, {{self.name}}! These are some very difficult tasks and you're breezing right through them!\n\nI'll make sure that Rick knows you're doing great work. I'm pushing hard for you to get promoted, because you really deserve it.\n\nWell done!\n\n-{{from.name}}\n", "sic1/client/content/md/s20.md": "---\nfrom: flunky1\nsubject: Dust off your resume\n---\nHey, {{self.name}}.\n\nI don't know if you've heard, but there are rumors that layoffs are coming. Now might be a good time to dust off your resume!\n\nSpeaking of which, do you think you'd have a few minutes to drop by my cubicle and tell me what you think of my resume?\n\nDo you think it would be a stretch to say that I lead development of sequence processing for the SIC-1 (when I was really only just part of a larger team that worked on it)?\n\nThanks, man!\n\n-{{from.name}}\n", "sic1/client/content/md/s26_0.md": "---\nfrom: owner\nto: [otherSkip, self]\nsubject: A new focus\n---\nJerin and {{self.name}},\n\nThanks for welcoming me. I'm excited to work with you!\n\nYour team's work on natural language processing is near and dear to my heart. As you may have heard, I founded Neutralino a few years back, with a goal of allowing a machine to reason about itself.\n\nI'd like to task you with a special project to bring a similar capability to the SIC-1, ideally by the end of this quarter. I've been shopping around this capability to various governments around the world, and already have \"hand shake\" agreements for a few multi-billion dollar orders.\n\nTo say that this work is important would be an understatement. It is revolutionary!\n\nRegards,\n\n-{{from.name}}\n", "sic1/client/content/md/dev-environment.md": "---\nfrom: onboarding\nsubject: SIC-1 Dev. Environment\nactions: [manualInNewWindow]\n---\n### SIC-1 DEVELOPMENT ENVIRONMENT\nThe SIC-1 Development Environment provides a state-of-the-art programming and simulation environment for SIC Systems's Single Instruction Computer Mark 1 (SIC-1).\n\n### MENUS\nMenus can be accessed using either the \"Esc\" key or the \"Menu\" button in the lower-left of the development environment. The Main Menu provides access to the following:\n\n* **Program Inventory**: Used for switching between assigned programming tasks, as well as viewing employee and task statistics (described in a dedicated section below).\n* **Electronic Mail**: An integrated client application for viewing electronic mail from automated agents and other SIC-1 employees (described in a dedicated section below).\n* **Options**: A sub-menu for modifying presentation settings (full-screen mode, volume, etc.), and other miscellaneous menus.\n\n### INTEGRATED DEVELOPMENT ENVIRONMENT\nThe SIC-1 Development Environment desktop is an integrated development environment (IDE) for the SIC-1. There are three main sections (left, right, center):\n\n* **Left**: Current task description, table of input and output (both expected and actual), simulation state/statistics, buttons for controlling the simulation, and a button for opening the Main Menu (described above).\n* **Center**: Main code editor for reading and writing SIC-1 Assembly Language programs (see the separate SIC-1 Reference Manual electronic mail for details).\n* **Right**: Detailed simulation state including a complete view of SIC-1 memory, code manipulation tools, as well as an unprecedented, revolutionary feature: a table of variables and their current values, for convenient lookup.\n\nThe memory table is shown in hexadecimal for compactness; hover over a cell to see the corresponding decimal value.\n\nDuring execution, the current instruction will be highlighted in both the code editor (center) and the memory table (upper right), current inputs and outputs are highlighted in the tables on the left, and variables are displayed in a table on the right (hover for hexadecimal and unsigned representations, if needed).\n\nTo aid debugging, it is possible to set breakpoints on `subleq` instructions. When hit, these breakpoints will pause execution for manual analysis. There are two ways to set breakpoints:\n\n* In code, add `!` to the beginning of a line (e.g. `!subleq @OUT, @IN`).\n* During execution, click the small circle to the left of any `subleq` instruction to toggle the breakpoint.\n\nNote that each program may be tested using multiple distinct test sets, the state of the SIC-1 resets between test sets, and the test sets generally include randomly generated input data. Solutions should be robust to arbitrary random data, in order to be eligible for inclusion in solution statistics.\n\n### KEYBOARD SHORTCUTS\nThe SIC-1 Development Environment supports the following convenient keyboard shortcuts:\n\n* **Esc**: Open/close menu or, if running, pause/halt execution.\n* **Ctrl+.**: Execute a single instruction and pause. If the program has not been compiled yet, this will compile the program and pause before executing the first instruction.\n* **Ctrl+Enter**: Run instructions until completion/error/pause. If already running, this will increase the speed of execution.\n* **Ctrl+Shift+Enter**: Pause execution (if running), otherwise halt execution.\n* **F11, Alt+Enter**: Toggle full-screen mode.\n\nCode editing shortcuts:\n\n* **Ctrl+K Ctrl+F**: Comment out all of the selected lines\n* **Ctrl+K Ctrl+U**: Uncomment all of the selected lines\n* **Ctrl+M**: Toggle **Tab Insert** mode (by default the Tab key cycles focus, with Tab Insert mode, tabs can be entered into the code editor)\n* **Tab**: If in **Tab Insert** mode, insert tabs into the selected lines\n* **Shift+Tab**: If in **Tab Insert** mode, un-indent the selected lines\n\n### PROGRAM INVENTORY\nThe Program Inventory displays a list of assigned tasks on the left. There is also a special \"employee statistics\" section at the top for viewing how your progress compares to other SIC Systems employees.\n\nSelect any task on the left to view the description (or your solution's statistics, as compared to other employees' solutions, for completed tasks). There is button at the bottom to load the program into the development environment.\n\nUnder the \"File Selection\" heading, it's possible to manage multiple implementations of a task (notably: \"New\" creates a new solution with default contents, \"Copy\" duplicates an existing implementation). This can be useful when there is one solution optimizing for fewest cycles, and a different solution optimizing for accessing the least amount of memory.\n\nIf available, other non-task entries will appear in the Program Inventory, under the \"Diversions\" heading (such as Sandbox Mode or any company-sanctioned electronic video games--only for use during legally-mandated breaks).\n\n### ELECTRONIC MAIL\nSIC Systems is pioneering a new digital form of intra-office communication known as \"electronic mail\". This eliminates paper waste for memos, and also ensures that all communications are securely routed to only the intended recipients.\n\nA complete list of received electronic mail is shown in the left pane of the electronic mail viewer (sorted from oldest at the top to newest at the bottom). Note that automated mails are de-emphasized, but they can be opened to view statistics for your completed programming tasks.\n\nIf you have any unread mail, it will appear in a separate section at the top of the left page, for convenience.\n\nAlso, remember that you can always access the SIC-1 Reference Manual and this document about the SIC-1 Development Environment from your employee on-boarding mails at the top (oldest) part of the left pane of the electronic mail viewer.\n\n### ADDENDUM\nAlthough the SIC-1 Development Environment has been thoroughly tested, it is possible that you may encounter unexpected behavior in certain instances. The authors of the SIC-1 Development Environment have assured us that the most likely causes for such issues are either cosmic rays or large solar flares interfering with sensitive electronics in an unpredictable manner. The simplest way to recover from such interference is to unplug the computer, wait for 30 seconds to allow it to cool and eject any rogue electrons, and then plug it back in.\n", "sic1/client/content/md/s10.md": "---\nfrom: goodManager\nsubject: Rick's mail\n---\n{{self.name}},\n\nI just saw Rick's mail about Don being promoted for his innovations in sequence processing.\n\nCould you drop by my cubicle to discuss a few things?\n\nI recall seeing you working late the night before this breakthrough, and I'd just like to understand your involvement there. If your work was used, you deserve credit for it.\n\nRegards,\n\n-{{from.name}}\n", "sic1/client/content/md/s25.md": "---\nfrom: otherSkip\nsubject: Right-sizing our team\n---\n{{self.name}},\n\nI wanted to let you know that Rick, Don, and Ted have all been let go.\n\nOn the surface, it might sound like this means that all the remaining natural language work now falls on your plate. But there's a silver lining: I've been given the go-ahead to offer you some non-cash perks to help you manage your schedule, namely:\n\n* Free breakfast, lunch and dinner at the office\n* On-site laundry service\n* An optional home cleaning/maintenance service, if you need it\n\nThanks for pushing so hard these last few weeks and months!\n\n-{{from.name}}\n", "sic1/client/content/md/s11.md": "---\nfrom: goodManager\nsubject: Organizational change\n---\n{{self.name}},\n\nI know this is sudden and unexpected, but you're going to be joining my team, effective today. Additionally, you have been promoted to **{{jobTitles[3].title}}**.\n\nI'm still not entirely clear what happened with Don and the new sequence processing work, but Rick mentioned that Don was considering letting you go, and I thought that seemed unfair. Fortunately, Rick was willing to give me a chance to add you to my team.\n\nAnyway, whatever happened, it's in the past now and we need to focus on the road ahead.\n\nThanks for your hard work!\n\n-{{from.name}}\n", "sic1/client/content/md/s9.md": "---\nto: [badManager2, badManagerTeam]\nfrom: skip\nsubject: Congratulations, Don!\n---\nDon (and Don's team),\n\nIn recognition of Don's tireless efforts that have recently culminated in the ability of the SIC-1 to process sequences, I'd like everyone to join me in congratulating Don on his promotion to Principal Engineering Lead!\n\nDon, I don't know how you managed to get sequences up and running so quickly, but we all owe a great debt to you.\n\nThank you once again!\n\n-{{from.name}}", "sic1/client/content/md/s27_0.md": "---\nfrom: otherSkip\nsubject: Compensation\n---\n{{self.name}},\n\nI know we had discussed increasing your compensation, given the increased scope and impact of your work.\n\nUnfortunately, Ilano has put a freeze on all new spending, so there's nothing I can do. My hands are tied.\n\nHaving said that, I'm sure that once your work is complete and Ilano sees what you've been able to accomplish, he'll make sure you're duly compensated. He might even want to shift you over to one of his other companies where technical know-how is needed.\n\nJust keep your focus on the task at hand!\n\n-{{from.name}}\n", "sic1/client/content/md/s4_0.md": "---\nfrom: badManager\nsubject: Checking in\n---\nHey, {{self.name}}! How's it feel to be a full-time employee working on the cutting edge of revolutionary technology? Only a single instruction! Amazing!\n\nAnyway, I did see your question about the compensation package Mary provided to you. I apologize if the pay is lower than what you were expecting. Another HR mix-up! What can I say?\n\nI'll talk to Rick to see if we can make an exception and raise your pay immediately, but just keep in mind that this company has a lot of room to grow, so your hard efforts will be very well rewarded!\n\n-{{from.name}}\n", "sic1/client/content/md/s31.md": "---\nfrom: goodManager2\nsubject: Great to hear from you!\nactions: [credits]\n---\n{{self.name}},\n\nIt's great to hear from you!\n\nI heard that SIC Systems let you go immediately after you demoed your (incomplete) self-hosting program. Ilano is going to be kicking himself when he realizes that the implementation SIC Systems owns doesn't support self-modifying code!\n\nNow that you're solely in possession of the only *truly* self-hosting program for the SIC-1, my advice is: destroy it. Erase all copies, set them on fire, and bury the ashes out in the desert. Ilano doesn't deserve to ever take advantage of your work again.\n\nSpeaking of work, I wanted to let you know that I found a job at a small startup that is working on a home computer with a graphical interface. It's revolutionary stuff, and we need someone with your technical skills to go to market.\n\nIs there any chance you'd be open to discussing a lead engineering position over here?\n\nIf you're interested, let me know and I'll schedule a meeting with us and the two remaining founders (both named Steve, by coincidence).\n\nHope to hear from you soon!\n\n-{{from.name}}\n", "sic1/client/content/md/s15.md": "---\nfrom: goodManager\nsubject: Wow!\n---\nWow! Great job, {{self.name}}! It looks like you have a deep understanding of self-modifying code. That will be a valuable skill as we continue to push the boundaries of the SIC-1.\n\nIt's my honor to let you know that you've earned a very well-deserved promotion to **{{jobTitles[4].title}}**!\n\nKeep up the great work!\n\n-{{from.name}}\n", "sic1/client/content/md/s21.md": "---\nfrom: mentor\nsubject: Farewell!\n---\nGreetings, {{self.name}}.\n\nI just wanted to let you know that today will be my last day at SIC Systems. I've enjoyed working with you, and I hope that my occasional clarifying electronic mails have been as beneficial to your career as working with you has been to mine.\n\nI generally try to distance myself from office politics and rumors, but I wanted to let you know that I have credible information that the SIC Systems board is currently trying to fend off a hostile takeover by Ilano Moscato (a foreign billionaire who is rather eccentric, to put it mildly).\n\nBased on what I've heard from friends who've worked at Ilano's other companies, I'm expecting working conditions here to deteriorate rapidly. Ilano has a reputation for randomly pivoting strategies, overworking his employees, and even flouting certain laws.\n\nI urge you to consider looking for employment elsewhere.\n\nBest of luck to you, {{self.name}}!\n\n-{{from.name}}\n", "sic1/client/content/md/s26_1.md": "---\nfrom: otherSkip\nsubject: New focus, new title, new perks\n---\n{{self.name}},\n\nI'm sure you saw the mail from Ilano. He thinks highly of us, but he also expects a lot.\n\nTo properly motivate you, Ilano has created a new job title exclusively for you: **{{jobTitles[7].title}}**.\n\nYou've shown tenacity to get this far, and you'll need loads of it for the next batch of tasks. We need to give the SIC-1 the ability to understand its own code, in order to unleash its immense computing power on optimizing its own performance. In addition to existing perks, we'll be happy to provide:\n\n* Free super-vitamins (used by Ilano himself), produced by Herbaleaf\n* Optional sleeping quarters at the office\n* Discounted fertility preservation services\n\nWe just need you to push through this one last sprint to the finish line. Your fellow SIC Systems family members thank you for your perseverance!\n\n-{{from.name}}\n", "sic1/client/content/md/s2_1.md": "---\nfrom: flunky\nsubject: Help!\n---\nHi, {{self.name}}, I'm {{from.name}}. We met in the hallway earlier.\n\nIs there any chance you could come over to my cubicle and help me with the first assessment? I'd ask Feng for help, but I haven't seen him around yet this morning.\n\nYesterday, Feng mentioned something about just using a label that initially points to the value zero, but what does that even mean??? He also said something about being able to reset a variable back to zero by subtracting itself. Is that a thing? I'm so lost!\n\nThanks for your time!\n\n-{{from.name}}\n", "sic1/client/content/md/s6.md": "---\nfrom: flunky1\nsubject: Loops???\n---\n{{self.name}}, I'm really stuck! Do you have any time to come help me with the multiplication task?\n\nI already asked Feng for some help, but all he told me is that I could run a loop a specific number of times by subtracting 1 from a counter each time and then using the result to branch.\n\nWhat does that even mean???\n\n-{{from.name}}\n", "sic1/client/content/md/s3_0.md": "---\nfrom: hr\nsubject: Training complete!\n---\nThanks for completing your training, {{self.name}}! Your starting job title is: **{{jobTitles[1].title}}**.\n\nYour finalized compensation package is described in the packet I left on your desk. As always, let me know if you have any questions.\n\nThank you!\n\n-{{from.name}}\n", "sic1/client/content/md/s2_0.md": "---\nfrom: badManager\nsubject: Good news!\n---\n{{self.name}},\n\nAfter talking with Rick, we've decided that it's not fair to make you complete training without compensating you. Hopefully your sitting down for this, because I've got some thrilling news.\n\n**We're providing free pizza lunches to all trainees!**\n\nSee? I told you I'd make it up to you.\n\nThanks for working hard!\n\n-{{from.name}}\n", "sic1/client/content/md/s3_1.md": "---\nfrom: mentor\nsubject: My mental model for SIC-1\n---\nGreetings, {{self.name}}. I'm also on Don's team and my name is {{from.name}}. Let me know if you ever need any assistance.\n\nAfter helping Ted with the first assessment, I thought I'd share my perspective on how to think about SIC-1 Assembly Language:\n\n* **Addresses** are just numbers that identify a specific byte of memory (0 for the first byte, 1 for the second, and so on, up to 255)\n* **Labels** are just names for addresses--specifically, the address of whatever comes next in your code (whether it's a `subleq` or a `.data`)\n* `subleq` always compiles into 3 bytes (each one an address)--if you omit the third address, it just gets set to the address of the next instruction in memory\n* `.data` just sets one or more bytes of memory to specific values (positive or negative numbers, or even labels, i.e. addresses)\n\nIn the end, everything compiles down to bytes in memory (which you can see in the memory table after you click \"Compile\" or \"Run\" to load the program). While running, the SIC-1 only sees those bytes in memory, and it doesn't know or care how those bytes were produced (or even modified). It will happily interpret any 3 bytes as a `subleq` instruction--even if that's not what you intended.\n\nIt can be instructive to look at a chunk of code and see the resulting compiled bytes. Here's an example:\n\n```\n@loop:\nsubleq @OUT, @IN           ; 3 byte instruction stored at address 0\nsubleq @zero, @zero, @loop ; 3 byte instruction stored at address 3\n\n@zero: .data 0             ; Initializes address 6 to zero\n```\n\n* `@loop` refers to address 0, i.e. the first instruction\n* The first `subleq` occupies bytes 0, 1, and 2, and is compiled to: 254 (`@OUT`), 253 (`@IN`), 3 (the next instruction)\n* The second `subleq` occupies bytes 3, 4, and 5, and is compiled to: 6 (`@zero`), 6 (`@zero`), 0 (`@loop`)\n* `@zero` refers to address 6, i.e. the next byte (which is initialized to zero using the `.data` directive)\n\nAs you know by now, the first instruction negates an input and writes it out, then advances to the next instruction (regardless of the result). The second instruction subtracts the value at address 6 from itself, always resulting in zero, and thus always jumps to its third argument: `@loop`, i.e. address 0 (the beginning of the program).\n\nHope that helps!\n\n-{{from.name}}\n", "sic1/client/content/md/s18.md": "---\nfrom: goodManager\nsubject: A promotion, and a new project!\n---\nSpectacular work, {{self.name}}! Based on your innovative solutions, you have been promoted to **{{jobTitles[5].title}}**.\n\nPlease don't mention this to anyone else, but I've heard rumors that Don (your old boss) and Jerin (another manager) are struggling to make progress on their natural language processing pipeline for the SIC-1.\n\nTo be honest, I don't think their team has any engineers of your caliber. I know it's risky, but I'd like to put you to work on solving some of the natural language problems (under the radar, so to speak).\n\nIf we can show definitive progress soon, then I think the board would be willing to move the whole project onto our team. That would be a big (and, frankly, unprecedented) promotion for you.\n\nLet me know if you have any concerns. And please don't share this will anyone (especially Ted)!\n\nThank you!\n\n-{{from.name}}\n", "sic1/client/content/md/s22_0.md": "---\nfrom: otherSkip\nto: [skip, goodManager, goodManagerTeam]\nsubject: Natural language processing\n---\nRick and Pat,\n\nIt has come to my attention that Pat's team has been discreetly working on natural language processing.\n\n**This absolutely must stop.**\n\nMy team has been solely tasked (by the SIC Systems board) with designing and implementing the natural language processing pipeline for the SIC-1.\n\nYour work is redundant and, to be blunt, a misuse of corporate resources. We cannot have two teams working independently on the same problem.\n\nPat, please turn over any documents you've created as a part of this duplicate effort immediately or I'll be forced to refer your entire team to corporate affairs for disciplinary action.\n\n-{{from.name}}\n", "sic1/client/content/md/s0.md": "---\nfrom: hr\nsubject: Welcome to SIC Systems!\nactions: [manual,manualInNewWindow]\n---\nCongratulations, {{self.name}}! SIC Systems has accepted your job application.\n\nI'm {{from.name}}, and I'll be your human resources contact at the company.\n\nAs you're no doubt aware, as a new trainee, you'll need to complete a few unpaid training tasks before you're instated as a full-time employee.\n\nYou should have already received a couple of electronic mails from our automated onboarding system that you can review:\n\n* The SIC-1 Reference Manual, which includes details on `subleq` and SIC-1 Assembly Language\n* A guide to the SIC-1 Development Environment (including usage information, keyboard shortcuts, etc.)\n\nYou can view these mails at any time in the electronic mail viewer, which can be opened using the main menu (which is accessed using the \"Menu\" button in the lower-left, or by pressing \"Esc\").\n\nAll information is, of course, confidential and covered by the nondisclosure agreement you signed as a condition of employment.\n\nPlease let me know if you have any other questions.\n\nThank you!\n\n-{{from.name}}\n", "sic1/client/content/md/s28.md": "---\nfrom: owner\nto: [all]\nsubject: UNACCEPTABLE!\n---\nMary,\n\nThe food at the executive retreat was absolutely horrible. I don't know how these events worked before, but I always treat my executives to the finest culinary delights the world has to offer.\n\nThe caviar was almost inedible (definitely *not* the Caspian Sea beluga caviar I had specifically requested), and the cocktail weenies were similarly unpalatable (anything less than Boar's Pride should go in the dumpster).\n\nWhat a disgrace!\n\n-{{from.name}}\n\nP.S. Please reject all meeting requests with staff for the rest of the week. And please come up with convincing excuses this time!\n", "sic1/client/content/md/avoision.md": "To help improve morale, SIC Systems has provided an officially sanctioned computer video game called \"Avoision\" for employees to play. If you think your work would benefit from an entertaining diversion, please feel free to compete against your coworkers for the highest score in \"Avoision\" (during your two legally-mandated unpaid breaks, or in lieu of an unneeded bathroom break).\n\n### Instructions\nUse the arrow keys to move your bright green block and try to capture the bright green square. The faster you capture the square, the more points you will score.\n\nAs you progress, moving dark green blocks will appear. If your bright green block collides with a dark green block, the game is over.\n\nClick the \"Play Avoision\" button below to play.\n", "sic1/client/content/md/s22_1.md": "---\nfrom: goodManager\nsubject: Please ignore Jerin's mail\n---\nHi, {{self.name}}.\n\nIt's unfortunate that Jerin sent that mail without consulting me or Rick first, but I want you to know that the work you're doing is very important and we shouldn't let office politics get in the way.\n\nYou have made fantastic progress on natural language processing, and I'm confident that once the board sees our tremendous progress, Jerin will be forced to back down. This isn't the first time an overzealous manager has come knocking on my door. Everything will be fine.\n\nAdditionally, **I have put together a proposal to create a new position for you, with a significant pay bump**. If you can finish this next task, I'm sure the board will have no other option than to promote you to *Distinguished Engineer*.\n\nThanks for all the hard work you've put in so far!\n\n-{{from.name}}\n", "sic1/client/content/md/s1.md": "---\nfrom: badManager\nsubject: Welcome to the team!\n---\nHello, {{self.name}}!\n\nI'm your manager, {{from.name}}, and I'm excited to have you join our team! We're working very hard to ship our flagship product, the SIC-1, on time and we need all the help we can get.\n\nYou've already met Mary from HR. The other members of your immediate team are Ted and Feng (note: their cubicles are unfortunately on the far end of this floor away from you--I'll see if I can get you moved closer). In case you see any welcome mail from Rick, be aware that he is my boss (so your skip-level boss). If you have any concerns, I kindly ask you to raise them directly with me before looping in Rick.\n\nWith introductions out of the way, let's talk about your job description. You are to implement programs as they're assigned to you. Your solutions will be compared to other employees' solutions on the basis of execution time (measured in cycles) and memory usage (measured in bytes).\n\nThanks in advance for your dedication!\n\n-{{from.name}}\n\nP.S. Sorry if it was unclear that you would not be paid during training. There must have been a mix-up on HR's end. I'll see if there's anything I can do to right the situation.\n", "sic1/client/content/md/s29.md": "---\nfrom: assistant\nto: [all]\nsubject: Clarification\n---\nEngineering team,\n\nPlease disregard the previous errant electronic mail that was purportedly sent by Ilano. That mail was apparently actually sent by a rogue human resources employee, Mary Townsend (who has since been fired).\n\nIlano treats all employees with dignity and respect, and would never complain about a matter so trivial as food catering at a meeting. He understands that budget cuts are difficult and, in fact, he has willingly slashed his own salary by 10% in solidarity with all SIC Systems staff.\n\nThank you, and have a great day!\n\n-{{from.name}}\n", "sic1/client/content/md/s5.md": "---\nfrom: mentor\nsubject: Constants\n---\nGreetings, {{self.name}}.\n\nAfter talking to Ted, I thought this might be a good time to remind everyone that you can use labels for both variables *and constants*. A label is really just an address, after all.\n\nFor example, if I want to be able to write out a 1, I could create a constant. Just remember that if you're subtracting the constant you'll want to negate the constant:\n\n```\nsubleq @OUT, @n_one ; Write out a 1 by subtracting -1 from @OUT\n                    ; Note: @OUT always reads as zero: 0 - (-1) = 1\n\n@n_one: .data -1    ; Constant\n```\n\n-{{from.name}}\n", "sic1/client/content/md/s19.md": "---\nfrom: badManager2\nsubject: Do you have a minute?\n---\n{{self.name}}, do you have a few minutes to drop by my office?\n\nI'd like to know if you have put any thought into joining Jerin and I to work on that exciting new natural language processing project I mentioned to you a little while back. It could mean a big promotion for you!\n\nIf you have any concerns, please, please let me know. It would be a shame to see your talents wasted on another team, to be honest. We're really working on some revolutionary stuff here!\n\nI'll stop by your cubicle in an hour or so, in case I don't hear from you by then.\n\nThanks!\n\n-{{from.name}}\n", "sic1/client/content/md/s24_0.md": "---\nfrom: hr\nto: [all]\nsubject: SIC Systems acquisition\n---\nEngineering team,\n\nAs reported in the news, SIC Systems has agreed to be acquired by Ilano Moscato (majority owner and CEO of Edison, Herbaleaf, and Neutralino).\n\nWhat this means for you:\n\n* Your day-to-day duties remain the same\n* No major changes to the organization are planned\n* Ilano has indicated that he will honor all existing approved compensation packages (both cash and equity)\n\nIn other words: \"business as usual\".\n\nPlease don't let reports in the media distract you from your work.\n\nLet me know if you have any questions. Thank you!\n\n-{{from.name}}\n", "sic1/client/content/md/s7_0.md": "---\nfrom: goodManager\nsubject: Nice work!\n---\nHi, {{self.name}}! I'm {{from.name}} and I'm another engineering lead (I actually work on the same team as your manager, Don).\n\nFeng (who used to report to me) mentioned that you've been making excellent progress!\n\nAnyway, I've been tasked with helping to improve morale across the team, so if there's anything that you especially like or don't like about the workplace or your compensation (or your team in general), feel free to send me a mail. I'll make sure to keep all discussions private.\n\nLooking forward to hearing from you!\n\n-{{from.name}}\n", "sic1/client/content/md/s12.md": "---\nfrom: mentor\nsubject: Debugging\n---\nGreetings, {{self.name}}.\n\nSelf-modifying code can be tricky to understand at first. For the \"stack memory\" example, I found that it's easiest to simply step through the program (using the \"Step\" button or \"Ctrl+.\") to see what it's doing. Remember that you can click the circle next to a `subleq` instruction to toggle a breakpoint.\n\nUsing this approach, you can see that the first bit of code is a loop that repeats as long as `@count` is greater than zero. Once the counter runs out, execution branches to the next chunk of code, and so on.\n\nYou can also watch the stack grow in the \"Memory\" table in the upper right. In the example, the stack happens to start at address 32 (defined by `@stack_address`), which is the beginning of the third row of the table. Note that numbers are shown in hexadecimal and the \"two's complement\" representation is used for negative numbers (meaning `80` in hex is -128 in decimal), so `ff` means -1, `fe` means -2, and so on.\n\nHope that helps!\n\n-{{from.name}}\n", "sic1/client/content/md/s16.md": "---\nfrom: badManager2\nsubject: Very impressive!\n---\nHi, {{self.name}}! It's been a while since we last chatted.\n\nHow do you like working on Pat's team? It looks like you're making excellent progress (between you and me, I think you're doing most, if not all, of the work, though).\n\nDon't share this with anyone, but I've been working with one of the other managers (Jerin Kransky) on setting up natural language processing functionality for the SIC-1.\n\nDo you have any interest in re-joining my team? I already have Jerin convinced that you're the right person for the job, and I think another promotion would be in order if you'd be willing to come join us.\n\nLet me know what you think!\n\n-{{from.name}}\n", "sic1/client/content/md/s17.md": "---\nfrom: flunky1\nsubject: Don\n---\nHey, {{self.name}}.\n\nI was chatting with Don while we played our weekly round of golf this week, and he said that you were planning to come back to his team to work on some secret new project.\n\nIt would be awesome to have you back on the team!\n\n-{{from.name}}\n\nP.S. Any chance you'd have time to walk me through your solution to the \"sort\" task? Thanks!", "sic1/client/content/md/s23.md": "---\nfrom: otherSkip\nsubject: Welcome aboard!\n---\nHi, {{self.name}}. In case we haven't met yet, I'm {{from.name}}, a peer to your old skip-level manager Rick. I'd like to congratulate you on the work you've done so far. What I've seen has been most impressive!\n\nEffective immediately, you'll be reporting directly to me to continue your exciting work on natural language processing.\n\nAdditionally, I'd like to inform you that you've been promoted to **{{jobTitles[6].title}}** (although, due to budget cuts, we won't be able to honor the original compensation package that was discussed).\n\nLooking forward to working with you!\n\n-{{from.name}}\n\nP.S. Pat is no longer employed by SIC Systems.\n", "sic1/client/content/md/s24_1.md": "---\nfrom: otherSkip\nsubject: New owner\n---\n{{self.name}},\n\nI just wanted to let you know that I met with our new owner, Ilano, earlier today, and he's very excited about the work you're doing.\n\nIf there's anything you might need to grind through the last couple of tricky problems, please let me know.\n\n-{{from.name}}\n", "sic1/client/content/md/s7_1.md": "---\nto: [all]\nfrom: hr\nsubject: Fun and games\nloadType: avoision\nloadLabel: Play Avoision\n---\nEngineering team,\n\nTo help improve morale, SIC Systems has provided an officially sanctioned computer video game called \"Avoision\" for employees to play. If you think your work would benefit from an entertaining diversion, please feel free to compete against your coworkers for the highest score in \"Avoision\" (during your two legally-mandated unpaid breaks, or in lieu of an unneeded bathroom break).\n\nYou can find \"Avoision\" in the \"Diversions\" section of the program inventory and also in the main menu of the SIC-1 Development Environment.\n\nEnjoy!\n\n-{{from.name}}\n", "sic1/client/content/md/s13.md": "---\nfrom: flunky1\nsubject: REVERSE SEQUENCE???\n---\nI'm completely lost! How can I reverse a sequence when I don't even know its length??\n\nFeng pointed me to the stack memory example, but that example only reverses 3 numbers. What if the sequence has 4 letters? Or 5???\n\nThis is starting to go way over my head... is there any chance I can copy your solution? I'll make sure to have it be a little slower so that it's not obvious I copied your work.\n\nHELP!!!\n\n-{{from.name}}\n", "sic1/shared/package.json": "{\n  \"name\": \"sic1-shared\",\n  \"version\": \"0.1.0\",\n  \"main\": \"puzzles.js\",\n  \"scripts\": {\n    \"build\": \"copy /y package.json dist && tsc -p .\",\n    \"watch\": \"tsc -w -p .\"\n  },\n  \"files\": [\n    \"puzzles.js\",\n    \"puzzles.d.ts\"\n  ],\n  \"dependencies\": {\n    \"sic1asm\": \"../../lib/dist\"\n  }\n}\n", "sic1/shared/tsconfig.json": "{\n    \"compilerOptions\": {\n        \"module\": \"commonjs\",\n        \"target\": \"ES2017\",\n        \"outDir\": \"dist\",\n        \"declaration\": true\n    },\n    \"files\": [\n        \"puzzles.ts\"\n    ]\n}\n", "sic1/shared/puzzles.ts": "import { AssembledProgram, Assembler, Emulator } from \"../../lib/src/sic1asm\";\n\nexport interface Puzzle {\n    title: string;\n    test?: {\n        fixed?: number[][][];\n        createRandomTest: () => number[][];\n        getExpectedOutput: (input: number[][]) => number[][];\n    };\n    io: ReadonlyArray<ReadonlyArray<ReadonlyArray<number>>>;\n}\n\nexport interface PuzzleTestSet {\n    input: number[];\n    output: number[];\n}\n\nexport interface PuzzleTest {\n    testSets: PuzzleTestSet[];\n}\n\nfunction flattenFixedTest(test: ReadonlyArray<ReadonlyArray<ReadonlyArray<number>>>): { input: number[], output: number[] } {\n    let input: number[] = [];\n    let output: number[] = [];\n    test.forEach(row => {\n        input = input.concat(row[0]);\n        output = output.concat(row[1]);\n    });\n\n    return { input, output };\n}\n\nfunction arrayEqual(a: number[], b: number[]): boolean {\n    if (a.length === b.length) {\n        for (let i = 0; i < a.length; i++) {\n            if (a[i] !== b[i]) {\n                return false;\n            }\n        }\n        return true;\n    } else {\n        return false;\n    }\n}\n\nexport function generatePuzzleTest(puzzle: Puzzle): PuzzleTest {\n    const testSets: PuzzleTestSet[] = [];\n\n    // Standard tests\n    const { input, output } = flattenFixedTest(puzzle.io);\n    testSets.push({ input, output });\n\n    // Extra and random tests\n    if (puzzle.test) {\n        // Fixed and random test sets\n        for (const fixedInput of (puzzle.test.fixed ?? []).concat([puzzle.test.createRandomTest()])) {\n            testSets.push({\n                input: ([] as number[]).concat(...fixedInput),\n                output: ([] as number[]).concat(...puzzle.test.getExpectedOutput(fixedInput)),\n            });\n        }\n\n        // Also add one that's similar to the first test set (but not identical!)\n        while (true) {\n            const test = puzzle.io.slice();\n            if (test.length <= 1) {\n                // Only one input set, so no real need to duplicate a random test\n                break;\n            }\n\n            const moreRandomInputGroups = puzzle.test.createRandomTest();\n            const randomIndex = Math.floor(moreRandomInputGroups.length * Math.random());\n            test.splice(test.length - 1, 1, [moreRandomInputGroups[randomIndex], puzzle.test.getExpectedOutput(moreRandomInputGroups)[randomIndex]]);\n\n            const testSet = flattenFixedTest(test);\n            if (!arrayEqual(testSet.input, input) && !arrayEqual(testSet.output, output)) {\n                testSets.push(testSet);\n                break;\n            }\n        }\n    }\n\n    return {\n        testSets,\n    }\n}\n\n// Backend/offline solution validation\nexport class ProgramVerificationError extends Error {\n    constructor(message: string, public errorContext: { inputs: number[], inputIndex?: number }) {\n        super(message);\n\n        // Ensure prototype is ProgramVerificationError\n        Object.setPrototypeOf(this, ProgramVerificationError.prototype);\n    }\n}\n\nfunction verifyProgram(context: string, inputs: number[], expectedOutputs: number[], program: AssembledProgram, maxCyclesExecuted: number, maxMemoryBytesAccessed: number): void {\n    let inputIndex = 0;\n    let outputIndex = 0;\n\n    let correct = true;\n    let errorContext = \"\";\n    const emulator = new Emulator(program, {\n        readInput: () => inputs[inputIndex++],\n        writeOutput: n => {\n            const expected = expectedOutputs[outputIndex++];\n            if (n !== expected) {\n                correct = false;\n                if (errorContext === \"\") {\n                    errorContext = `expected ${expected} but got ${n} instead at index ${outputIndex - 1}`;\n                }\n            }\n        },\n\n        onHalt: () => { throw new ProgramVerificationError(\"Execution halted unexpectedly\", { inputs, inputIndex }); },\n    });\n\n    while (correct && outputIndex < expectedOutputs.length && emulator.getCyclesExecuted() <= maxCyclesExecuted && emulator.getMemoryBytesAccessed() <= maxMemoryBytesAccessed) {\n        emulator.step();\n    }\n\n    if (emulator.getCyclesExecuted() > maxCyclesExecuted || emulator.getMemoryBytesAccessed() > maxMemoryBytesAccessed) {\n        throw new ProgramVerificationError(`Execution during ${context} did not complete within ${maxCyclesExecuted} cycles and ${maxMemoryBytesAccessed} bytes (actual: ${emulator.getCyclesExecuted()} cycles, ${emulator.getMemoryBytesAccessed()} bytes)`, { inputs, inputIndex });\n    }\n\n    if (!correct) {\n        throw new ProgramVerificationError(`Incorrect output produced during ${context} (${errorContext})`, { inputs, inputIndex });\n    }\n}\n\nexport const verificationMaxCycles = 100000;\nexport const solutionBytesMax = 256;\n\nexport function verifySolution(puzzle: Puzzle, bytes: number[], cyclesExecuted: number, memoryBytesAccessed: number): void {\n    const { testSets } = generatePuzzleTest(puzzle);\n    const program: AssembledProgram = {\n        bytes,\n        sourceMap: [],\n        variables: [],\n        breakpoints: [],\n    };\n\n    // Verify using standard input and supplied stats\n    verifyProgram(\"standard input\", testSets[0].input, testSets[0].output, program, cyclesExecuted, memoryBytesAccessed);\n\n    // Verify subsequent tests\n    for (let i = 1; i < testSets.length; i++) {\n        verifyProgram(`test set ${i + 1}`, testSets[i].input, testSets[i].output, program, verificationMaxCycles, solutionBytesMax);\n    }\n}\n\n// Helpers\nfunction randomPositive() {\n    return Math.floor(Math.random() * 10) + 1;\n}\n\nfunction randomKindOfLargePositive() {\n    return Math.floor(Math.random() * 99) + 1;\n}\n\nfunction randomLargePositive() {\n    return Math.floor(Math.random() * 101) + 1;\n}\n\nfunction randomNonnegative() {\n    return Math.floor(Math.random() * 10);\n}\n\nfunction randomPositiveSequence(sequenceLength: number = 6) {\n    const sequence = [];\n    for (let i = 0; i < sequenceLength; i++) {\n        sequence.push(randomPositive());\n    }\n    sequence.push(0);\n    return sequence;\n}\n\nfunction randomSet(setSize: number = 5) {\n    const pool = [];\n    for (let i = 0; i < setSize * 2; i++) {\n        pool.push(i + 1);\n    }\n\n    const set = [];\n    for (let i = 0; i < setSize; i++) {\n        const value = pool.splice(Math.floor(Math.random() * pool.length), 1)[0];\n        set.push(value);\n    }\n    set.push(0);\n    return set;\n}\n\nfunction charactersToNumbers(characters: string): number[] {\n    const numbers: number[] = [];\n    for (let i = 0; i < characters.length; i++) {\n        numbers.push(characters.charCodeAt(i));\n    }\n    return numbers;\n}\n\nfunction stringToNumbers(str: string): number[] {\n    const numbers = charactersToNumbers(str);\n    numbers.push(0);\n    return numbers;\n}\n\nfunction stringsToNumbers(strings: string[]): number[] {\n    const numbers: number[] = [];\n    for (const str of strings) {\n        numbers.push(...charactersToNumbers(str));\n        numbers.push(0);\n    }\n    return numbers;\n}\n\nexport function shuffleInPlace<T>(array: T[]): void {\n    for (let i = array.length - 1; i >= 1; i--) {\n        const index = Math.floor(Math.random() * (i + 1));\n        const tmp = array[i];\n        array[i] = array[index];\n        array[index] = tmp;\n    }\n}\n\nexport const puzzleFlatArray: Puzzle[] = [\n    {\n        title: \"Subleq Instruction and Output\",\n        io: [\n            [[3], [-3]]\n        ],\n    },\n    {\n        title: \"Data Directive and Looping\",\n        io: [\n            [[3], [-3]],\n            [[4], [-4]],\n            [[5], [-5]]\n        ],\n    },\n    {\n        title: \"First Assessment\",\n        test: {\n            createRandomTest: () => [1, 2, 3].map(a => [randomPositive()]),\n            getExpectedOutput: (input) => input,\n        },\n        io: [\n            [[1], [1]],\n            [[2], [2]],\n            [[3], [3]]\n        ],\n    },\n    {\n        title: \"Addition\",\n        test: {\n            fixed: [[[99, 28], [-100, 100], [1, -2]]],\n            createRandomTest: () => [1, 2, 3].map(a => [randomNonnegative(), randomNonnegative()]),\n            getExpectedOutput: (input) => input.map(a => [a[0] + a[1]]),\n        },\n        io: [\n            [[1, 1], [2]],\n            [[1, 2], [3]],\n            [[1, -1], [0]],\n            [[11, 25], [36]],\n            [[82, 17], [99]]\n        ],\n    },\n    {\n        title: \"Subtraction\",\n        test: {\n            fixed: [[[100, 101], [111, 72], [1, -120]]],\n            createRandomTest: () => [1, 2, 3].map(a => [randomNonnegative(), randomNonnegative()]),\n            getExpectedOutput: (input) => input.map(a => [a[0] - a[1]]),\n        },\n        io: [\n            [[1, 1], [0]],\n            [[1, 2], [-1]],\n            [[1, -1], [2]],\n            [[11, 25], [-14]],\n            [[82, 17], [65]]\n        ],\n    },\n    {\n        title: \"Sign Function\",\n        test: {\n            fixed: [\n                [[127], [99], [-100], [1], [0], [99], [1]],\n                [[-1], [-1], [-2], [3], [0], [0]],\n                [[-1], [1], [2], [-3], [0], [0]],\n            ],\n            createRandomTest: () => [1, 2, 3, 4].map(a => [Math.floor(Math.random() * 5) - 2]),\n            getExpectedOutput: (input) => input.map(a => a.map(b => b < 0 ? -1 : (b > 0 ? 1 : 0))),\n        },\n        io: [\n            [[-1], [-1]],\n            [[0], [0]],\n            [[1], [1]],\n            [[7], [1]],\n            [[-29], [-1]],\n            [[99], [1]],\n            [[-99], [-1]]\n        ],\n    },\n    {\n        title: \"Multiplication\",\n        test: {\n            fixed: [[[11, 11], [2, 3, 0, 0], [11, 0]]],\n            createRandomTest: () => [1, 2, 3].map(a => [randomNonnegative(), randomNonnegative()]),\n            getExpectedOutput: (input) => input.map(a => {\n                const result: number[] = [];\n                for (let i = 0; i < a.length; i += 2) {\n                    result.push(a[i] * a[i + 1]);\n                }\n                return result;\n            }),\n        },\n        io: [\n            [[1, 0], [0]],\n            [[0, 1], [0]],\n            [[1, 1], [1]],\n            [[2, 3], [6]],\n            [[7, 13], [91]]\n        ],\n    },\n    {\n        title: \"Division\",\n        test: {\n            fixed: [[[122, 11], [16, 3], [7, 7]]],\n            createRandomTest: () => [1, 2, 3, 4].map(a => [randomPositive(), randomPositive()]),\n            getExpectedOutput: (input) => input.map(a => [Math.floor(a[0] / a[1]), a[0] % a[1]]),\n        },\n        io: [\n            [[1, 1], [1, 0]],\n            [[9, 3], [3, 0]],\n            [[17, 2], [8, 1]],\n            [[67, 9], [7, 4]]\n        ],\n    },\n    {\n        title: \"Sequence Sum\",\n        test: {\n            fixed: [[[100, 20, 7, 0]]],\n            createRandomTest: () => [1, 2, 3].map(a => randomPositiveSequence()),\n            getExpectedOutput: (input) => input.map(a => [a.reduce((sum, value) => sum + value, 0)]),\n        },\n        io: [\n            [[1, 1, 1, 0], [3]],\n            [[1, 2, 3, 0], [6]],\n            [[3, 5, 7, 11, 0], [26]],\n            [[53, 13, 22, 9, 0], [97]]\n        ],\n    },\n    {\n        title: \"Sequence Cardinality\",\n        test: {\n            fixed: [[[100, 100, 100, 0]]],\n            createRandomTest: () => [1, 2].map(a => randomPositiveSequence(Math.floor(Math.random() * 4) + 2)),\n            getExpectedOutput: (input) => input.map(a => [a.reduce((sum) => sum + 1, -1)]),\n        },\n        io: [\n            [[0], [0]],\n            [[1, 0], [1]],\n            [[3, 4, 0], [2]],\n            [[9, 2, 7, 13, 26, 0], [5]],\n        ],\n    },\n    {\n        title: \"Number to Sequence\",\n        test: {\n            fixed: [[[2], [0], [3], [0]]],\n            createRandomTest: () => [1, 2].map(a => [randomPositive()]),\n            getExpectedOutput: (input) => input.map(value => {\n                const output = [];\n                for (let i = 0; i < value[0]; i++) {\n                    output.push(1);\n                }\n                output.push(0);\n                return output;\n            }),\n        },\n        io: [\n            [[0], [0]],\n            [[1], [1, 0]],\n            [[2], [1, 1, 0]],\n            [[5], [1, 1, 1, 1, 1, 0]],\n            [[3], [1, 1, 1, 0]],\n            [[7], [1, 1, 1, 1, 1, 1, 1, 0]]\n        ],\n    },\n    {\n        title: \"Self-Modifying Code\",\n        io: [\n            [[0], [12, 1, 3, -2, 12, 6, 1, 13, 9, 12, 12, 0]]\n        ],\n    },\n    {\n        title: \"Stack Memory\",\n        io: [\n            [[3, 5, 7], [7, 5, 3]]\n        ],\n    },\n    {\n        title: \"Reverse Sequence\",\n        test: {\n            fixed: [[[98, 99, 100, 0]]],\n            createRandomTest: () => [1, 2].map(() => randomPositiveSequence()),\n            getExpectedOutput: input => input.map(seq => seq.slice(0, seq.length - 1).reverse().concat([0])),\n        },\n        io: [\n            [[1, 2, 3, 0], [3, 2, 1, 0]],\n            [[3, 2, 1, 0], [1, 2, 3, 0]],\n            [[3, 5, 7, 11, 13, 15, 17, 0], [17, 15, 13, 11, 7, 5, 3, 0]]\n        ],\n    },\n    {\n        title: \"Interleave\",\n        test: {\n            createRandomTest: () => [1, 2].map(() => randomPositiveSequence(3).concat(randomPositiveSequence(3))),\n            getExpectedOutput: input => input.map(seq => {\n                const output = [];\n                for (let i = 0; i < seq.length / 2; i++) {\n                    output.push(seq[i]);\n                    output.push(seq[i + seq.length / 2]);\n                }\n                output.pop();\n                return output;\n            }),\n        },\n        io: [\n            [[1, 1, 1, 0, 2, 2, 2, 0], [1, 2, 1, 2, 1, 2, 0]],\n            [[9, 8, 7, 0, 10, 20, 30, 0], [9, 10, 8, 20, 7, 30, 0]],\n            [[3, 5, 7, 11, 0, 13, 17, 19, 23, 0], [3, 13, 5, 17, 7, 19, 11, 23, 0]],\n        ],\n    },\n    {\n        title: \"Indicator Function\",\n        test: {\n            fixed: [[[13, 57, 99, 63, 0, 13, 99, 57, 0], [61, 62, 63, 64, 0, 66, 64, 62, 60, 0], [97, 98, 99, 0, 77, 88, 99, 0]]],\n            createRandomTest: () => [1, 2].map(() => randomSet().concat(randomSet())),\n            getExpectedOutput: input => input.map(seqIn => {\n                const seq = seqIn.slice();\n                const a = seq.splice(0, seq.indexOf(0));\n                seq.shift();\n                const b = seq.splice(0, seq.indexOf(0));\n                return b.map(value => (a.indexOf(value) >= 0) ? 1 : 0);\n            }),\n        },\n        io: [\n            [[2, 4, 6, 0, 1, 2, 3, 0], [0, 1, 0]],\n            [[3, 5, 7, 0, 9, 6, 3, 0], [0, 0, 1]],\n        ],\n    },\n    {\n        title: \"Sort\",\n        test: {\n            fixed: [[[93, 94, 95, 96, 97, 98, 99, 0]]],\n            createRandomTest: () => [1, 2].map(() => randomPositiveSequence()),\n            getExpectedOutput: input => input.map(seq => seq.slice(0, seq.length - 1).sort((a, b) => a - b).concat([0])),\n        },\n        io: [\n            [[3, 1, 2, 0], [1, 2, 3, 0]],\n            [[9, 9, 5, 0], [5, 9, 9, 0]],\n            [[17, 13, 19, 5, 23, 7, 0], [5, 7, 13, 17, 19, 23, 0]],\n        ],\n    },\n    {\n        title: \"Mode\",\n        test: {\n            fixed: [[[96, 97, 98, 97, 96, 98, 99, 96, 98, 96, 0], [87, 49, 87, 3, 49, 49, 3, 0]]],\n            createRandomTest: () => [1, 2].map((count) => {\n                const numbers = [1, 2, 3].map(n => randomKindOfLargePositive());\n                const input = [];\n                for (let j = 0; j < 3; j++) {\n                    for (let c = 0; c <= count; c++) {\n                        input.push(numbers[j]);\n                    }\n                }\n                input.push(numbers[Math.floor(Math.random() * numbers.length)]);\n                shuffleInPlace(input);\n                input.push(0);\n                return input;\n            }),\n            getExpectedOutput: input => input.map(seq => {\n                let counts = {};\n                for (const value of seq) {\n                    if (counts[value]) {\n                        counts[value]++;\n                    } else {\n                        counts[value] = 1;\n                    }\n                }\n\n                let max = 0;\n                let mode = 0;\n                for (const key in counts) {\n                    if (counts[key] > max) {\n                        max = counts[key];\n                        mode = parseInt(key);\n                    }\n                }\n                return [mode];\n            }),\n        },\n        io: [\n            [[1, 2, 3, 3, 0], [3]],\n            [[1, 2, 1, 2, 1, 0], [1]],\n            [[3, 1, 2, 3, 1, 2, 3, 3, 1, 2, 2, 2, 0], [2]],\n        ],\n    },\n    {\n        title: \"Characters\",\n        io: [\n            [[0], charactersToNumbers(\"Hi\")],\n        ],\n    },\n    {\n        title: \"Decimal Digits\",\n        test: {\n            fixed: [[charactersToNumbers(\"0\"), charactersToNumbers(\"9\")]],\n            createRandomTest: () => [1, 2, 3, 4, 5, 6].map(n => charactersToNumbers(Math.floor(Math.random() * 10).toString())),\n            getExpectedOutput: input => input.map(seq => [parseInt(String.fromCharCode(seq[0]))]),\n        },\n        io: [\n            [charactersToNumbers(\"1\"), [1]],\n            [charactersToNumbers(\"2\"), [2]],\n            [charactersToNumbers(\"7\"), [7]],\n        ],\n    },\n    {\n        title: \"Uppercase\",\n        test: {\n            fixed: [[[\"a\".charCodeAt(0)], [\"z\".charCodeAt(0)], [\"a\".charCodeAt(0) - 1], [\"z\".charCodeAt(0) + 1]]],\n            createRandomTest: () => [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13].map(n => [Math.floor(Math.random() * 75) + 48]),\n            getExpectedOutput: input => input.map(seq => [String.fromCharCode(seq[0]).toUpperCase().charCodeAt(0)]),\n        },\n        io: [\n            [charactersToNumbers(\"U\"), charactersToNumbers(\"U\")],\n            [charactersToNumbers(\"r\"), charactersToNumbers(\"R\")],\n            [charactersToNumbers(\"g\"), charactersToNumbers(\"G\")],\n            [charactersToNumbers(\"e\"), charactersToNumbers(\"E\")],\n            [charactersToNumbers(\"n\"), charactersToNumbers(\"N\")],\n            [charactersToNumbers(\"t\"), charactersToNumbers(\"T\")],\n            [charactersToNumbers(\"!\"), charactersToNumbers(\"!\")],\n        ],\n    },\n    {\n        title: \"Strings\",\n        io: [\n            [[0], stringToNumbers(\"Hello, world!\")],\n        ],\n    },\n    {\n        title: \"Tokenizer\",\n        test: {\n            fixed: [[stringToNumbers(\"subleq @OUT @IN\"), stringToNumbers(\".data 0\")]],\n            createRandomTest: () => [stringToNumbers([1, 2, 3].map(n => String.fromCharCode(...[1, 2, 3].map(n2 => Math.floor(Math.random() * 75) + 48))).join(\" \"))],\n            getExpectedOutput: input => input.map(seq => stringsToNumbers(String.fromCharCode(...seq.slice(0, seq.length - 1)).split(\" \"))),\n        },\n        io: [\n            [stringToNumbers(\"The quick brown fox loves SIC Systems\"), stringsToNumbers([\"The\", \"quick\", \"brown\", \"fox\", \"loves\", \"SIC\", \"Systems\"])],\n        ],\n    },\n    {\n        title: \"Parse Decimal\",\n        test: {\n            fixed: [[stringToNumbers(\"123\"), stringToNumbers(\"9\")]],\n            createRandomTest: () => [1, 2, 3].map(n => stringToNumbers(randomLargePositive().toString())),\n            getExpectedOutput: input => input.map(seq => [parseInt(String.fromCharCode(...seq.slice(0, seq.length - 1)))]),\n        },\n        io: [\n            [stringToNumbers(\"1\"), [1]],\n            [stringToNumbers(\"20\"), [20]],\n            [stringToNumbers(\"74\"), [74]],\n        ],\n    },\n    {\n        title: \"Print Decimal\",\n        test: {\n            fixed: [[[123], [9], [100], [101], [12]]],\n            createRandomTest: () => [1, 2, 3].map(n => [randomLargePositive()]),\n            getExpectedOutput: input => input.map(seq => stringToNumbers(seq[0].toString())),\n        },\n        io: [\n            [[1], stringToNumbers(\"1\")],\n            [[20], stringToNumbers(\"20\")],\n            [[74], stringToNumbers(\"74\")],\n        ],\n    },\n    {\n        title: \"Calculator\",\n        test: {\n            fixed: [[stringToNumbers(\"10 * 11\"), stringToNumbers(\"120 - 61\"), stringToNumbers(\"61 + 62\"), stringToNumbers(\"8 * 1\")]],\n            createRandomTest: () => [1, 2, 3, 4].map(n => {\n                const operations = [\"+\", \"-\", \"*\"];\n                const operation = operations[Math.floor(Math.random() * operations.length)];\n                let a: number;\n                let b: number;\n                switch (operation) {\n                    case \"+\":\n                        a = randomLargePositive();\n                        b = Math.floor(Math.random() * (120 - a)) + 1;\n                        break;\n\n                    case \"-\":\n                        a = randomLargePositive();\n                        b = randomLargePositive();\n                        break;\n\n                    case \"*\":\n                        a = Math.floor(Math.random() * 11) + 1;\n                        b = Math.floor(Math.random() * 11) + 1;\n                        break;\n                }\n\n                return stringToNumbers(`${a} ${operation} ${b}`);\n            }),\n            getExpectedOutput: input => input.map(seq => {\n                const parts = String.fromCharCode(...seq.slice(0, seq.length - 1)).split(\" \");\n                const a = parseInt(parts[0]);\n                const b = parseInt(parts[2]);\n                switch (parts[1]) {\n                    case \"+\": return [a + b];\n                    case \"-\": return [a - b];\n                    case \"*\": return [a * b];\n                }\n            }),\n        },\n        io: [\n            [stringToNumbers(\"1 + 1\"), [2]],\n            [stringToNumbers(\"99 - 100\"), [-1]],\n            [stringToNumbers(\"10 * 4\"), [40]],\n        ],\n    },\n    {\n        title: \"Multi-Line Strings\",\n        io: [\n            [stringToNumbers(\".data 1\\n.data 2\\n.data 3\\n\"), stringsToNumbers([\".data 1\", \".data 2\", \".data 3\"])],\n        ],\n    },\n    {\n        title: \"Parse Data Directives\",\n        test: {\n            fixed: [[stringToNumbers(\".data 0\\n.data -128\\n.data 127\\n\")]],\n            createRandomTest: () => [stringToNumbers([1, 2, 3, 4].map(n => `.data ${Math.floor(Math.random() * 256) - 128}`).join(\"\\n\") + \"\\n\")],\n            getExpectedOutput: input => input.map(seq => String.fromCharCode(...seq.slice(0, seq.length - 1))\n                .replace(/[.]data/g, \"\")\n                .split(\"\\n\")\n                .map(s => s.trim())\n                .filter(s => s.length > 0)\n                .map(s => parseInt(s))),\n        },\n        io: [\n            [stringToNumbers(\".data 5\\n.data -7\\n.data 11\\n\"), [5, -7, 11]],\n        ],\n    },\n    {\n        title: \"Parse Subleq Instructions\",\n        test: {\n            fixed: [[stringToNumbers(\"subleq 7 253 255\\nsubleq 7 7 0\\n\")]],\n            createRandomTest: () => [stringToNumbers([1, 2, 3].map(n => `subleq ${[1, 2, 3].map(x => Math.floor(Math.random() * 256).toString()).join(\" \")}`).join(\"\\n\") + \"\\n\")],\n            getExpectedOutput: input => input.map(seq => String.fromCharCode(...seq.slice(0, seq.length - 1))\n                .replace(/subleq/g, \"\")\n                .split(/[ \\n]/)\n                .map(s => s.trim())\n                .filter(s => s.length > 0)\n                .map(s => Assembler.unsignedToSigned(parseInt(s)))),\n        },\n        io: [\n            [stringToNumbers(\"subleq 9 253 3\\nsubleq 254 9 6\\nsubleq 9 9 0\\n\"), [9, -3, 3, -2, 9, 6, 9, 9, 0]],\n        ],\n    },\n    {\n        title: \"Self-Hosting\",\n        test: {\n            fixed: [\n                [stringToNumbers(\n`subleq 18 17 3\nsubleq 17 18 6\nsubleq 254 17 9\nsubleq 16 15 255\nsubleq 18 18 0\n.data 1\n.data 5\n.data -1\n.data 0\n`\n                )],\n            ],\n            createRandomTest: () => [\n                (() => {\n                    const primes = [1, -3, 5, -7, 11, -13, 17, -19];\n                    const x = primes[Math.floor(Math.random() * primes.length)];\n                    const y = primes[Math.floor(Math.random() * primes.length)];\n                    const addresses = [16, 17];\n                    const a1 = addresses[Math.floor(Math.random() * addresses.length)];\n                    const a2 = addresses[Math.floor(Math.random() * addresses.length)];\n                    const a3 = addresses[Math.floor(Math.random() * addresses.length)];\n                    return stringToNumbers(\n`subleq 15 ${a1} ${((Math.random() * 2) >= 1) ? 9 : 3}\nsubleq 15 ${a2} ${((Math.random() * 2) >= 1) ? 9 : 6}\nsubleq 15 ${a3} 9\nsubleq 254 15 12\nsubleq 15 15 255\n.data ${x}\n.data ${y}\n.data 0\n`\n                    );\n                })(),\n                stringToNumbers(\n`subleq 18 17 3\nsubleq 17 18 6\nsubleq 254 17 9\nsubleq 16 15 255\nsubleq 18 18 0\n.data 1\n.data 5\n.data -${Math.floor(Math.random() * 3) + 1}\n.data 0\n`\n                    ),\n            ],\n            getExpectedOutput: input => input.map(seq => {\n                const input = String.fromCharCode(...seq.slice(0, seq.length - 1)).split(\"\\n\");\n                const result = [];\n                const emulator = new Emulator(Assembler.assemble(input), {\n                    writeOutput: n => {\n                        result.push(n);\n                    },\n                });\n\n                let step = 0;\n                while (step++ < 50 && emulator.isRunning()) {\n                    emulator.step();\n                }\n\n                return result;\n            }),\n        },\n        io: [\n            // subleq @b @a\n            // subleq @b @a\n            // subleq @OUT @b @HALT\n\n            // @a: .data -9\n            // @b: .data 0\n\n            [stringToNumbers(\"subleq 10 9 3\\nsubleq 10 9 6\\nsubleq 254 10 255\\n\\n.data -9\\n.data 0\\n\"), [-18]],\n        ],\n    },\n    {\n        title: \"Self-Hosting Part 2\",\n        test: {\n            // Derived from a minimal reflector:\n            //\n            // @read:\n            // subleq @l3+2 0 3\n            // subleq @OUT @l3+2 6\n            // @l3: subleq @read+1, @l4+2 0\n            // @l4: subleq @counter 0 @HALT ; Replace that second address to change increment\n            // subleq @l3+2 @l3+2 @read\n            // @counter: .data 15\n            fixed: [[\n                ...[0, 2, 5].map(address => stringToNumbers(`subleq 8 0 3\\nsubleq 254 8 6\\nsubleq 1 11 0\\nsubleq 15 ${address} 255\\nsubleq 8 8 0\\n.data 15\\n`)),\n\n                // Output every other byte\n                stringToNumbers(\"subleq 254 0 3\\nsubleq 1 12 6\\nsubleq 14 12 0\\nsubleq 15 15 255\\n.data -2\\n.data 1\\n.data -11\\n.data 0\\n\"),\n            ]],\n\n            createRandomTest: () => {\n                const result: number[][] = [];\n\n                for (let i = 0; i < 2; i++) {\n                    // Derived from code that patches reading one byte:\n                    //\n                    //@l1: subleq @l2 @a\n                    // @l2: subleq @l3+6 @b\n                    // @l3: subleq @OUT-4 @l1+1 ; This address changes\n                    // subleq @z @z @HALT\n                    // @a: .data 6\n                    // @b: .data -4\n                    // @z: .data 0\n\n                    const a = Math.floor(Math.random() * 5) + 1;\n                    const b = Math.floor(Math.random() * 5) + 1;\n                    result.push(stringToNumbers(\n`subleq 3 12 3\nsubleq ${6+a} 13 6\nsubleq ${254-b} ${Math.floor(Math.random() * 10)} 9\nsubleq 14 14 255\n.data ${a}\n.data -${b}\n.data 0\n`\n                    ));\n                }\n\n                // Derived from code that patches two instructions:\n                //\n                // @unmask:\n                // subleq @masked, @mask\n                // subleq @unmask, @n_1\n                // subleq @counter, @n_1, @unmask\n                // @masked: ; subleq @OUT, @o\n                // .data 53\n                // .data 70\n                // .data 67\n                // .data 70 ; subleq @o, @o, @HALT\n                // .data 70\n                // .data 54\n                // .data 21 ; @o: .data ...\n                // @mask: .data 55\n                // @counter: .data -6\n                // @n_1: .data -1\n                const mask = Math.floor(Math.random() * 30) + 20;\n                const output = Math.floor(Math.random() * 30) + 20;\n\n                result.push(stringToNumbers(\n`subleq 9 16 3\nsubleq 0 18 6\nsubleq 17 18 0\n.data ${Assembler.unsignedToSigned(254 + mask)}\n.data ${15 + mask}\n.data ${12 + mask}\n.data ${15 + mask}\n.data ${15 + mask}\n.data ${Assembler.unsignedToSigned(255 + mask)}\n.data ${output + mask}\n.data ${mask}\n.data -6\n.data -1\n`\n                ));\n\n                return result;\n            },\n\n            getExpectedOutput: input => input.map(seq => {\n                const input = String.fromCharCode(...seq.slice(0, seq.length - 1)).split(\"\\n\");\n                const result = [];\n                const emulator = new Emulator(Assembler.assemble(input), {\n                    writeOutput: n => {\n                        result.push(n);\n                    },\n                });\n\n                let step = 0;\n                while (step++ < 50 && emulator.isRunning()) {\n                    emulator.step();\n                }\n\n                return result;\n            }),\n        },\n        io: [\n            [stringToNumbers(\n                // ; Outputs its own first 12 bytes of code (negated)\n                //\n                // @start:\n                // subleq @OUT @start\n                // subleq @start+1 @n_1\n                // subleq @count @n_1 @start\n                // subleq @zero @zero @HALT\n                \n                // @n_1: .data -1\n                // .data 1\n                // @count: .data -11\n                // @zero: .data 0\n                \n                `subleq 254 0 3\n                subleq 1 12 6\n                subleq 14 12 0\n                subleq 15 15 255\n                .data -1\n                .data 1\n                .data -11\n                .data 0\n                `\n                ),\n                [2, -1, -3, -1, -12, -6, -14, -12, 0, -15, -15, 1],\n            ],\n        ],\n    },\n] as const;\n\nconst titleToPuzzleInternal: { [title: string]: Puzzle } = {};\nfor (const puzzle of puzzleFlatArray) {\n    titleToPuzzleInternal[puzzle.title] = puzzle;\n}\n\nexport const titleToPuzzle = titleToPuzzleInternal;\nexport const puzzleCount = puzzleFlatArray.length;\n", "sic1/server/contract/contract.ts": "// Shared definitions\nexport interface HistogramDataBucket {\n    bucketMax: number;\n    count: number;\n}\n\nexport type HistogramData = HistogramDataBucket[];\n\n// User profile\nexport const UserProfileRoute = \"/users/:userId\"; // GET, PUT\nexport const UserNameMaxLength = 50;\nexport interface UserProfileRequestParameters {\n    userId: string;\n}\n\nexport interface UserProfileGetResponse {\n    name: string;\n}\n\nexport interface UserProfilePutRequestBody {\n    name: string;\n}\n\n// User stats\nexport const UserStatsRoute = \"/stats/users\"; // GET\nexport interface UserStatsRequestQuery {\n    userId?: string;\n}\n\nexport interface UserStatsResponse {\n    solutionsByUser: HistogramData;\n    userSolvedCount: number;\n}\n\n// Leaderboard\nexport const LeaderboardRoute = \"/stats/top\"; // GET\nexport interface LeaderboardEntry {\n    name: string;\n    solved: number;\n}\n\nexport type LeaderboardResponse = LeaderboardEntry[];\n\n// Puzzle stats\nexport const PuzzleStatsRoute = \"/stats/test/:testName\"; // GET\nexport interface PuzzleStatsRequestParameters {\n    testName: string;\n}\n\nexport interface PuzzleStatsResponse {\n    cyclesExecutedBySolution: HistogramData;\n    memoryBytesAccessedBySolution: HistogramData;\n}\n\n// Solution upload\nexport const SolutionUploadRoute = \"/solutions/:testName\"; // POST\nexport interface SolutionUploadRequestParameters {\n    testName: string;\n}\n\nexport interface SolutionUploadRequestBody {\n    userId: string;\n    solutionCycles: number;\n    solutionBytes: number;\n    program: string;\n}\n", "BUILD.txt": "From sic1/client run npm ci --ignore-scripts, then node node_modules/parcel/lib/bin.js build --no-cache --public-url ./ --no-source-maps index.html. Node 22 used. Source file paths in this JSON are relative to the repository root. Original upstream at https://github.com/jaredkrinke/sic1/tree/bc0631a8e426b9d6e4f7d9b91e1791dffc324be3", "packaging.py": "from pathlib import Path\nimport json,shutil,subprocess,re\nr=Path('/private/tmp/skillsafe-20261026-0931');s=r/'source';d=r/'dist';commit=subprocess.check_output(['git','-C',str(s),'rev-parse','HEAD'],text=True).strip()\nmeta={'title':'SIC-1 · Single Instruction Computer','tags':['github-source','game'],'source':'https://github.com/jaredkrinke/sic1','source_commit':commit,'license':{'client':'LGPL-3.0-or-later','content':'CC-BY-SA-4.0'},'adaptation':'Local-only edition with no score uploads, telemetry, proprietary soundtrack, external popups or import/export. Cached historical charts; synthetic sound effects.'}\n(d/'metadata.json').write_text(json.dumps(meta,indent=2))\nfor f in ['LICENSE.md','LGPL-3.txt','AGPL-3.txt','CC-BY-SA-4.0.txt']:shutil.copy(s/f,d/('LICENSE-overview.txt' if f=='LICENSE.md' else f))\n# Complete editable first-party client/library/shared source and dependency manifests.\nsource={}\nfor base in [s/'lib',s/'sic1/client',s/'sic1/shared']:\n for p in base.rglob('*'):\n  if p.is_file() and not any(x in p.relative_to(base).parts for x in ['node_modules','dist','.parcel-cache','windows','electron','marketing','music']) and p.suffix in ['.ts','.tsx','.css','.html','.json','.md','.svg']:\n   source[str(p.relative_to(s))]=p.read_text()\nsource['sic1/server/contract/contract.ts']=(s/'sic1/server/contract/contract.ts').read_text()\nsource['BUILD.txt']='From sic1/client run npm ci --ignore-scripts, then node node_modules/parcel/lib/bin.js build --no-cache --public-url ./ --no-source-maps index.html. Node 22 used. Source file paths in this JSON are relative to the repository root. Original upstream at '+meta['source']+'/tree/'+commit\nsource['packaging.py']=(r/'package.py').read_text()\nsource['adaptations.json']=(r/'adaptations.json').read_text()\n(d/'source-files.json').write_text(json.dumps(source,ensure_ascii=False))\n(d/'CREDITS.txt').write_text('SIC-1 by Jared Krinke / Anti-Pattern Games. Source: '+meta['source']+'/tree/'+commit+'\\nClient code LGPL-3.0-or-later; story, puzzles and translations CC-BY-SA-4.0. Full notices accompany this release. Adapted first-party source: source-files.json. Third-party notices are also available in the in-game credits.\\n'+meta['adaptation']+'\\n')\n# Visible source access without browser downloads or new windows.\np=d/'index.html';h=p.read_text();h=re.sub(r'<footer class=\"edition\">.*?</footer>','',h);h=h.replace('<title>SIC-1</title>','<title>SIC-1 · Single Instruction Computer</title>');h=h.replace('<body>','<body><footer class=\"edition\">Local-only edition · historical benchmark charts · <a href=\"CREDITS.txt\">Credits</a> · <a href=\"source-files.json\">Adapted source</a></footer>');p.write_text(h)\np=d/'client.css';p.write_text(p.read_text().split('\\n.edition{')[0]+'\\n.edition{position:fixed;bottom:0;left:0;right:0;background:#071409;color:#9fc4a4;font:11px monospace;text-align:center;z-index:100;padding:4px}.edition a{color:inherit}body{padding-bottom:25px}\\n')\nprint(len(list(d.iterdir())),sum(p.stat().st_size for p in d.iterdir()))\n", "adaptations.json": "{\n  \"changes\": [\n    \"Removed Backtrace telemetry and tokens\",\n    \"Removed score/profile uploads; retained cached benchmark charts\",\n    \"Removed proprietary soundtrack references\",\n    \"Disabled import/export and external popups; routed manual to in-game reader\",\n    \"Removed unsupported OpenType fonts in favor of monospace fallback\"\n  ],\n  \"client_license\": \"LGPL-3.0-or-later\",\n  \"content_license\": \"CC-BY-SA-4.0\"\n}"}