{"ScriptPreparationCode":"var cursors = Array.from({\r\n length: 100\r\n}, (_, i) =\u003E ({\r\n type: \u0060${Math.random() \u003E 0.5 ? \u0022presentation\u0022 : \u0022whiteboard\u0022}.cursor\u0060,\r\n data: {\r\n id: btoa(\u0060gid://stoege/${Math.random() \u003E 0.5 ? \u0022Pupil\u0022 : \u0022Admin\u0022}/${i%2 * 1000}\u0060),\r\n aCoords: {\r\n tl: {\r\n x: Math.ceil(Math.random() * 1920),\r\n y: Math.ceil(Math.random() * 1080)\r\n }\r\n }\r\n }\r\n}));\r\n\r\n\r\nclass BiderectionalMap {\r\n constructor() {\r\n this.keyToValue = new Map();\r\n this.valueToKey = new Map();\r\n }\r\n set(key, value) {\r\n if (this.keyToValue.has(key)) {\r\n const oldValue = this.keyToValue.get(key);\r\n this.valueToKey.delete(oldValue);\r\n }\r\n if (this.valueToKey.has(value)) {\r\n const oldKey = this.valueToKey.get(value);\r\n this.keyToValue.delete(oldKey);\r\n }\r\n this.keyToValue.set(key, value);\r\n this.valueToKey.set(value, key);\r\n }\r\n get(input) {\r\n if (typeof input === \u0022number\u0022 \u0026\u0026 this.keyToValue.has(input)) {\r\n return this.keyToValue.get(input);\r\n } else if (typeof input === \u0022string\u0022 \u0026\u0026 this.valueToKey.has(input)) {\r\n return this.valueToKey.get(input);\r\n } else {\r\n return undefined;\r\n }\r\n }\r\n}\r\n\r\nvar eventTypes = new BiderectionalMap();\r\neventTypes.set(0, \u0022undefined\u0022);\r\neventTypes.set(1, \u0022presentation.cursor\u0022);\r\neventTypes.set(2, \u0022whiteboard.cursor\u0022);\r\n\r\nfunction rolesKV(key){\r\n\tswitch(key){\r\n case 1: return \u0022Admin\u0022;\r\n case 2: return \u0022Pupil\u0022;\r\n default: return \u0022undefined\u0022;\r\n }\r\n};\r\n\r\nfunction rolesVK(value){\r\n\tswitch(value){\r\n case \u0022Admin\u0022: return 1;\r\n case \u0022Pupil\u0022: return 2;\r\n default: return 0;\r\n }\r\n};\r\n\r\nconst _madIdExtractor = (decodedId) =\u003E {\r\n const splitedStr = decodedId.split(\u0027/\u0027);\r\n return [decodedId, splitedStr[3], splitedStr[4]];\r\n};\r\nconst get_m_madIdExtractor = () =\u003E {\r\n const results = new Map();\r\n return (decodedId) =\u003E {\r\n if (results.has(decodedId))\r\n return results.get(decodedId);\r\n results.set(decodedId, _madIdExtractor(decodedId));\r\n return results.get(decodedId);\r\n };\r\n};\r\n\r\n\r\nvar m_atob = get_m_atob();\r\nvar m_btoa = get_m_btoa();\r\nvar m_madIdExtractor = get_m_madIdExtractor();\r\n\r\nfunction crazyCompressor(cursor){\r\n /*\r\n Bytes Bits Max Value\r\n 1 8 256 \u2014 Role\r\n 2 16 65,536 \u2014 X and Y\r\n 4 32 4,294,967,296 \u2014 ID\r\n \r\n 1 \u002B 2 \u002B 2 \u002B 4 \u002B 1 = 10\r\n Role \u002B X \u002B Y \u002B ID \u002B Type\r\n */\r\n const MAX_UINT32_VALUE = 4294967296;\r\n const buffer = new ArrayBuffer(10);\r\n const fullView = new DataView(buffer, 0, 10);\r\n \r\n const getId = (encodedId) =\u003E {\r\n const extractedId = m_madIdExtractor(m_atob(encodedId));\r\n if (extractedId.length \u003C 3)\r\n throw new Error(\u0022Incorrect id format\u0022);\r\n const [_, role, rawId] = extractedId;\r\n const id = Number(rawId);\r\n if (id \u003E MAX_UINT32_VALUE - 1)\r\n throw new Error(\u0022ID is bigger than max uint32 value\u0022);\r\n return [role, id];\r\n };\r\n\r\n const getXY = (coords) =\u003E {\r\n const { x, y } = coords.tl;\r\n return [x, y];\r\n };\r\n const [role, id] = getId(cursor.data.id);\r\n const [x, y] = getXY(cursor.data.aCoords);\r\n\r\n fullView.setUint8(0, rolesVK(role));\r\n fullView.setUint32(1, id);\r\n fullView.setUint16(5, x);\r\n fullView.setUint16(7, y);\r\n fullView.setUint8(9, eventTypes.get(cursor.type));\r\n\r\n return buffer;\r\n};\r\nfunction crazyDecompressor(buffer){\r\n const fullView = new DataView(buffer, 0, 10);\r\n \r\n return {\r\n type: eventTypes.get(fullView.getUint8(0)),\r\n data: {\r\n id: m_btoa(\u0060gid://stoege/${rolesKV(fullView.getUint8(9))}/${fullView.getUint32(1)}\u0060),\r\n aCoords: {\r\n tl: {\r\n x: fullView.getUint16(5),\r\n y: fullView.getUint16(7)\r\n }\r\n }\r\n }\r\n };\r\n};\r\n\r\n\r\nfunction get_m_atob() {\r\n const results = new Map();\r\n return (encodedString) =\u003E {\r\n if (results.has(encodedString))\r\n return results.get(encodedString);\r\n results.set(encodedString, atob(encodedString));\r\n return results.get(encodedString);\r\n };\r\n}\r\n\r\nfunction get_m_btoa() {\r\n const results = new Map();\r\n return (decodedString) =\u003E {\r\n if (results.has(decodedString))\r\n return results.get(decodedString);\r\n results.set(decodedString, btoa(decodedString));\r\n return results.get(decodedString);\r\n };\r\n}\r\n\r\nfunction JSONCompressor(cursor) {\r\n return JSON.stringify(cursor);\r\n};\r\n\r\nfunction JSONDecompressor(cursorStr) {\r\n return JSON.parse(cursorStr);\r\n};","TestCases":[{"Name":"ArrayBuffer","Code":"const compressed = cursors.map(crazyCompressor);\r\nconst decompressed = compressed.map(crazyDecompressor);","IsDeferred":false},{"Name":"JSON","Code":"const compressed = cursors.map(JSONCompressor);\r\nconst decompressed = compressed.map(JSONDecompressor);","IsDeferred":false}]}