{"id":"microbit","nickname":"microbit","name":"makecode.microbit.org","title":"Microsoft MakeCode for micro:bit","description":"A Blocks / JavaScript code editor for the micro:bit powered by Microsoft MakeCode.","corepkg":"core","bundleddirs":["libs/core","libs/audio-samples","libs/radio","libs/devices","libs/bluetooth","libs/servo","libs/radio-broadcast","libs/microphone","libs/settings","libs/flashlog","libs/datalogger","libs/bitmap","libs/fonts","libs/color","libs/audio-recording"],"cloud":{"workspace":false,"packages":true,"sharing":true,"thumbnails":true,"publishing":true,"importing":true,"showBadges":false,"preferredPackages":["Microsoft/pxt-neopixel"],"githubPackages":true,"cloudProviders":{"github":{"id":"github","name":"GitHub","icon":"@cdnUrl@/blob/ea6ff545a246caa64074ba809bbc86fcb8589071/static/providers/github-mark.png","identity":false,"order":3},"microsoft":{"id":"microsoft","name":"Microsoft","icon":"@cdnUrl@/blob/5334aa7ca6864819631aad2993cc42f68d72a6e3/static/providers/microsoft-logo.svg","identity":true,"redirect":true,"order":1},"google":{"id":"google","name":"Google","icon":"@cdnUrl@/blob/c06982fbad6b6825d8efb8497291a533747480df/static/providers/google-logo.svg","identity":true,"redirect":true,"order":2},"clever":{"id":"clever","name":"Clever","icon":"@cdnUrl@/blob/3494ce63ad28b4528664f74f1fdac22242269125/static/providers/clever-logo.png","identity":true,"redirect":true,"order":3}}},"compile":{"isNative":false,"hasHex":true,"deployDrives":"(MICROBIT|MBED)","driveName":"MICROBIT","hexMimeType":"application/x-microbit-hex","openocdScript":"source [find interface/cmsis-dap.cfg]; source [find target/nrf51.cfg]","flashUsableEnd":242688,"flashEnd":242688,"flashCodeAlign":1024,"floatingPoint":true,"taggedInts":true,"utf8":false,"gc":true,"imageRefTag":9,"shimRenames":{"sendBufferAsm":"light::sendWS2812Buffer"},"patches":{"0.0.0 - 1.0.0":[{"type":"package","map":{"microbit":"core","microbit-bluetooth":"bluetooth","microbit-radio":"radio","microbit-devices":"devices","microbit-led":"","microbit-music":"","microbit-game":"","microbit-pins":"","microbit-serial":""}},{"type":"missingPackage","map":{"radio\\s*\\.":"radio","bluetooth\\s*\\.":"bluetooth","devices\\s*\\.":"devices"}},{"type":"api","map":{"bluetooth\\s*\\.\\s*uartRead\\s*\\((.*?)\\)":"bluetooth.uartReadUntil($1)","bluetooth\\s*\\.\\s*uartWrite\\s*\\((.*?)\\)":"bluetooth.uartWriteUntil($1)","input\\s*\\.\\s*calibrate\\s*\\(":"input.calibrateCompass(","radio\\s*\\.\\s*onDataPacketReceived\\(\\s*\\(\\{\\s*receivedNumber\\s*\\}\\)\\s*=>\\s*\\{":"radio.onReceivedNumber(function (receivedNumber) {","radio\\s*\\.\\s*onDataPacketReceived\\(\\s*\\(\\{\\s*receivedString: name, receivedNumber: value\\s*\\}\\)\\s*=>\\s*\\{":"radio.onReceivedValue(function (name, value) {","radio\\s*\\.\\s*onDataPacketReceived\\(\\s*\\(\\{\\s*receivedString\\s*\\}\\)\\s*=>\\s*\\{":"radio.onReceivedString(function (receivedString) {","Math\\s*\\.\\s*random\\s*\\(":"Math.randomRange(0, "}},{"type":"blockId","map":{"device_get_acceleration":"device_acceleration"}},{"type":"blockValue","map":{"device_print_message.message":"text"}}],"0.0.0 - 1.4.12":[{"type":"api","map":{"DisplayMode\\s*\\.\\s*BackAndWhite":"DisplayMode.BlackAndWhite"}}],"0.0.0 - 3.1.10":[{"type":"package","map":{"pxt-microbit-v2-extension":"microphone"}}],"0.0.0 - 3.0.18":[{"type":"missingPackage","map":{".*":"microphone"}}]},"hidSelectors":[{"usagePage":"0xFF00","usageId":"0x0001","vid":"0x0d28","pid":"0x0204"}],"webUSB":true,"useNewFunctions":true,"nativeType":"thumb","switches":{},"jsRefCounting":false,"noSourceInFlash":true,"compilerExtension":"/// <reference path=\"../node_modules/pxt-core/built/pxtcompiler.d.ts\"/>\n\n(function (ts) {\n    var pxtc;\n    (function (pxtc) {\n        var extension;\n        (function (extension) {\n            pxtc.compilerHooks.postBinary = (program, opts, res) => {\n                if (!opts.target.isNative)\n                    return;\n                const mbdal = res.outfiles[\"mbdal-binary.hex\"];\n                const mbcodal = res.outfiles[\"mbcodal-binary.hex\"];\n                if (!mbdal || !mbcodal)\n                    return;\n                let outp = \"\";\n                wrapHex(mbdal, 0x00, [0x99, 0x00, 0xc0, 0xde]);\n                wrapHex(mbcodal, 0x0D, [0x99, 0x03, 0xc0, 0xde], true);\n                outp += \":00000001FF\\n\";\n                res.outfiles[\"binary.hex\"] = outp;\n                function hex2str(bytes) {\n                    return ts.pxtc.hexfile.hexBytes([bytes.length - 3].concat(bytes)) + \"\\n\";\n                }\n                function paddingString(len) {\n                    let r = \"\";\n                    const len0 = len;\n                    while (len >= 44) {\n                        r += hex2str([0x00, 0x00, 0x0C,\n                            0x42, 0x42, 0x42, 0x42,\n                            0x42, 0x42, 0x42, 0x42,\n                            0x42, 0x42, 0x42, 0x42,\n                            0x42, 0x42, 0x42, 0x42]);\n                        len -= 44;\n                    }\n                    if (len >= 12) {\n                        const numBytes = (len - 11) >> 1;\n                        const bytes = [0x00, 0x00, 0x0C];\n                        for (let i = 0; i < numBytes; ++i)\n                            bytes.push(0x42);\n                        const add = hex2str(bytes);\n                        r += add;\n                        len -= add.length;\n                    }\n                    while (len--)\n                        r += \"\\n\";\n                    pxtc.U.assert(r.length == len0);\n                    return r;\n                }\n                function addBlock(blk) {\n                    const leftoff = blk.length & 511;\n                    outp += blk + paddingString(512 - leftoff);\n                }\n                function wrapHex(inpHex, dataType, deviceType, keepSrc = false) {\n                    let blk = hex2str([0x00, 0x00, 0x04, 0x00, 0x00])\n                        + hex2str([0x00, 0x00, 0x0A].concat(deviceType));\n                    let upperAddr = 0;\n                    const lines = inpHex.split(/\\r?\\n/);\n                    for (let i = 0; i < lines.length; ++i) {\n                        const line = lines[i];\n                        if (!line)\n                            continue;\n                        const parsed = ts.pxtc.hexfile.parseHexRecord(line);\n                        switch (parsed.type) {\n                            case 0x00:\n                                const parsed2 = parsed.len <= 16 && lines[i + 1] ?\n                                    ts.pxtc.hexfile.parseHexRecord(lines[i + 1])\n                                    : null;\n                                // if this and next line can fit in 32 bytes, concat them\n                                if (parsed2 && parsed2.type == 0x00 &&\n                                    parsed2.addr == parsed.addr + parsed.len &&\n                                    parsed.len + parsed2.len <= 32) {\n                                    parsed.data = parsed.data.concat(parsed2.data);\n                                    parsed.len += parsed2.len;\n                                    i++;\n                                }\n                                addData([parsed.addr >> 8, parsed.addr & 0xff, dataType]\n                                    .concat(parsed.data));\n                                break;\n                            case 0x01:\n                                flush();\n                                if (keepSrc)\n                                    break;\n                                else\n                                    return;\n                            case 0x04:\n                                const newUpper = ((parsed.data[0] << 8) | parsed.data[1]) << 16;\n                                if (upperAddr != newUpper) {\n                                    upperAddr = newUpper;\n                                    addData([0, 0, 0x04, parsed.data[0], parsed.data[1]]);\n                                }\n                                break;\n                            case 0x03:\n                            case 0x05:\n                                // ignore\n                                break;\n                            case 0x0E:\n                                // src record\n                                addData([parsed.addr >> 8, parsed.addr & 0xff, 0x0E]\n                                    .concat(parsed.data));\n                                break;\n                            default:\n                                pxtc.U.oops(`unknown hex record type: ${line}`);\n                                break;\n                        }\n                    }\n                    flush();\n                    function addData(bytes) {\n                        const newData = hex2str(bytes);\n                        blk += newData;\n                    }\n                    function flush() {\n                        if (blk)\n                            addBlock(blk);\n                        blk = \"\";\n                    }\n                }\n            };\n        })(extension = pxtc.extension || (pxtc.extension = {}));\n    })(pxtc = ts.pxtc || (ts.pxtc = {}));\n})(ts || (ts = {}));\n"},"compileService":{"yottaTarget":"bbc-microbit-classic-gcc@https://github.com/lancaster-university/yotta-target-bbc-microbit-classic-gcc","yottaCorePackage":"microbit","githubCorePackage":"lancaster-university/microbit","gittag":"v2.2.0-rc6","serviceId":"microbit","dockerImage":"pext/yotta:gcc5","yottaBinary":"pxt-microbit-app-combined.hex"},"multiVariants":["mbdal","mbcodal"],"alwaysMultiVariant":true,"variants":{"mbdal":{"compile":{},"compileService":{}},"mbcodal":{"compile":{"flashCodeAlign":4096,"flashUsableEnd":471040,"flashEnd":524288},"compileService":{"buildEngine":"codal","codalTarget":{"name":"codal-microbit-v2","url":"https://github.com/lancaster-university/codal-microbit-v2","branch":"v0.3.0","type":"git"},"codalBinary":"MICROBIT","githubCorePackage":"lancaster-university/microbit-v2-samples","gittag":"v0.2.13","serviceId":"mbcodal2","dockerImage":"pext/yotta:latest","yottaConfigCompatibility":true}}},"runtime":{"mathBlocks":true,"loopsBlocks":true,"logicBlocks":true,"variablesBlocks":true,"textBlocks":true,"listsBlocks":true,"functionBlocks":true,"breakBlock":true,"continueBlock":true,"functionsOptions":{"useNewFunctions":true,"extraFunctionEditorTypes":[{"typeName":"game.LedSprite","label":"LedSprite","icon":"send","defaultName":"sprite"},{"typeName":"Image","label":"Image","icon":"image outline","defaultName":"image"}]},"onStartColor":"#1E90FF","onStartNamespace":"basic","onStartWeight":54},"simulator":{"autoRun":true,"streams":false,"aspectRatio":1.22,"parts":true,"partsAspectRatio":0.69,"messageSimulators":{"jacdac":{"url":"https://microsoft.github.io/jacdac-docs/tools/makecode-sim?webusb=0&parentOrigin=$PARENT_ORIGIN$","localHostUrl":"http://localhost:8000/tools/makecode-sim?webusb=0&parentOrigin=$PARENT_ORIGIN$","aspectRatio":1.22,"permanent":true},"robot":{"url":"https://microsoft.github.io/microbit-robot/?parentOrigin=$PARENT_ORIGIN$","localHostUrl":"http://localhost:3000/microbit-robot/?parentOrigin=$PARENT_ORIGIN$","aspectRatio":1.22,"permanent":true}},"testSimulatorExtensions":{},"boardDefinition":{"visual":"microbit","gpioPinBlocks":[["P0"],["P1"],["P2"],["P3"],["P4","P5","P6","P7"],["P8","P9","P10","P11","P12"],["P16"]],"gpioPinMap":{"P0":"P0","P1":"P1","P2":"P2","P3":"P3","P4":"P4","P5":"P5","P6":"P6","P7":"P7","P8":"P8","P9":"P9","P10":"P10","P11":"P11","P12":"P12","P13":"P13","P14":"P14","P15":"P15","P16":"P16","P19":"P19","P20":"P20"},"spiPins":{"MOSI":"P15","MISO":"P14","SCK":"P13"},"i2cPins":{"SDA":"P20","SCL":"P19"},"analogInPins":["P0","P1","P2","P3","P10"],"groundPins":["GND"],"threeVoltPins":["+3v3"],"attachPowerOnRight":true,"onboardComponents":["accelerometer","buttonpair","ledmatrix","speaker","bluetooth","thermometer","compass","builtinspeaker","microphone","logotouch","flashlog","v2"],"pinStyles":{"P0":"croc","P1":"croc","P2":"croc","GND":"croc","+3v3":"croc"},"marginWhenBreadboarding":[0,0,80,0]}},"serial":{"nameFilter":"^(mbed Serial Port|DAPLink CMSIS-DAP)","log":true,"useEditor":true,"editorTheme":{"graphBackground":"#d9d9d9","lineColors":["#6633cc","#2C7485","#3454D1","#EF767A","#F46197","#107C10"]},"vendorId":"0x0d28","productId":"0x0204","rawHID":true},"appTheme":{"accentColor":"#5C005C","logoUrl":"https://microbit.org/","logo":"@cdnUrl@/blob/d955ce94fc3f7d2c6573300c71a56dc1d92c9bf0/static/logo.portrait.white.svg","docsLogo":"@cdnUrl@/blob/3403510141da69da71b1fbb1024619a3ba88ac29/static/logo.square.white.svg","portraitLogo":"@cdnUrl@/blob/3403510141da69da71b1fbb1024619a3ba88ac29/static/logo.square.white.svg","footerLogo":"@cdnUrl@/blob/642175ae61e6822c948990e15570e590d2e0ecf1/static/logo.portrait.black.svg","cardLogo":"@cdnUrl@/blob/4de54063603c8d16531078818a83f7c29a3588fa/static/icons/apple-touch-icon.png","appLogo":"@cdnUrl@/blob/4de54063603c8d16531078818a83f7c29a3588fa/static/icons/apple-touch-icon.png","organization":"Microsoft MakeCode","organizationUrl":"https://makecode.com/","organizationLogo":"@cdnUrl@/blob/106597ae039a275897661651b96856220c9b0fad/static/Microsoft_logo_rgb_W-white_D-square.png","organizationWideLogo":"@cdnUrl@/blob/d6139e3d0af51f02aa5f8765ecb0985acbd98551/static/Microsoft_logo_rgb_W-white_D.png","homeScreenHero":{"imageUrl":"@cdnUrl@/blob/27137e90637eecca4fffc33c1d9b1ab0d20612d5/static/herogallery/hero-banner.png","name":"Flashing Heart","url":"/projects/flashing-heart","description":"New? Start here!","cardType":"tutorial"},"homeScreenHeroGallery":"/hero-banner","homeUrl":"https://makecode.microbit.org/","embedUrl":"https://makecode.microbit.org/","shareUrl":"https://makecode.microbit.org/","privacyUrl":"https://makecode.com/privacy","termsOfUseUrl":"https://makecode.com/termsofuse","githubUrl":"https://github.com/Microsoft/pxt-microbit","boardName":"micro:bit","boardNickname":"micro:bit","driveDisplayName":"MICROBIT","appStoreID":"1092687276","mobileSafariDownloadProtocol":"microbithex://?data","crowdinProject":"makecode","extendEditor":true,"extendFieldEditors":true,"enableTrace":true,"ignoreDocsErrors":false,"errorList":true,"workspaceSearch":true,"allowPackageExtensions":true,"addNewTypeScriptFile":true,"enabledFeatures":{"blocksErrorList":{},"aiErrorHelp":{"includeRegions":["US"]}},"experiments":["accessibleBlocks","debugExtensionCode","bluetoothUartConsole","bluetoothPartialFlashing","identity"],"supportedExperiences":["code-eval"],"bluetoothUartFilters":[{"namePrefix":"BBC micro:bit"}],"docMenu":[{"name":"Support","path":"https://support.microbit.org/"},{"name":"Reference","path":"/reference"},{"name":"Hardware","path":"/device"},{"name":"Buy","path":"https://microbit.org/resellers"}],"hasReferenceDocs":true,"usbDocs":"/device/usb","hideHomeDetailsVideo":true,"invertedMenu":true,"coloredToolbox":true,"monacoToolbox":true,"hasAudio":true,"socialOptions":{"orgTwitterHandle":"MSMakeCode","hashtags":"MakeCode","discourse":"https://forum.makecode.com/","discourseCategory":"micro:bit"},"blocklyOptions":{"grid":{"spacing":45,"length":7,"colour":"rgba(189, 195, 199, 0.30)","snap":false}},"blockColors":{"logic":"#00A4A6","loops":"#00AA00","math":"#9400D3","variables":"#DC143C","text":"#B8860B","advanced":"#00272B","functions":"#3455DB","arrays":"#E65722"},"defaultColorTheme":"microbit-light","highContrastColorTheme":"pxt-high-contrast","blocksCollapsing":true,"highContrast":true,"greenScreen":true,"print":true,"selectLanguage":true,"availableLocales":["en","ar","bg","ca","cs","cy","da","de","el","es-ES","fi","fr","gn","he","hu","is","it","ja","ko","nl","nb","nn-NO","pl","pt-BR","pt-PT","ru","si-LK","sk","sr","sv-SE","tr","uk","vi","zh-CN","zh-TW"],"monacoColors":{"editor.background":"#ecf0f1"},"monacoFieldEditors":["soundeffect-editor","image-editor"],"browserDbPrefixes":{"1":"v1","2":"v2","3":"v3","4":"v4","5":"v5","6":"v6","7":"v7"},"editorVersionPaths":{"0":"v0"},"showProjectSettings":true,"scriptManager":true,"debugger":true,"simGifTransparent":"rgba(0,0,0,0)","simGifMaxFrames":44,"simScreenshot":true,"simScreenshotMaxUriLength":300000,"simGif":true,"simGifWidth":240,"qrCode":true,"importExtensionFiles":true,"nameProjectFirst":true,"githubEditor":true,"chooseLanguageRestrictionOnNewProject":true,"openProjectNewTab":true,"python":true,"appFlashingTroubleshoot":"/device/windows-app/troubleshoot","immersiveReader":true,"tutorialCodeValidation":true,"downloadDialogTheme":{"webUSBDeviceNames":["BBC micro:bit CMSIS-DAP","DAPLink CMSIS-DAP"],"minimumFirmwareVersion":"0249","deviceIcon":"xicon microbit","deviceSuccessIcon":"xicon microbit-check","downloadMenuHelpURL":"/device/usb","downloadHelpURL":"/device/usb","troubleshootWebUSBHelpURL":"/device/usb/webusb/troubleshoot","incompatibleHardwareHelpURL":"/device/v2","dragFileImage":"@cdnUrl@/blob/4ac41b592008946443c877dfb6704aef96e9fed3/static/download/transfer.png","connectDeviceImage":"@cdnUrl@/blob/531d5c31f85c523c9a72d2da24e0508502e1e965/static/download/connect-microbit.gif","disconnectDeviceImage":"@cdnUrl@/blob/5052d4e01613fa58ba6cf77c6155c07cd56e52cf/static/download/full-reset.gif","selectDeviceImage":"@cdnUrl@/blob/8b42ea0666da4b22eb9e6d5441b2d7956cdec9e6/static/download/selecting-microbit.gif","connectionSuccessImage":"@cdnUrl@/blob/87ce2f19a063cfe3bed227537b92c5ac0e098212/static/download/successfully-paired.png","incompatibleHardwareImage":"@cdnUrl@/blob/1ae40aeeaccad7ecef3eb8905c37eb89635fee09/static/download/incompatible.png","usbDeviceForgottenImage":"@cdnUrl@/blob/dd759c7e39f810c4304c711547c77232fd96b250/static/download/device-forgotten.gif","browserUnpairImage":"@cdnUrl@/blob/ab08b2f484a3c9779b3ee9757968976a12599d3a/static/download/browser-unpair-image.gif"},"winAppDeprImage":"@cdnUrl@/blob/418c9c299ed5dce035443b8b2094fec39f7fb5b1/static/winapp.PNG","showWinAppDeprBanner":false,"tours":{"editor":"/tours/editor-tour"},"tutorialSimSidebarLayout":true,"preferWebUSBDownload":true,"hideReplaceMyCode":true,"matchWebUSBDeviceInSim":true,"condenseProfile":true,"cloudProfileIcon":"@cdnUrl@/blob/0333f81cb5145591d6833c44eba89af5764d8321/static/profile/microbit-cloud.png","timeMachine":true,"timeMachineDiffInterval":600000,"timeMachineSnapshotInterval":1800000,"TOC":[{"name":"About","path":"/about","subitems":[]},{"name":"FAQ","path":"/faq","subitems":[]},{"name":"Projects","path":"/projects","subitems":[]},{"name":"GitHub","path":"/github","subitems":[]},{"name":"Support","path":"https://support.microbit.org/","subitems":[]},{"name":"Courses","path":"/courses","subitems":[{"name":"CS Intro","path":"/courses/csintro","subitems":[{"name":"About","path":"/courses/csintro/about","subitems":[]},{"name":"Introduction","path":"/courses/csintro/introduction","subitems":[]},{"name":"References","path":"/courses/csintro/references","subitems":[]},{"name":"Acknowledgements","path":"/courses/csintro/acknowledgements","subitems":[]},{"name":"Making","path":"/courses/csintro/making","subitems":[{"name":"Introduction","path":"/courses/csintro/making/introduction","subitems":[]},{"name":"Unplugged","path":"/courses/csintro/making/unplugged","subitems":[]},{"name":"Walkthrough","path":"/courses/csintro/making/activity","subitems":[]},{"name":"Project","path":"/courses/csintro/making/project","subitems":[]},{"name":"Standards","path":"/courses/csintro/making/standards","subitems":[]}]},{"name":"Algorithms","path":"/courses/csintro/algorithms","subitems":[{"name":"Overview","path":"/courses/csintro/algorithms/overview","subitems":[]},{"name":"Unplugged","path":"/courses/csintro/algorithms/unplugged","subitems":[]},{"name":"Activity","path":"/courses/csintro/algorithms/activity","subitems":[]},{"name":"Project","path":"/courses/csintro/algorithms/project","subitems":[]},{"name":"Standards","path":"/courses/csintro/algorithms/standards","subitems":[]}]},{"name":"Variables","path":"/courses/csintro/variables","subitems":[{"name":"Overview","path":"/courses/csintro/variables/overview","subitems":[]},{"name":"Unplugged","path":"/courses/csintro/variables/unplugged","subitems":[]},{"name":"Activity","path":"/courses/csintro/variables/activity","subitems":[]},{"name":"Project","path":"/courses/csintro/variables/project","subitems":[]},{"name":"Standards","path":"/courses/csintro/variables/standards","subitems":[]}]},{"name":"Conditionals","path":"/courses/csintro/conditionals","subitems":[{"name":"Overview","path":"/courses/csintro/conditionals/overview","subitems":[]},{"name":"Unplugged","path":"/courses/csintro/conditionals/unplugged","subitems":[]},{"name":"Activity","path":"/courses/csintro/conditionals/activity","subitems":[]},{"name":"Project","path":"/courses/csintro/conditionals/project","subitems":[]},{"name":"Standards","path":"/courses/csintro/conditionals/standards","subitems":[]}]},{"name":"Iteration","path":"/courses/csintro/iteration","subitems":[{"name":"Overview","path":"/courses/csintro/iteration/overview","subitems":[]},{"name":"Unplugged","path":"/courses/csintro/iteration/unplugged","subitems":[]},{"name":"Activity","path":"/courses/csintro/iteration/activity","subitems":[]},{"name":"Project","path":"/courses/csintro/iteration/project","subitems":[]},{"name":"Standards","path":"/courses/csintro/iteration/standards","subitems":[]}]},{"name":"Mini-project","path":"/courses/csintro/miniproject","subitems":[{"name":"Review","path":"/courses/csintro/miniproject/review","subitems":[]},{"name":"Activity","path":"/courses/csintro/miniproject/activity","subitems":[]},{"name":"Project","path":"/courses/csintro/miniproject/project","subitems":[]},{"name":"Standards","path":"/courses/csintro/miniproject/standards","subitems":[]}]},{"name":"Coordinates","path":"/courses/csintro/coordinates","subitems":[{"name":"Overview","path":"/courses/csintro/coordinates/overview","subitems":[]},{"name":"Unplugged","path":"/courses/csintro/coordinates/unplugged","subitems":[]},{"name":"Activity","path":"/courses/csintro/coordinates/activity","subitems":[]},{"name":"Project","path":"/courses/csintro/coordinates/project","subitems":[]},{"name":"Standards","path":"/courses/csintro/coordinates/standards","subitems":[]}]},{"name":"Booleans","path":"/courses/csintro/booleans","subitems":[{"name":"Overview","path":"/courses/csintro/booleans/overview","subitems":[]},{"name":"Unplugged","path":"/courses/csintro/booleans/unplugged","subitems":[]},{"name":"Activity","path":"/courses/csintro/booleans/activity","subitems":[]},{"name":"Project","path":"/courses/csintro/booleans/project","subitems":[]},{"name":"Standards","path":"/courses/csintro/booleans/standards","subitems":[]}]},{"name":"Binary","path":"/courses/csintro/binary","subitems":[{"name":"Overview","path":"/courses/csintro/binary/overview","subitems":[]},{"name":"Unplugged","path":"/courses/csintro/binary/unplugged","subitems":[]},{"name":"Activity","path":"/courses/csintro/binary/activity","subitems":[]},{"name":"Project","path":"/courses/csintro/binary/project","subitems":[]},{"name":"Standards","path":"/courses/csintro/binary/standards","subitems":[]}]},{"name":"Radio","path":"/courses/csintro/radio","subitems":[{"name":"Overview","path":"/courses/csintro/radio/overview","subitems":[]},{"name":"Unplugged","path":"/courses/csintro/radio/unplugged","subitems":[]},{"name":"Activity","path":"/courses/csintro/radio/activity","subitems":[]},{"name":"Project","path":"/courses/csintro/radio/project","subitems":[]},{"name":"Standards","path":"/courses/csintro/radio/standards","subitems":[]}]},{"name":"Arrays","path":"/courses/csintro/arrays","subitems":[{"name":"Overview","path":"/courses/csintro/arrays/overview","subitems":[]},{"name":"Unplugged","path":"/courses/csintro/arrays/unplugged","subitems":[]},{"name":"Activity","path":"/courses/csintro/arrays/activity","subitems":[]},{"name":"Project","path":"/courses/csintro/arrays/project","subitems":[]},{"name":"Standards","path":"/courses/csintro/arrays/standards","subitems":[]}]},{"name":"Final Project","path":"/courses/csintro/finalproject","subitems":[{"name":"Review","path":"/courses/csintro/finalproject/review","subitems":[]},{"name":"Project","path":"/courses/csintro/finalproject/project","subitems":[]},{"name":"Examples","path":"/courses/csintro/finalproject/examples","subitems":[]},{"name":"Standards","path":"/courses/csintro/finalproject/standards","subitems":[]}]}]},{"name":"Blocks to JavaScript","path":"/courses/blocks-to-javascript","subitems":[{"name":"Hello JavaScript","path":"/courses/blocks-to-javascript/hello-javascript","subitems":[]},{"name":"Starter Blocks","path":"/courses/blocks-to-javascript/starter-blocks","subitems":[]},{"name":"Writing Code","path":"/courses/blocks-to-javascript/writing-code","subitems":[]},{"name":"Conditional Loops","path":"/courses/blocks-to-javascript/conditional-loops","subitems":[]},{"name":"Writing Functions","path":"/courses/blocks-to-javascript/writing-functions","subitems":[]}]},{"name":"Science experiments","path":"/courses/ucp-science","subitems":[{"name":"Data collection","path":"/courses/ucp-science/data-collection","subitems":[{"name":"Overview","path":"/courses/ucp-science/data-collection/overview","subitems":[]},{"name":"Setup and procedure","path":"/courses/ucp-science/data-collection/setup-procedure","subitems":[]},{"name":"Resources","path":"/courses/ucp-science/data-collection/resources","subitems":[]}]},{"name":"Population Traits","path":"/courses/ucp-science/population","subitems":[{"name":"Overview","path":"/courses/ucp-science/population/overview","subitems":[]},{"name":"Setup and procedure","path":"/courses/ucp-science/population/setup-procedure","subitems":[]},{"name":"Resources","path":"/courses/ucp-science/population/resources","subitems":[]}]},{"name":"Temperature","path":"/courses/ucp-science/temperature","subitems":[{"name":"Overview","path":"/courses/ucp-science/temperature/overview","subitems":[]},{"name":"Setup and procedure","path":"/courses/ucp-science/temperature/setup-procedure","subitems":[]},{"name":"Resources","path":"/courses/ucp-science/temperature/resources","subitems":[]}]},{"name":"Soil Moisture","path":"/courses/ucp-science/soil-moisture","subitems":[{"name":"Overview","path":"/courses/ucp-science/soil-moisture/overview","subitems":[]},{"name":"Setup and procedure","path":"/courses/ucp-science/soil-moisture/setup-procedure","subitems":[]},{"name":"Resources","path":"/courses/ucp-science/soil-moisture/resources","subitems":[]}]},{"name":"Gravity, Motion and Waves","path":"/courses/ucp-science/gravity","subitems":[{"name":"Overview","path":"/courses/ucp-science/gravity/overview","subitems":[]},{"name":"Setup and procedure","path":"/courses/ucp-science/gravity/setup-procedure","subitems":[]},{"name":"Resources","path":"/courses/ucp-science/gravity/resources","subitems":[]}]},{"name":"Body Electrical and Waves","path":"/courses/ucp-science/body-electrical","subitems":[{"name":"Overview","path":"/courses/ucp-science/body-electrical/overview","subitems":[]},{"name":"Setup and procedure","path":"/courses/ucp-science/body-electrical/setup-procedure","subitems":[]},{"name":"Resources","path":"/courses/ucp-science/body-electrical/resources","subitems":[]}]},{"name":"Electricity","path":"/courses/ucp-science/electricity","subitems":[{"name":"Overview","path":"/courses/ucp-science/electricity/overview","subitems":[]},{"name":"Setup and procedure","path":"/courses/ucp-science/electricity/setup-procedure","subitems":[]},{"name":"Resources","path":"/courses/ucp-science/electricity/resources","subitems":[]}]},{"name":"Rocket Acceleration","path":"/courses/ucp-science/rocket-acceleration","subitems":[{"name":"Overview","path":"/courses/ucp-science/rocket-acceleration/overview","subitems":[]},{"name":"Build","path":"/courses/ucp-science/rocket-acceleration/build","subitems":[]},{"name":"Setup and procedure","path":"/courses/ucp-science/rocket-acceleration/setup-procedure","subitems":[]},{"name":"Resources","path":"/courses/ucp-science/rocket-acceleration/resources","subitems":[]}]}]},{"name":"Logic Lab","path":"/courses/logic-lab","subitems":[{"name":"Logic and Expressions","path":"/courses/logic-lab/expressions","subitems":[]},{"name":"Boolean Elements","path":"/courses/logic-lab/elements","subitems":[]},{"name":"Logic Explorer","path":"/courses/logic-lab/explorer","subitems":[]},{"name":"Logic Gates","path":"/courses/logic-lab/logic-gates","subitems":[]},{"name":"Programmable Logic","path":"/courses/logic-lab/programmable","subitems":[]}]}]},{"name":"Reference","path":"/reference","subitems":[{"name":"Basic","path":"/reference/basic","subitems":[{"name":"show number","path":"/reference/basic/show-number","subitems":[]},{"name":"show icon","path":"/reference/basic/show-icon","subitems":[]},{"name":"show leds","path":"/reference/basic/show-leds","subitems":[]},{"name":"show string","path":"/reference/basic/show-string","subitems":[]},{"name":"clear screen","path":"/reference/basic/clear-screen","subitems":[]},{"name":"forever","path":"/reference/basic/forever","subitems":[]},{"name":"pause","path":"/reference/basic/pause","subitems":[]},{"name":"show arrow","path":"/reference/basic/show-arrow","subitems":[]}]},{"name":"Input","path":"/reference/input","subitems":[{"name":"on button pressed","path":"/reference/input/on-button-pressed","subitems":[]},{"name":"on gesture","path":"/reference/input/on-gesture","subitems":[]},{"name":"on pin pressed","path":"/reference/input/on-pin-pressed","subitems":[]},{"name":"button is pressed","path":"/reference/input/button-is-pressed","subitems":[]},{"name":"compass heading","path":"/reference/input/compass-heading","subitems":[]},{"name":"pin is pressed","path":"/reference/input/pin-is-pressed","subitems":[]},{"name":"temperature","path":"/reference/input/temperature","subitems":[]},{"name":"acceleration","path":"/reference/input/acceleration","subitems":[]},{"name":"light level","path":"/reference/input/light-level","subitems":[]},{"name":"rotation","path":"/reference/input/rotation","subitems":[]},{"name":"magnetic force","path":"/reference/input/magnetic-force","subitems":[]},{"name":"running time","path":"/reference/input/running-time","subitems":[]},{"name":"set accelerometer range","path":"/reference/input/set-accelerometer-range","subitems":[]}]},{"name":"Music","path":"/reference/music","subitems":[{"name":"play tone","path":"/reference/music/play-tone","subitems":[]},{"name":"ring tone","path":"/reference/music/ring-tone","subitems":[]},{"name":"rest","path":"/reference/music/rest","subitems":[]},{"name":"beat","path":"/reference/music/beat","subitems":[]},{"name":"tempo","path":"/reference/music/tempo","subitems":[]},{"name":"change tempo by","path":"/reference/music/change-tempo-by","subitems":[]},{"name":"set tempo","path":"/reference/music/set-tempo","subitems":[]}]},{"name":"Led","path":"/reference/led","subitems":[{"name":"plot","path":"/reference/led/plot","subitems":[]},{"name":"unplot","path":"/reference/led/unplot","subitems":[]},{"name":"point","path":"/reference/led/point","subitems":[]},{"name":"toggle","path":"/reference/led/toggle","subitems":[]},{"name":"brightness","path":"/reference/led/brightness","subitems":[]},{"name":"set brightness","path":"/reference/led/set-brightness","subitems":[]},{"name":"stop animation","path":"/reference/led/stop-animation","subitems":[]},{"name":"plot bar graph","path":"/reference/led/plot-bar-graph","subitems":[]},{"name":"enable","path":"/reference/led/enable","subitems":[]}]},{"name":"Radio","path":"/reference/radio","subitems":[{"name":"send number","path":"/reference/radio/send-number","subitems":[]},{"name":"send value","path":"/reference/radio/send-value","subitems":[]},{"name":"send string","path":"/reference/radio/send-string","subitems":[]},{"name":"on received number","path":"/reference/radio/on-received-number","subitems":[]},{"name":"on received string","path":"/reference/radio/on-received-string","subitems":[]},{"name":"on received buffer","path":"/reference/radio/on-received-buffer","subitems":[]},{"name":"received packet","path":"/reference/radio/received-packet","subitems":[]},{"name":"set group","path":"/reference/radio/set-group","subitems":[]},{"name":"set transmit power","path":"/reference/radio/set-transmit-power","subitems":[]},{"name":"set transmit serial number","path":"/reference/radio/set-transmit-serial-number","subitems":[]},{"name":"on data packet received","path":"/reference/radio/on-data-packet-received","subitems":[]},{"name":"write received packet to serial","path":"/reference/radio/write-received-packet-to-serial","subitems":[]}]},{"name":"Game","path":"/reference/game","subitems":[{"name":"create sprite","path":"/reference/game/create-sprite","subitems":[]},{"name":"delete","path":"/reference/game/delete","subitems":[]},{"name":"move","path":"/reference/game/move","subitems":[]},{"name":"turn","path":"/reference/game/turn","subitems":[]},{"name":"if on edge bounce","path":"/reference/game/if-on-edge-bounce","subitems":[]},{"name":"get","path":"/reference/game/get","subitems":[]},{"name":"set","path":"/reference/game/set","subitems":[]},{"name":"change","path":"/reference/game/change","subitems":[]},{"name":"is touching","path":"/reference/game/is-touching","subitems":[]},{"name":"is touching edge","path":"/reference/game/is-touching-edge","subitems":[]},{"name":"add score","path":"/reference/game/add-score","subitems":[]},{"name":"score","path":"/reference/game/score","subitems":[]},{"name":"set score","path":"/reference/game/set-score","subitems":[]},{"name":"set life","path":"/reference/game/set-life","subitems":[]},{"name":"add life","path":"/reference/game/add-life","subitems":[]},{"name":"remove life","path":"/reference/game/remove-life","subitems":[]},{"name":"start countdown","path":"/reference/game/start-countdown","subitems":[]},{"name":"game over","path":"/reference/game/game-over","subitems":[]},{"name":"pause","path":"/reference/game/pause","subitems":[]},{"name":"resume","path":"/reference/game/resume","subitems":[]}]},{"name":"Images","path":"/reference/images","subitems":[{"name":"create image","path":"/reference/images/create-image","subitems":[]},{"name":"create big image","path":"/reference/images/create-big-image","subitems":[]},{"name":"show image","path":"/reference/images/show-image","subitems":[]},{"name":"scroll image","path":"/reference/images/scroll-image","subitems":[]},{"name":"arrow image","path":"/reference/images/arrow-image","subitems":[]},{"name":"icon image","path":"/reference/images/icon-image","subitems":[]},{"name":"arrow number","path":"/reference/images/arrow-number","subitems":[]}]},{"name":"Pins","path":"/reference/pins","subitems":[{"name":"digital read pin","path":"/reference/pins/digital-read-pin","subitems":[]},{"name":"digital write pin","path":"/reference/pins/digital-write-pin","subitems":[]},{"name":"analog read pin","path":"/reference/pins/analog-read-pin","subitems":[]},{"name":"analog write pin","path":"/reference/pins/analog-write-pin","subitems":[]},{"name":"analog set period","path":"/reference/pins/analog-set-period","subitems":[]},{"name":"map","path":"/reference/pins/map","subitems":[]},{"name":"on pulsed","path":"/reference/pins/on-pulsed","subitems":[]},{"name":"pulse duration","path":"/reference/pins/pulse-duration","subitems":[]},{"name":"pulse in","path":"/reference/pins/pulse-in","subitems":[]},{"name":"servo write pin","path":"/reference/pins/servo-write-pin","subitems":[]},{"name":"servo set pulse","path":"/reference/pins/servo-set-pulse","subitems":[]},{"name":"i2c read number","path":"/reference/pins/i2c-read-number","subitems":[]},{"name":"i2c write number","path":"/reference/pins/i2c-write-number","subitems":[]},{"name":"set pull","path":"/reference/pins/set-pull","subitems":[]},{"name":"analog pitch","path":"/reference/pins/analog-pitch","subitems":[]},{"name":"analog set pitch pin","path":"/reference/pins/analog-set-pitch-pin","subitems":[]},{"name":"spi write","path":"/reference/pins/spi-write","subitems":[]},{"name":"spi Pins","path":"/reference/pins/spi-pins","subitems":[]},{"name":"spi format","path":"/reference/pins/spi-format","subitems":[]},{"name":"spi frequency","path":"/reference/pins/spi-frequency","subitems":[]}]},{"name":"Serial","path":"/reference/serial","subitems":[{"name":"write line","path":"/reference/serial/write-line","subitems":[]},{"name":"write number","path":"/reference/serial/write-number","subitems":[]},{"name":"write value","path":"/reference/serial/write-value","subitems":[]},{"name":"write string","path":"/reference/serial/write-string","subitems":[]},{"name":"read until","path":"/reference/serial/read-until","subitems":[]},{"name":"read line","path":"/reference/serial/read-line","subitems":[]},{"name":"read string","path":"/reference/serial/read-string","subitems":[]},{"name":"on data received","path":"/reference/serial/on-data-received","subitems":[]},{"name":"redirect","path":"/reference/serial/redirect","subitems":[]},{"name":"redirect to usb","path":"/reference/serial/redirect-to-usb","subitems":[]},{"name":"set baud rate","path":"/reference/serial/set-baud-rate","subitems":[]},{"name":"set write line padding","path":"/reference/serial/set-write-line-padding","subitems":[]},{"name":"write buffer","path":"/reference/serial/write-buffer","subitems":[]},{"name":"read buffer","path":"/reference/serial/read-buffer","subitems":[]}]},{"name":"Control","path":"/reference/control","subitems":[{"name":"in background","path":"/reference/control/in-background","subitems":[]},{"name":"reset","path":"/reference/control/reset","subitems":[]},{"name":"wait micros","path":"/reference/control/wait-micros","subitems":[]},{"name":"on event","path":"/reference/control/on-event","subitems":[]},{"name":"raise event","path":"/reference/control/raise-event","subitems":[]},{"name":"event timestamp","path":"/reference/control/event-timestamp","subitems":[]},{"name":"event value","path":"/reference/control/event-value","subitems":[]}]},{"name":"Bluetooth","path":"/reference/bluetooth","subitems":[{"name":"About","path":"/reference/bluetooth/about-bluetooth","subitems":[]},{"name":"Pairing","path":"/reference/bluetooth/bluetooth-pairing","subitems":[]},{"name":"on bluetooth connected","path":"/reference/bluetooth/on-bluetooth-connected","subitems":[]},{"name":"on bluetooth disconnected","path":"/reference/bluetooth/on-bluetooth-disconnected","subitems":[]},{"name":"start accelerometer service","path":"/reference/bluetooth/start-accelerometer-service","subitems":[]},{"name":"start button service","path":"/reference/bluetooth/start-button-service","subitems":[]},{"name":"start io pin service","path":"/reference/bluetooth/start-io-pin-service","subitems":[]},{"name":"start led service","path":"/reference/bluetooth/start-led-service","subitems":[]},{"name":"start magnetometer service","path":"/reference/bluetooth/start-magnetometer-service","subitems":[]},{"name":"start temperature service","path":"/reference/bluetooth/start-temperature-service","subitems":[]},{"name":"start uart service","path":"/reference/bluetooth/start-uart-service","subitems":[]},{"name":"uart read until","path":"/reference/bluetooth/uart-read-until","subitems":[]},{"name":"uart write string","path":"/reference/bluetooth/uart-write-string","subitems":[]},{"name":"uart write number","path":"/reference/bluetooth/uart-write-number","subitems":[]},{"name":"uart write value","path":"/reference/bluetooth/uart-write-value","subitems":[]},{"name":"advertise url","path":"/reference/bluetooth/advertise-url","subitems":[]},{"name":"stop advertising","path":"/reference/bluetooth/stop-advertising","subitems":[]},{"name":"advertise uid","path":"/reference/bluetooth/advertise-uid","subitems":[]},{"name":"advertise-uid-buffer","path":"/reference/bluetooth/advertise-uid-buffer","subitems":[]}]}]},{"name":"Extensions","path":"/extensions","subitems":[]},{"name":"Blocks","path":"/blocks","subitems":[{"name":"On Start","path":"/blocks/on-start","subitems":[]},{"name":"Loops","path":"/blocks/loops","subitems":[{"name":"repeat","path":"/blocks/loops/repeat","subitems":[]},{"name":"for","path":"/blocks/loops/for","subitems":[]},{"name":"while","path":"/blocks/loops/while","subitems":[]},{"name":"for of","path":"/blocks/loops/for-of","subitems":[]}]},{"name":"Logic","path":"/blocks/logic","subitems":[{"name":"if","path":"/blocks/logic/if","subitems":[]},{"name":"Boolean","path":"/blocks/logic/boolean","subitems":[]}]},{"name":"Variables","path":"/blocks/variables","subitems":[{"name":"assign","path":"/blocks/variables/assign","subitems":[]},{"name":"change var","path":"/blocks/variables/change","subitems":[]},{"name":"var","path":"/blocks/variables/var","subitems":[]}]},{"name":"Math","path":"/blocks/math","subitems":[]},{"name":"JavaScript blocks","path":"/blocks/javascript-blocks","subitems":[]},{"name":"Custom blocks","path":"/blocks/custom","subitems":[]}]},{"name":"Python","path":"/python","subitems":[{"name":"Calling","path":"/python/call","subitems":[]},{"name":"Sequencing","path":"/python/sequence","subitems":[]},{"name":"Variables","path":"/python/variables","subitems":[]},{"name":"Operators","path":"/python/operators","subitems":[]},{"name":"Statements","path":"/python/statements","subitems":[]},{"name":"Functions","path":"/python/functions","subitems":[]},{"name":"Classes","path":"/python/classes","subitems":[]}]},{"name":"JavaScript","path":"/javascript","subitems":[{"name":"Calling","path":"/javascript/call","subitems":[]},{"name":"Sequencing","path":"/javascript/sequence","subitems":[]},{"name":"Variables","path":"/javascript/variables","subitems":[]},{"name":"Operators","path":"/javascript/operators","subitems":[]},{"name":"Statements","path":"/javascript/statements","subitems":[]},{"name":"Functions","path":"/javascript/functions","subitems":[]},{"name":"Types","path":"/javascript/types","subitems":[]},{"name":"Classes","path":"/javascript/classes","subitems":[]},{"name":"Interfaces","path":"/javascript/interfaces","subitems":[]},{"name":"Generics","path":"/javascript/generics","subitems":[]}]},{"name":"Types","path":"/types","subitems":[{"name":"Number","path":"/types/number","subitems":[]},{"name":"String","path":"/types/string","subitems":[]},{"name":"Boolean","path":"/types/boolean","subitems":[]},{"name":"Array","path":"/types/array","subitems":[]},{"name":"Function","path":"/types/function","subitems":[]},{"name":"Buffer","path":"/types/buffer","subitems":[{"name":"Using buffers","path":"/types/buffer/using-buffers","subitems":[]},{"name":"Number format","path":"/types/buffer/number-format","subitems":[]}]}]},{"name":"Blocks Gallery","path":"/block-gallery","subitems":[]},{"name":"Miscellaneous","path":"","subitems":[{"name":"About","path":"/about","subitems":[]},{"name":"Support","path":"/support","subitems":[]},{"name":"Translate","path":"/translate","subitems":[]},{"name":"Sharing projects","path":"/share","subitems":[]},{"name":"Offline support","path":"/offline","subitems":[]},{"name":"Save","path":"/save","subitems":[]},{"name":"Sign In","path":"/identity/sign-in","subitems":[]},{"name":"Cloud Sync","path":"/identity/cloud-sync","subitems":[]},{"name":"Home Page Content","path":"/homepage-content","subitems":[]}]},{"name":"Hardware","path":"/device","subitems":[{"name":"Data Analysis","path":"/device/data-analysis","subitems":[{"name":"Plotting with LEDs","path":"/device/data-analysis/led-plotting","subitems":[]},{"name":"Viewing Data","path":"/device/data-analysis/viewing","subitems":[]},{"name":"Writing Data","path":"/device/data-analysis/writing","subitems":[]},{"name":"Generating Data","path":"/device/data-analysis/generating","subitems":[]},{"name":"Analyzing Data","path":"/device/data-analysis/analyze","subitems":[]},{"name":"Remote Data","path":"/device/data-analysis/remote","subitems":[]}]},{"name":"Error codes","path":"/device/error-codes","subitems":[]},{"name":"Foil circuits","path":"/device/foil-circuits","subitems":[]},{"name":"Incompatible Hardware","path":"/device/incompatible","subitems":[]},{"name":"MES events","path":"/device/mes-events","subitems":[]},{"name":"Pins","path":"/device/pins","subitems":[]},{"name":"Reactive","path":"/device/reactive","subitems":[]},{"name":"Screen","path":"/device/screen","subitems":[]},{"name":"Serial","path":"/device/serial","subitems":[]},{"name":"Servo","path":"/device/servo","subitems":[]},{"name":"Simulator","path":"/device/simulator","subitems":[]},{"name":"USB","path":"/device/usb","subitems":[]},{"name":"WebUSB","path":"/device/usb/webusb","subitems":[{"name":"WebUSB Troubleshoot","path":"/device/usb/webusb/troubleshoot","subitems":[]}]},{"name":"Flashing via HID (CMSIS-DAP)","path":"/hidflash","subitems":[]}]},{"name":"Developers","path":"","subitems":[{"name":"Command Line Interface","path":"/cli","subitems":[]},{"name":"Visual Studio Code support","path":"/code","subitems":[]},{"name":"Blocks Embed","path":"/blocks-embed","subitems":[]}]},{"name":"Projects","path":"/projects","subitems":[{"name":"Flashing Heart","path":"/projects/flashing-heart","subitems":[]},{"name":"Smiley Buttons","path":"/projects/smiley-buttons","subitems":[]},{"name":"Love Meter","path":"/projects/love-meter","subitems":[]},{"name":"Rock Paper Scissors","path":"/projects/rock-paper-scissors","subitems":[]},{"name":"Magic Button Trick","path":"/projects/magic-button-trick","subitems":[]},{"name":"Coin Flipper","path":"/projects/coin-flipper","subitems":[]},{"name":"Salute!","path":"/projects/salute","subitems":[]},{"name":"Hack Your Headphones","path":"/projects/hack-your-headphones","subitems":[]},{"name":"Banana Keyboard","path":"/projects/banana-keyboard","subitems":[]},{"name":"Guitar","path":"/projects/guitar","subitems":[]},{"name":"Duct Tape Wallet","path":"/projects/wallet","subitems":[]},{"name":"Watch","path":"/projects/watch","subitems":[]},{"name":"Soil Moisture","path":"/projects/soil-moisture","subitems":[]},{"name":"Plant Watering","path":"/projects/plant-watering","subitems":[]},{"name":"Reaction Time","path":"/projects/reaction-time","subitems":[]},{"name":"States of Matter","path":"/projects/states-of-matter","subitems":[]},{"name":"Mood Radio","path":"/projects/mood-radio","subitems":[]},{"name":"Tele-Potato","path":"/projects/tele-potato","subitems":[]},{"name":"Hot or Cold","path":"/projects/hot-or-cold","subitems":[]},{"name":"Voting Machine","path":"/projects/voting-machine","subitems":[]},{"name":"Infection","path":"/projects/infection","subitems":[]},{"name":"Fireflies","path":"/projects/fireflies","subitems":[]},{"name":"Rock Paper Scissors Teams","path":"/projects/rps-teams","subitems":[]},{"name":"Inchworm","path":"/projects/inchworm","subitems":[]},{"name":"Milk Carton Robot","path":"/projects/milk-carton-robot","subitems":[]},{"name":"Milk Monster","path":"/projects/milky-monster","subitems":[]},{"name":"RC Car","path":"/projects/rc-car","subitems":[]},{"name":"Timing Gates","path":"/projects/timing-gates","subitems":[]},{"name":"Compass","path":"/projects/compass","subitems":[]},{"name":"Telegraph","path":"/projects/telegraph","subitems":[]},{"name":"Railway Crossing","path":"/projects/railway-crossing","subitems":[]},{"name":"Karel","path":"/projects/karel","subitems":[]},{"name":"Stopwatch","path":"/projects/stopwatch","subitems":[]},{"name":"Name Tag","path":"/projects/name-tag","subitems":[]},{"name":"Step counter","path":"/projects/step-counter","subitems":[]},{"name":"Servo calibrator","path":"/projects/servo-calibrator","subitems":[]},{"name":"Analog Pin Tester","path":"/projects/analog-pin-tester","subitems":[]},{"name":"Light Level Meter","path":"/projects/light-level-meter","subitems":[]},{"name":"Radio bridge","path":"/projects/radio-bridge","subitems":[]},{"name":"Snap the dot","path":"/projects/snap-the-dot","subitems":[]},{"name":"Red light green light","path":"/projects/red-light-green-light","subitems":[]},{"name":"Name Badge","path":"/projects/name-badge","subitems":[]}]}],"id":"microbit","title":"Microsoft MakeCode for micro:bit","name":"makecode.microbit.org","description":"A Blocks / JavaScript code editor for the micro:bit powered by Microsoft MakeCode.","htmlDocIncludes":{}},"queryVariants":{"hidemenu":{"appTheme":{"hideMenuBar":true}},"hidelanguage":{"appTheme":{"selectLanguage":false}},"androidapp":{"compile":{"webUSB":false},"appTheme":{"disableBlobObjectDownload":true}},"skillsMap=1":{"appTheme":{"hideReplaceMyCode":false}},"teachertool=1":{"appTheme":{"hideMenuBar":true,"workspaceSearch":true,"noReloadOnUpdate":true}}},"uploadDocs":true,"versions":{"branch":"master","tag":"v7.1.42","commits":"https://github.com/microsoft/pxt-microbit/commits/2047bab2db8b1d8151974b7ac65c051d8004f504","target":"7.1.42","pxt":"11.4.28"},"blocksprj":{"id":"blocksprj","config":{"name":"{0} block","dependencies":{"core":"*","radio":"*","microphone":"*"},"description":"","files":["main.blocks","main.ts","README.md"],"additionalFilePaths":[]},"files":{"README.md":"","main.blocks":"<xml xmlns=\"http://www.w3.org/1999/xhtml\">\n  <block type=\"pxt-on-start\"></block>\n  <block type=\"device_forever\"></block>\n</xml>","main.ts":"\n"}},"tsprj":{"id":"tsprj","config":{"name":"{0} bit","dependencies":{"core":"*","radio":"*","microphone":"*"},"description":"","files":["main.ts","README.md"],"additionalFilePaths":[]},"files":{"README.md":"","main.ts":"basic.showLeds(`\n    . . . . .\n    . # . # .\n    . . . . .\n    # . . . #\n    . # # # .\n    `);"}},"colorThemeMap":{"pxt-high-contrast":{"id":"pxt-high-contrast","name":"High Contrast","weight":100,"monacoBaseTheme":"hc-black","colors":{"pxt-header-background":"#000000","pxt-header-foreground":"#FFFFFF","pxt-header-background-hover":"#000000","pxt-header-foreground-hover":"#FFFFFF","pxt-header-stencil":"#FFFFFF","pxt-primary-background":"#000000","pxt-primary-foreground":"#FFFFFF","pxt-primary-background-hover":"#000000","pxt-primary-foreground-hover":"#FFFFFF","pxt-primary-accent":"#000000","pxt-secondary-background":"#000000","pxt-secondary-foreground":"#FFFFFF","pxt-secondary-background-hover":"#000000","pxt-secondary-foreground-hover":"#FFFFFF","pxt-secondary-accent":"#000000","pxt-tertiary-background":"#000000","pxt-tertiary-foreground":"#FFFFFF","pxt-tertiary-background-hover":"#000000","pxt-tertiary-foreground-hover":"#FFFFFF","pxt-tertiary-accent":"#000000","pxt-target-background1":"#000000","pxt-target-foreground1":"#FFFFFF","pxt-target-background1-hover":"#000000","pxt-target-foreground1-hover":"#cccccc","pxt-target-stencil1":"#FFFFFF","pxt-target-background2":"#000000","pxt-target-foreground2":"#FFFFFF","pxt-target-background2-hover":"#000000","pxt-target-foreground2-hover":"#cccccc","pxt-target-stencil2":"#FFFFFF","pxt-target-background3":"#000000","pxt-target-foreground3":"#FFFFFF","pxt-target-background3-hover":"#000000","pxt-target-foreground3-hover":"#cccccc","pxt-target-stencil3":"#FFFFFF","pxt-neutral-background1":"#000000","pxt-neutral-foreground1":"#FFFFFF","pxt-neutral-background1-hover":"#000000","pxt-neutral-foreground1-hover":"#FFFFFF","pxt-neutral-stencil1":"#FFFFFF","pxt-neutral-background2":"#000000","pxt-neutral-foreground2":"#FFFFFF","pxt-neutral-background2-hover":"#000000","pxt-neutral-foreground2-hover":"#FFFFFF","pxt-neutral-stencil2":"#FFFFFF","pxt-neutral-background3":"#000000","pxt-neutral-foreground3":"#FFFFFF","pxt-neutral-background3-hover":"#000000","pxt-neutral-foreground3-hover":"#FFFFFF","pxt-neutral-stencil3":"#FFFFFF","pxt-neutral-background3-alpha90":"#000000E5","pxt-neutral-base":"rgba(255, 255, 255, 1)","pxt-neutral-alpha0":"rgba(255, 255, 255, 0)","pxt-neutral-alpha10":"rgba(255, 255, 255, 0.1)","pxt-neutral-alpha20":"rgba(255, 255, 255, 0.2)","pxt-neutral-alpha50":"rgba(255, 255, 255, 0.5)","pxt-neutral-alpha80":"rgba(255, 255, 255, 0.8)","pxt-link":"#807FFF","pxt-link-hover":"#1b19ff","pxt-focus-border":"#FFFF00","pxt-success":"#00FF00","pxt-success-foreground":"#000000","pxt-success-hover":"#00FF00","pxt-success-alpha10":"#00FF0019","pxt-warning":"#00FFFF","pxt-warning-foreground":"#FFFFFF","pxt-warning-hover":"#00FFFF","pxt-warning-alpha10":"#00FFFF19","pxt-error":"#880000","pxt-error-foreground":"#FFFFFF","pxt-error-hover":"#880000","pxt-error-alpha10":"#88000019","pxt-colors-purple-background":"#FF00FF","pxt-colors-purple-foreground":"#000000","pxt-colors-purple-hover":"#FF00FF","pxt-colors-purple-alpha10":"#FF00FF19","pxt-colors-orange-background":"#FF7F00","pxt-colors-orange-foreground":"#000000","pxt-colors-orange-hover":"#FF7F00","pxt-colors-orange-alpha10":"#FF7F0019","pxt-colors-brown-background":"#d1b7a3","pxt-colors-brown-foreground":"#FFFFFF","pxt-colors-brown-hover":"#d1b7a3","pxt-colors-brown-alpha10":"#d1b7a319","pxt-colors-blue-background":"#8C8CFF","pxt-colors-blue-foreground":"#000000","pxt-colors-blue-hover":"#8C8CFF","pxt-colors-blue-alpha10":"#8C8CFF19","pxt-colors-green-background":"#00FF00","pxt-colors-green-foreground":"#000000","pxt-colors-green-hover":"#00FF00","pxt-colors-green-alpha10":"#00FF0019","pxt-colors-red-background":"#880000","pxt-colors-red-foreground":"#FFFFFF","pxt-colors-red-hover":"#880000","pxt-colors-red-alpha10":"#88000019","pxt-colors-teal-background":"#5BE0FF","pxt-colors-teal-foreground":"#000000","pxt-colors-teal-hover":"#5BE0FF","pxt-colors-teal-alpha10":"#5BE0FF19","pxt-colors-yellow-background":"#00FFFF","pxt-colors-yellow-foreground":"#000000","pxt-colors-yellow-hover":"#00FFFF","pxt-colors-yellow-alpha10":"#00FFFF19"},"overrideCss":".common-button {\n    color: var(--pxt-neutral-foreground2) !important;\n    background-color: var(--pxt-neutral-background2) !important;\n    border-color: var(--pxt-neutral-foreground2) !important;\n}\n\n.common-button:hover, .common-button:focus {\n    outline: 2px solid var(--pxt-colors-yellow-background) !important;\n    z-index: 1;\n}\n\n/* \n * Inverted image colors\n */\n.barcharticon,\n.blockly-ws-search-next-btn,\n.blockly-ws-search-previous-btn,\n.blockly-ws-search-close-btn {\n    filter: invert(1);\n}\n\n/* Sim toolbar */\n#simulator .editor-sidebar .simtoolbar .debug-button.active,\n#simulator .editor-sidebar .simtoolbar .debug-button.active:hover,\n#simulator .editor-sidebar .simtoolbar .debug-button.active:hover i {\n    /* Make active state more apparent by inverting the colors */\n    background: var(--pxt-neutral-foreground2) !important;\n    color: var(--pxt-neutral-background2) !important;\n}\n\n/* Image Editor */\n.image-editor-topbar, .image-editor-bottombar, .image-editor-sidebar {\n    background: var(--pxt-neutral-background1) !important;\n}\n.image-editor-tool-buttons {\n    background: none !important;\n}\n.image-editor-button,\n.image-editor-input,\n.image-editor-confirm {\n    border: 1px solid var(--pxt-neutral-foreground1);\n}\n.image-editor-canvas, .image-editor-canvas:hover, .image-editor-canvas:focus {\n    outline: none !important;\n}\n.cursor-button {\n    /* remove margin since we now have a border around the cursor buttons and it looks better centered */\n    margin-right: 0;\n}\n\n/* Toolbox */\n.pxtToolbox:not(.invertedToolbox) span.blocklyTreeLabel {\n    color: var(--pxt-target-foreground3);\n}\n\n.pxtToolbox:not(.invertedToolbox) .blocklyTreeSelected span.blocklyTreeLabel,\n.pxtToolbox:not(.invertedToolbox) .blocklyTreeSelected span.blocklyTreeIcon {\n    color: var(--pxt-target-foreground3);\n}\n\n.pxtToolbox:not(.invertedToolbox) .blocklyTreeRow:not(.blocklyTreeSelected) .blocklyTreeLabel {\n    color: var(--pxt-target-foreground3) !important;\n}\n\n.pxtToolbox:not(.invertedToolbox) .blocklyTreeRow:not(.blocklyTreeSelected):hover,\n.pxtToolbox:not(.invertedToolbox) .blocklyTreeRow:not(.blocklyTreeSelected):focus {\n    background-color: #404040 !important;\n}\n"},"microbit-light":{"id":"microbit-light","name":"Micro:bit Light","weight":20,"colors":{"pxt-header-background":"#3454D1","pxt-header-foreground":"#FFFFFF","pxt-header-background-hover":"#1d3282","pxt-header-foreground-hover":"#FFFFFF","pxt-header-stencil":"#2742ab","pxt-primary-background":"#6633cc","pxt-primary-foreground":"#FFFFFF","pxt-primary-background-hover":"#5C2EB8","pxt-primary-foreground-hover":"#FFFFFF","pxt-primary-accent":"#5229A3","pxt-secondary-background":"#3454D1","pxt-secondary-foreground":"#FFFFFF","pxt-secondary-background-hover":"#2742ab","pxt-secondary-foreground-hover":"#FFFFFF","pxt-secondary-accent":"#516DD8","pxt-tertiary-background":"#3454D1","pxt-tertiary-foreground":"#FFFFFF","pxt-tertiary-background-hover":"#2742ab","pxt-tertiary-foreground-hover":"#FFFFFF","pxt-tertiary-accent":"#1d3282","pxt-target-background1":"#ECF0F1","pxt-target-foreground1":"#000000","pxt-target-background1-hover":"#cfd9db","pxt-target-foreground1-hover":"#000000","pxt-target-stencil1":"#e1e1e1","pxt-target-background2":"#FDFDFF","pxt-target-foreground2":"#000000","pxt-target-background2-hover":"#cacaff","pxt-target-foreground2-hover":"#000000","pxt-target-stencil2":"#e1e1e1","pxt-target-background3":"#FFFFFF","pxt-target-foreground3":"#000000","pxt-target-background3-hover":"#e6e6e6","pxt-target-foreground3-hover":"#000000","pxt-target-stencil3":"#e1e1e1","pxt-neutral-background1":"#FFFFFF","pxt-neutral-foreground1":"rgba(0,0,0,.85)","pxt-neutral-background1-hover":"#e6e6e6","pxt-neutral-foreground1-hover":"rgba(0,0,0,.85)","pxt-neutral-stencil1":"rgba(34, 74, 114, 0.15)","pxt-neutral-background2":"#F8F8F8","pxt-neutral-foreground2":"rgba(0,0,0,.85)","pxt-neutral-background2-hover":"#DFDFDF","pxt-neutral-foreground2-hover":"rgba(0,0,0,.85)","pxt-neutral-stencil2":"#e9eef2","pxt-neutral-background3":"#617374","pxt-neutral-foreground3":"#FFFFFF","pxt-neutral-background3-hover":"#363c3d","pxt-neutral-foreground3-hover":"#FFFFFF","pxt-neutral-stencil3":"#FFFFFF","pxt-neutral-background3-alpha90":"#617374E5","pxt-neutral-base":"rgba(0, 0, 0, 1)","pxt-neutral-alpha0":"rgba(0, 0, 0, 0)","pxt-neutral-alpha10":"rgba(0, 0, 0, 0.1)","pxt-neutral-alpha20":"rgba(0, 0, 0, 0.2)","pxt-neutral-alpha50":"rgba(0, 0, 0, 0.5)","pxt-neutral-alpha80":"rgba(0, 0, 0, 0.8)","pxt-link":"#3977B4","pxt-link-hover":"#204467","pxt-focus-border":"#0078D4","pxt-success":"#2ECC71","pxt-pxt-success-foreground":"#000000","pxt-pxt-success-hover":"#22BE64","pxt-pxt-success-alpha10":"#2ECC7119","pxt-warning":"#FFD43A","pxt-warning-foreground":"#000000","pxt-warning-hover":"#FFCE21","pxt-warning-alpha10":"#FFD43A19","pxt-error":"#FF3A54","pxt-error-foreground":"#000000","pxt-error-hover":"#FF213E","pxt-error-alpha10":"#FF3A5419","pxt-colors-purple-background":"#9932cc","pxt-colors-purple-foreground":"#FFFFFF","pxt-colors-purple-hover":"#7a28a3","pxt-colors-purple-alpha10":"#9932cc19","pxt-colors-orange-background":"#ff7f50","pxt-colors-orange-foreground":"#FFFFFF","pxt-colors-orange-hover":"#ff5a1d","pxt-colors-orange-alpha10":"#ff7f5019","pxt-colors-brown-background":"#663905","pxt-colors-brown-foreground":"#FFFFFF","pxt-colors-brown-hover":"#351e03","pxt-colors-brown-alpha10":"#66390519","pxt-colors-blue-background":"#3454D1","pxt-colors-blue-foreground":"#FFFFFF","pxt-colors-blue-hover":"#2742ab","pxt-colors-blue-alpha10":"#3454D119","pxt-colors-green-background":"#107c10","pxt-colors-green-foreground":"#FFFFFF","pxt-colors-green-hover":"#096a09","pxt-colors-green-alpha10":"#107c1019","pxt-colors-red-background":"#E41B21","pxt-colors-red-foreground":"#FFFFFF","pxt-colors-red-hover":"#d60f15","pxt-colors-red-alpha10":"#e41b2119","pxt-colors-teal-background":"#2C7485","pxt-colors-teal-foreground":"#FFFFFF","pxt-colors-teal-hover":"#1f535f","pxt-colors-teal-alpha10":"#2C748519","pxt-colors-yellow-background":"#FDE74C","pxt-colors-yellow-foreground":"#000000","pxt-colors-yellow-hover":"#fce01a","pxt-colors-yellow-alpha10":"#FDE74C19"},"overrideCss":"/* Lots of specificity to override another !important rule */\n#simulator #editorSidebar .simtoolbar .ui.icon.tiny.buttons .ui.button.play-button.play .icon.play {\n    color: var(--pxt-colors-green-background) !important;\n}\n\n.theme-preview-microbit-light .theme-preview-sim-button {\n    background-color: var(--pxt-neutral-background2) !important;\n}\n"}},"bundledpkgs":{"core":{"README.md":"# core\n\nThe core library.\n\n","advmath.cpp":"#include \"pxtbase.h\"\n\nusing namespace std;\n\n#define SINGLE(op) return fromDouble(::op(toDouble(x)));\n\nnamespace Math_ {\n\n//%\nTNumber log2(TNumber x){SINGLE(log2)}\n//%\nTNumber exp(TNumber x){SINGLE(exp)}\n//%\nTNumber tanh(TNumber x){SINGLE(tanh)}\n//%\nTNumber sinh(TNumber x){SINGLE(sinh)}\n//%\nTNumber cosh(TNumber x){SINGLE(cosh)}\n//%\nTNumber atanh(TNumber x){SINGLE(atanh)}\n//%\nTNumber asinh(TNumber x){SINGLE(asinh)}\n//%\nTNumber acosh(TNumber x){SINGLE(acosh)}\n\n}","basic.cpp":"#include \"pxt.h\"\n\n\n/**\n * Provides access to basic micro:bit functionality.\n */\n//% color=#1E90FF weight=116 icon=\"\\uf00a\"\nnamespace basic {\n    /**\n     * Draws an image on the LED screen.\n     * @param leds the pattern of LED to turn on/off.\n     * @param interval time in milliseconds to pause after drawing.\n     */\n    //% help=basic/show-leds\n    //% weight=95 blockGap=8\n    //% imageLiteral=1 async\n    //% blockId=device_show_leds\n    //% block=\"show leds\" icon=\"\\uf00a\"\n    //% parts=\"ledmatrix\"\n    void showLeds(ImageLiteral_ leds, int interval = 400) {\n      uBit.display.print(MicroBitImage(imageBytes(leds)), 0, 0, 0, interval);\n    }\n\n    /**\n     * Display text on the display, one character at a time. If the string fits on the screen (i.e. is one letter), does not scroll.\n     * @param text the text to scroll on the screen, eg: \"Hello!\"\n     * @param interval how fast to shift characters; eg: 150, 100, 200, -100\n     */\n    //% help=basic/show-string\n    //% weight=87 blockGap=16\n    //% block=\"show|string %text\"\n    //% async\n    //% blockId=device_print_message\n    //% parts=\"ledmatrix\"\n    //% text.shadowOptions.toString=true\n    void showString(String text, int interval = 150) {\n      if (interval <= 0)\n        interval = 1;\n      int l = text ? text->getUTF8Size() : 0;\n      if (l == 0) {\n        uBit.display.clear();\n        fiber_sleep(interval * 5);\n      } else if (l > 1) {\n        uBit.display.scroll(MSTR(text), interval);\n      } else {\n        uBit.display.printChar(text->getUTF8Data()[0], interval * 5);\n      }\n    }\n\n    /**\n     * Turn off all LEDs\n     */\n    //% help=basic/clear-screen weight=79\n    //% blockId=device_clear_display block=\"clear screen\"\n    //% parts=\"ledmatrix\"\n    void clearScreen() {\n      uBit.display.image.clear();\n    }\n\n    /**\n     * Shows a sequence of LED screens as an animation.\n     * @param leds pattern of LEDs to turn on/off\n     * @param interval time in milliseconds between each redraw.\n     */\n    //% help=basic/show-animation imageLiteral=1 async\n    //% parts=\"ledmatrix\"\n    void showAnimation(ImageLiteral_ leds, int interval = 400) {\n      uBit.display.animate(MicroBitImage(imageBytes(leds)), interval, 5, 0, 0);\n    }\n\n    /**\n     * Draws an image on the LED screen.\n     * @param leds pattern of LEDs to turn on/off\n     */\n    //% help=basic/plot-leds weight=80\n    //% parts=\"ledmatrix\"\n    void plotLeds(ImageLiteral_ leds) {\n      MicroBitImage i(imageBytes(leds));\n      uBit.display.print(i, 0, 0, 0, 0);\n    }\n\n    /**\n     * Repeats the code forever in the background. On each iteration, allows other codes to run.\n     * @param body code to execute\n     */\n    //% help=basic/forever weight=55 blockGap=16 blockAllowMultiple=1 afterOnStart=true\n    //% blockId=device_forever block=\"forever\" icon=\"\\uf01e\"\n    void forever(Action a) {\n      runForever(a);\n    }\n\n    /**\n     * Pause for the specified time in milliseconds\n     * @param ms how long to pause for, eg: 100, 200, 500, 1000, 2000\n     */\n    //% help=basic/pause weight=54\n    //% async block=\"pause (ms) %pause\" blockGap=16\n    //% blockId=device_pause icon=\"\\uf110\"\n    //% pause.shadow=timePicker\n    void pause(int ms) {\n      fiber_sleep(ms);\n    }\n}","basic.ts":"namespace basic {\n\n    /**\n     * Scroll a number on the screen. If the number fits on the screen (i.e. is a single digit), do not scroll.\n     * @param interval speed of scroll; eg: 150, 100, 200, -100\n     */\n    //% help=basic/show-number\n    //% weight=96\n    //% blockId=device_show_number block=\"show|number %number\" blockGap=8\n    //% async\n    //% parts=\"ledmatrix\" interval.defl=150\n    export function showNumber(value: number, interval?: number) {\n        if (isNaN(value))\n            showString(\"?\")\n        else\n            showString(Math.roundWithPrecision(value, 2).toString(), interval);\n    }\n}\n\n/**\n * Pause for the specified time in milliseconds\n * @param ms how long to pause for, eg: 100, 200, 500, 1000, 2000\n */\nfunction pause(ms: number): void {\n    if (isNaN(ms)) ms = 20\n    basic.pause(ms);\n}\n\n/**\n * Repeats the code forever in the background. On each iteration, allows other codes to run.\n * @param body code to execute\n */\nfunction forever(a: () => void): void {\n    basic.forever(a);\n}\n","buffer.cpp":"#include \"pxtbase.h\"\n#include <limits.h>\n\nusing namespace std;\n\n//% indexerGet=BufferMethods::getByte indexerSet=BufferMethods::setByte\nnamespace BufferMethods {\n//%\nuint8_t *getBytes(Buffer buf) {\n    return buf->data;\n}\n\n//%\nint getByte(Buffer buf, int off) {\n    if (buf && 0 <= off && off < buf->length)\n        return buf->data[off];\n    return 0;\n}\n\n//%\nvoid setByte(Buffer buf, int off, int v) {\n    if (buf && 0 <= off && off < buf->length)\n        buf->data[off] = v;\n}\n\n/**\n * Reads an unsigned byte at a particular location\n */\n//%\nint getUint8(Buffer buf, int off) {\n    return getByte(buf, off);\n}\n\n/**\n * Returns false when the buffer can be written to.\n */\n//%\nbool isReadOnly(Buffer buf) {\n    return buf->isReadOnly();\n}\n\n/**\n * Writes an unsigned byte at a particular location\n */\n//%\nvoid setUint8(Buffer buf, int off, int v) {\n    setByte(buf, off, v);\n}\n\nint writeBuffer(Buffer buf, int dstOffset, Buffer src, int srcOffset = 0, int length = -1) {\n    if (length < 0)\n        length = src->length;\n\n    if (srcOffset < 0 || dstOffset < 0 || dstOffset > buf->length)\n        return -1;\n\n    length = pxt::min(src->length - srcOffset, buf->length - dstOffset);\n\n    if (length < 0)\n        return -1;\n\n    if (buf == src) {\n        memmove(buf->data + dstOffset, src->data + srcOffset, length);\n    } else {\n        memcpy(buf->data + dstOffset, src->data + srcOffset, length);\n    }\n\n    return 0;\n}\n\n/**\n * Write a number in specified format in the buffer.\n */\n//%\nvoid setNumber(Buffer buf, NumberFormat format, int offset, TNumber value) {\n    if (offset < 0)\n        return;\n    setNumberCore(buf->data + offset, buf->length - offset, format, value);\n}\n\n/**\n * Read a number in specified format from the buffer.\n */\n//%\nTNumber getNumber(Buffer buf, NumberFormat format, int offset) {\n    if (offset < 0)\n        return fromInt(0);\n    return getNumberCore(buf->data + offset, buf->length - offset, format);\n}\n\n/** Returns the length of a Buffer object. */\n//% property\nint length(Buffer s) {\n    return s->length;\n}\n\n/**\n * Fill (a fragment) of the buffer with given value.\n */\n//%\nvoid fill(Buffer buf, int value, int offset = 0, int length = -1) {\n    if (offset < 0 || offset > buf->length)\n        return; // DEVICE_INVALID_PARAMETER;\n    if (length < 0)\n        length = buf->length;\n    length = pxt::min(length, buf->length - offset);\n    memset(buf->data + offset, value, length);\n}\n\n/**\n * Return a copy of a fragment of a buffer.\n */\n//%\nBuffer slice(Buffer buf, int offset = 0, int length = -1) {\n    offset = pxt::min((int)buf->length, offset);\n    if (length < 0)\n        length = buf->length;\n    length = pxt::min(length, buf->length - offset);\n    return mkBuffer(buf->data + offset, length);\n}\n\n/**\n * Shift buffer left in place, with zero padding.\n * @param offset number of bytes to shift; use negative value to shift right\n * @param start start offset in buffer. Default is 0.\n * @param length number of elements in buffer. If negative, length is set as the buffer length minus\n * start. eg: -1\n */\n//%\nvoid shift(Buffer buf, int offset, int start = 0, int length = -1) {\n    if (length < 0)\n        length = buf->length - start;\n    if (start < 0 || start + length > buf->length || start + length < start || length == 0 ||\n        offset == 0 || offset == INT_MIN)\n        return;\n    if (offset <= -length || offset >= length) {\n        fill(buf, 0);\n        return;\n    }\n\n    uint8_t *data = buf->data + start;\n    if (offset < 0) {\n        offset = -offset;\n        memmove(data + offset, data, length - offset);\n        memset(data, 0, offset);\n    } else {\n        length = length - offset;\n        memmove(data, data + offset, length);\n        memset(data + length, 0, offset);\n    }\n}\n\n/**\n * Convert a buffer to string assuming UTF8 encoding\n */\n//%\nString toString(Buffer buf) {\n    return mkString((char *)buf->data, buf->length);\n}\n\n/**\n * Convert a buffer to its hexadecimal representation.\n */\n//%\nString toHex(Buffer buf) {\n    const char *hex = \"0123456789abcdef\";\n    auto res = mkStringCore(NULL, buf->length * 2);\n    for (int i = 0; i < buf->length; ++i) {\n        res->ascii.data[i << 1] = hex[buf->data[i] >> 4];\n        res->ascii.data[(i << 1) + 1] = hex[buf->data[i] & 0xf];\n    }\n    return res;\n}\n\n/**\n * Rotate buffer left in place.\n * @param offset number of bytes to shift; use negative value to shift right\n * @param start start offset in buffer. Default is 0.\n * @param length number of elements in buffer. If negative, length is set as the buffer length minus\n * start. eg: -1\n */\n//%\nvoid rotate(Buffer buf, int offset, int start = 0, int length = -1) {\n    if (length < 0)\n        length = buf->length - start;\n    if (start < 0 || start + length > buf->length || start + length < start || length == 0 ||\n        offset == 0 || offset == INT_MIN)\n        return;\n\n    if (offset < 0)\n        offset += length << 8; // try to make it positive\n    offset %= length;\n    if (offset < 0)\n        offset += length;\n\n    uint8_t *data = buf->data + start;\n\n    uint8_t *n_first = data + offset;\n    uint8_t *first = data;\n    uint8_t *next = n_first;\n    uint8_t *last = data + length;\n\n    while (first != next) {\n        uint8_t tmp = *first;\n        *first++ = *next;\n        *next++ = tmp;\n        if (next == last) {\n            next = n_first;\n        } else if (first == n_first) {\n            n_first = next;\n        }\n    }\n}\n\n/**\n * Write contents of `src` at `dstOffset` in current buffer.\n */\n//%\nvoid write(Buffer buf, int dstOffset, Buffer src) {\n    // srcOff and length not supported, we only do up to 4 args :/\n    writeBuffer(buf, dstOffset, src, 0, -1);\n}\n\n/**\n * Compute k-bit FNV-1 non-cryptographic hash of the buffer.\n */\n//%\nuint32_t hash(Buffer buf, int bits) {\n    if (bits < 1)\n        return 0;\n    uint32_t h = hash_fnv1(buf->data, buf->length);\n    if (bits >= 32)\n        return h;\n    else\n        return ((h ^ (h >> bits)) & ((1 << bits) - 1));\n}\n\n} // namespace BufferMethods\n\nbool BoxedBuffer::isInstance(TValue v) {\n    return getAnyVTable(v) == &buffer_vt;\n}\n\n// The functions below are deprecated in control namespace, but they are referenced\n// in Buffer namespaces via explicit shim=...\nnamespace control {\n/**\n * Create a new zero-initialized buffer.\n * @param size number of bytes in the buffer\n */\n//% deprecated=1\nBuffer createBuffer(int size) {\n    return mkBuffer(NULL, size);\n}\n\n/**\n * Create a new buffer with UTF8-encoded string\n * @param str the string to put in the buffer\n */\n//% deprecated=1\nBuffer createBufferFromUTF8(String str) {\n#if PXT_UTF8\n    auto sz = toRealUTF8(str, NULL);\n    auto r = mkBuffer(NULL, sz);\n    toRealUTF8(str, r->data);\n    return r;\n#else\n    return mkBuffer((const uint8_t *)str->getUTF8Data(), str->getUTF8Size());\n#endif\n}\n} // namespace control\n\nnamespace pxt {\nstatic int writeBytes(uint8_t *dst, uint8_t *src, int length, bool swapBytes, int szLeft) {\n    if (szLeft < length) {\n        return -1;\n    }\n\n    if (swapBytes) {\n        uint8_t *p = dst + length;\n        for (int i = 0; i < length; ++i)\n            *--p = src[i];\n    } else {\n        if (length == 4 && ((uintptr_t)dst & 3) == 0)\n            *(uint32_t *)dst = *(uint32_t *)src;\n        else if (length == 2 && ((uintptr_t)dst & 1) == 0)\n            *(uint16_t *)dst = *(uint16_t *)src;\n        else\n            memcpy(dst, src, length);\n    }\n\n    return 0;\n}\n\nstatic int readBytes(uint8_t *src, uint8_t *dst, int length, bool swapBytes, int szLeft) {\n    if (szLeft < length) {\n        memset(dst, 0, length);\n        return -1;\n    }\n\n    if (swapBytes) {\n        uint8_t *p = src + length;\n        for (int i = 0; i < length; ++i)\n            dst[i] = *--p;\n    } else {\n        if (length == 4 && ((uintptr_t)src & 3) == 0)\n            *(uint32_t *)dst = *(uint32_t *)src;\n        else if (length == 2 && ((uintptr_t)src & 1) == 0)\n            *(uint16_t *)dst = *(uint16_t *)src;\n        else\n            memcpy(dst, src, length);\n    }\n\n    return 0;\n}\n\nvoid setNumberCore(uint8_t *buf, int szLeft, NumberFormat format, TNumber value) {\n    int8_t i8;\n    uint8_t u8;\n    int16_t i16;\n    uint16_t u16;\n    int32_t i32;\n    uint32_t u32;\n    float f32;\n    double f64;\n\n// Assume little endian\n#define WRITEBYTES(isz, swap, toInt)                                                               \\\n    isz = toInt(value);                                                                            \\\n    writeBytes(buf, (uint8_t *)&isz, sizeof(isz), swap, szLeft);                                   \\\n    break\n\n    switch (format) {\n    case NumberFormat::Int8LE:\n        WRITEBYTES(i8, false, toInt);\n    case NumberFormat::UInt8LE:\n        WRITEBYTES(u8, false, toInt);\n    case NumberFormat::Int16LE:\n        WRITEBYTES(i16, false, toInt);\n    case NumberFormat::UInt16LE:\n        WRITEBYTES(u16, false, toInt);\n    case NumberFormat::Int32LE:\n        WRITEBYTES(i32, false, toInt);\n    case NumberFormat::UInt32LE:\n        WRITEBYTES(u32, false, toUInt);\n\n    case NumberFormat::Int8BE:\n        WRITEBYTES(i8, true, toInt);\n    case NumberFormat::UInt8BE:\n        WRITEBYTES(u8, true, toInt);\n    case NumberFormat::Int16BE:\n        WRITEBYTES(i16, true, toInt);\n    case NumberFormat::UInt16BE:\n        WRITEBYTES(u16, true, toInt);\n    case NumberFormat::Int32BE:\n        WRITEBYTES(i32, true, toInt);\n    case NumberFormat::UInt32BE:\n        WRITEBYTES(u32, true, toUInt);\n\n    case NumberFormat::Float32LE:\n        WRITEBYTES(f32, false, toFloat);\n    case NumberFormat::Float32BE:\n        WRITEBYTES(f32, true, toFloat);\n    case NumberFormat::Float64LE:\n        WRITEBYTES(f64, false, toDouble);\n    case NumberFormat::Float64BE:\n        WRITEBYTES(f64, true, toDouble);\n    }\n}\n\nTNumber getNumberCore(uint8_t *buf, int szLeft, NumberFormat format) {\n    int8_t i8;\n    uint8_t u8;\n    int16_t i16;\n    uint16_t u16;\n    int32_t i32;\n    uint32_t u32;\n    float f32;\n    double f64;\n\n// Assume little endian\n#define READBYTES(isz, swap, conv)                                                                 \\\n    readBytes(buf, (uint8_t *)&isz, sizeof(isz), swap, szLeft);                                    \\\n    return conv(isz)\n\n    switch (format) {\n    case NumberFormat::Int8LE:\n        READBYTES(i8, false, fromInt);\n    case NumberFormat::UInt8LE:\n        READBYTES(u8, false, fromInt);\n    case NumberFormat::Int16LE:\n        READBYTES(i16, false, fromInt);\n    case NumberFormat::UInt16LE:\n        READBYTES(u16, false, fromInt);\n    case NumberFormat::Int32LE:\n        READBYTES(i32, false, fromInt);\n    case NumberFormat::UInt32LE:\n        READBYTES(u32, false, fromUInt);\n\n    case NumberFormat::Int8BE:\n        READBYTES(i8, true, fromInt);\n    case NumberFormat::UInt8BE:\n        READBYTES(u8, true, fromInt);\n    case NumberFormat::Int16BE:\n        READBYTES(i16, true, fromInt);\n    case NumberFormat::UInt16BE:\n        READBYTES(u16, true, fromInt);\n    case NumberFormat::Int32BE:\n        READBYTES(i32, true, fromInt);\n    case NumberFormat::UInt32BE:\n        READBYTES(u32, true, fromUInt);\n\n    case NumberFormat::Float32LE:\n        READBYTES(f32, false, fromFloat);\n    case NumberFormat::Float32BE:\n        READBYTES(f32, true, fromFloat);\n    case NumberFormat::Float64LE:\n        READBYTES(f64, false, fromDouble);\n    case NumberFormat::Float64BE:\n        READBYTES(f64, true, fromDouble);\n    }\n\n    return 0;\n}\n} // namespace pxt\n","buffer.ts":"namespace pins {\n    //% deprecated=1\n    export function sizeOf(format: NumberFormat) {\n        return Buffer.sizeOfNumberFormat(format)\n    }\n\n    //% deprecated=1\n    export function createBufferFromArray(bytes: number[]) {\n        return Buffer.fromArray(bytes)\n    }\n\n    //% deprecated=1\n    export function packedSize(format: string) {\n        return Buffer.packedSize(format)\n    }\n\n    //% deprecated=1\n    export function packBuffer(format: string, nums: number[]) {\n        return Buffer.pack(format, nums)\n    }\n\n    //% deprecated=1\n    export function packIntoBuffer(format: string, buf: Buffer, offset: number, nums: number[]) {\n        buf.packAt(offset, format, nums)\n    }\n\n    //% deprecated=1\n    export function unpackBuffer(format: string, buf: Buffer, offset = 0) {\n        return buf.unpack(format, offset)\n    }\n\n    //% deprecated=1\n    export function concatBuffers(bufs: Buffer[]) {\n        return Buffer.concat(bufs)\n    }\n}\n\n// see http://msgpack.org/ for the spec\n// it currently only implements numbers and their sequances\n// once we handle any type and typeof expressions we can do more\n\nnamespace msgpack {\n    function tagFormat(tag: number) {\n        switch (tag) {\n            case 0xCB: return NumberFormat.Float64BE\n            case 0xCC: return NumberFormat.UInt8BE\n            case 0xCD: return NumberFormat.UInt16BE\n            case 0xCE: return NumberFormat.UInt32BE\n            case 0xD0: return NumberFormat.Int8BE\n            case 0xD1: return NumberFormat.Int16BE\n            case 0xD2: return NumberFormat.Int32BE\n            default:\n                return null\n        }\n    }\n\n    function packNumberCore(buf: Buffer, offset: number, num: number) {\n        let tag = 0xCB\n        if (num == (num << 0) || num == (num >>> 0)) {\n            if (-31 <= num && num <= 127) {\n                if (buf) buf[offset] = num\n                return 1\n            } else if (0 <= num) {\n                if (num <= 0xff) {\n                    tag = 0xCC\n                } else if (num <= 0xffff) {\n                    tag = 0xCD\n                } else {\n                    tag = 0xCE\n                }\n            } else {\n                if (-0x7f <= num) {\n                    tag = 0xD0\n                } else if (-0x7fff <= num) {\n                    tag = 0xD1\n                } else {\n                    tag = 0xD2\n                }\n            }\n        }\n        let fmt = tagFormat(tag)\n        if (buf) {\n            buf[offset] = tag\n            buf.setNumber(fmt, offset + 1, num)\n        }\n        return pins.sizeOf(fmt) + 1\n    }\n\n    /**\n     * Unpacks a buffer into a number array.\n     */\n    export function unpackNumberArray(buf: Buffer, offset = 0): number[] {\n        let res: number[] = []\n\n        while (offset < buf.length) {\n            let fmt = tagFormat(buf[offset++])\n            if (fmt === null) {\n                let v = buf.getNumber(NumberFormat.Int8BE, offset - 1)\n                if (-31 <= v && v <= 127)\n                    res.push(v)\n                else\n                    return null\n            } else {\n                res.push(buf.getNumber(fmt, offset))\n                offset += pins.sizeOf(fmt)\n            }\n            // padding at the end\n            while (buf[offset] === 0xc1) offset++;\n        }\n\n        return res\n    }\n\n    /**\n     * Pack a number array into a buffer.\n     * @param nums the numbers to be packed\n     */\n    export function packNumberArray(nums: number[]): Buffer {\n        let off = 0\n        for (let n of nums) {\n            off += packNumberCore(null, off, n)\n        }\n        let buf = Buffer.create(off)\n        off = 0\n        for (let n of nums) {\n            off += packNumberCore(buf, off, n)\n        }\n        return buf\n    }\n}\n\nnamespace helpers {\n    export function bufferConcat(a: Buffer, b: Buffer) {\n        const r = Buffer.create(a.length + b.length)\n        r.write(0, a)\n        r.write(a.length, b)\n        return r\n    }\n\n    export function bufferEquals(l: Buffer, r: Buffer) {\n        if (!l || !r) return !!l == !!r;\n        if (l.length != r.length) return false;\n        for (let i = 0; i < l.length; ++i) {\n            if (l[i] != r[i])\n                return false;\n        }\n        return true;\n    }\n\n    export function bufferIndexOf(a: Buffer, b: Buffer) {\n        for (let i = 0; i <= a.length - b.length; ++i) {\n            if (a[i] == b[0]) {\n                let j = 0\n                while (j < b.length) {\n                    if (a[i + j] != b[j])\n                        break\n                    j++\n                }\n                if (j >= b.length)\n                    return i\n            }\n        }\n        return -1\n    }\n\n    export function bufferUnpack(buf: Buffer, format: string, offset?: number) {\n        if (!offset) offset = 0\n        let res: number[] = []\n        Buffer.__packUnpackCore(format, res, buf, false, offset)\n        return res\n    }\n\n    export function bufferPackAt(buf: Buffer, offset: number, format: string, nums: number[]) {\n        Buffer.__packUnpackCore(format, nums, buf, true, offset)\n    }\n\n    export function bufferChunked(buf: Buffer, maxBytes: number) {\n        if (buf.length <= maxBytes) return [buf]\n        else {\n            const r: Buffer[] = []\n            for (let i = 0; i < buf.length; i += maxBytes)\n                r.push(buf.slice(i, maxBytes))\n            return r\n        }\n    }\n\n    export function bufferToArray(buf: Buffer, format: NumberFormat) {\n        const sz = Buffer.sizeOfNumberFormat(format)\n        const len = buf.length - sz\n        const r: number[] = []\n        for (let i = 0; i <= len; i += sz)\n            r.push(buf.getNumber(format, i))\n        return r\n    }\n\n    export const _b64 = \"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/\"\n    export function bufferToBase64(buf: Buffer) {\n        const len = buf.length\n        let r = \"\"\n        for (let i = 0; i < len; i += 3) {\n            const x0 = buf[i]\n            r += _b64[x0 >> 2]\n            if (i + 1 >= len) {\n                r += _b64[(x0 & 3) << 4] + \"==\"\n            } else {\n                const x1 = buf[i + 1]\n                r += _b64[(x0 & 3) << 4 | (x1 >> 4)]\n                if (i + 2 >= len) {\n                    r += _b64[(x1 & 15) << 2] + \"=\"\n                } else {\n                    const x2 = buf[i + 2]\n                    r += _b64[(x1 & 15) << 2 | (x2 >> 6)]\n                    r += _b64[x2 & 63]\n                }\n            }\n        }\n        return r\n    }\n}\n\ninterface Buffer {\n    [index: number]: number;\n\n    /**\n     * Return concatenation of current buffer and the given buffer\n     */\n    //% helper=bufferConcat\n    concat(other: Buffer): Buffer;\n\n    /**\n     * Return position of other buffer in current buffer\n     */\n    //% helper=bufferIndexOf\n    indexOf(other: Buffer): number;\n\n    /**\n     * Reads numbers from the buffer according to the format\n     */\n    //% helper=bufferUnpack\n    unpack(format: string, offset?: number): number[];\n\n    /**\n     * Writes numbers to the buffer according to the format\n     */\n    //% helper=bufferPackAt\n    packAt(offset: number, format: string, nums: number[]): void;\n\n    /**\n     * Returns true if this and the other buffer hold the same data\n     */\n    //% helper=bufferEquals\n    equals(other: Buffer): boolean;\n\n    /**\n     * Splits buffer into parts no larger than specified\n     */\n    //% helper=bufferChunked\n    chunked(maxSize: number): Buffer[];\n\n    /**\n     * Read contents of buffer as an array in specified format\n     */\n    //% helper=bufferToArray\n    toArray(format: NumberFormat): number[];\n\n    /**\n     * Convert buffer to ASCII base64 encoding.\n     */\n    //% helper=bufferToBase64\n    toBase64(): string;\n\n    // rest defined in buffer.cpp\n}\n\nnamespace Buffer {\n    /**\n     * Allocate a new buffer.\n     * @param size number of bytes in the buffer\n     */\n    //% shim=control::createBuffer\n    export declare function create(size: number): Buffer;\n\n    /**\n     * Create a new buffer, decoding a hex string\n     */\n    export function fromHex(hex: string) {\n        const hexStr = \"0123456789abcdef\"\n        const res = Buffer.create(hex.length >> 1)\n        hex = hex.toLowerCase()\n        for (let i = 0; i < hex.length; i += 2) {\n            const p0 = hexStr.indexOf(hex.charAt(i))\n            const p1 = hexStr.indexOf(hex.charAt(i + 1))\n            if (p0 < 0 || p1 < 0)\n                throw \"Invalid hex\"\n            res[i >> 1] = (p0 << 4) | p1\n        }\n        return res\n    }\n\n    function b64Idx(c: string) {\n        if (c === undefined || c == \"=\") return -1\n\n        // handle base64url\n        if (c == \"-\") return 62\n        if (c == \"_\") return 63\n\n        const r = helpers._b64.indexOf(c)\n        if (r < 0)\n            throw \"Invalid Base64\"\n        return r\n    }\n\n    function fromBase64Core(trg: Buffer, b64: string) {\n        const len = b64.length\n        let dp = 0\n        for (let i = 0; i < len; i += 4) {\n            const x0 = b64Idx(b64[i])\n            const x1 = b64Idx(b64[i + 1])\n            const x2 = b64Idx(b64[i + 2])\n            const x3 = b64Idx(b64[i + 3])\n            if (x0 < 0 || x1 < 0) throw \"Invalid Base64\"\n            if (trg)\n                trg[dp] = (x0 << 2) | (x1 >> 4)\n            dp++\n            if (x2 >= 0) {\n                if (trg)\n                    trg[dp] = (x1 << 4) | (x2 >> 2)\n                dp++\n                if (x3 >= 0) {\n                    if (trg)\n                        trg[dp] = (x2 << 6) | x3\n                    dp++\n                }\n            } else {\n                if (x3 >= 0 || i + 4 < len)\n                    throw \"Invalid Base64\"\n            }\n        }\n        return dp\n    }\n\n    /**\n     * Create a new buffer, decoding a Base64 string\n     */\n    export function fromBase64(b64: string) {\n        const sz = fromBase64Core(null, b64)\n        const res = create(sz)\n        fromBase64Core(res, b64)\n        return res\n    }\n\n    /**\n     * Create a new buffer from an UTF8-encoded string\n     * @param str the string to put in the buffer\n     */\n    //% shim=control::createBufferFromUTF8\n    export declare function fromUTF8(str: string): Buffer;\n\n    function chunkLen(s: string, off: number, maxlen: number) {\n        let L = Math.idiv(maxlen, 3)\n        let R = maxlen\n\n        if (fromUTF8(s.slice(off, off + R)).length <= maxlen)\n            return R\n\n        while (L < R) {\n            const m = (L + R) >> 1\n            if (m == L)\n                break\n            const ll = fromUTF8(s.slice(off, off + m)).length\n            if (ll <= maxlen)\n                L = m\n            else\n                R = m\n        }\n\n        return L\n    }\n\n    export function chunkedFromUTF8(str: string, maxBytes: number) {\n        if (maxBytes < 3)\n            throw \"Oops\"\n        const chunks: Buffer[] = []\n        let pos = 0\n        while (pos < str.length) {\n            const len = chunkLen(str, pos, maxBytes)\n            chunks.push(fromUTF8(str.slice(pos, pos + len)))\n            pos += len\n        }\n        return chunks\n    }\n\n    /**\n     * Create a new buffer initialized to bytes from given array.\n     * @param bytes data to initialize with\n     */\n    export function fromArray(bytes: number[]) {\n        let buf = Buffer.create(bytes.length)\n        for (let i = 0; i < bytes.length; ++i)\n            buf[i] = bytes[i]\n        return buf\n    }\n\n    /**\n     * Concatenates all buffers in the list\n     */\n    export function concat(buffers: Buffer[]) {\n        let len = 0\n        for (let b of buffers)\n            len += b.length\n        const r = Buffer.create(len)\n        len = 0\n        for (let b of buffers) {\n            r.write(len, b)\n            len += b.length\n        }\n        return r\n    }\n\n    // Python-like packing, see https://docs.python.org/3/library/struct.html\n\n    export function packedSize(format: string) {\n        return __packUnpackCore(format, null, null, true)\n    }\n\n    export function pack(format: string, nums: number[]) {\n        let buf = Buffer.create(packedSize(format))\n        __packUnpackCore(format, nums, buf, true)\n        return buf\n    }\n\n    function getFormat(pychar: string, isBig: boolean) {\n        switch (pychar) {\n            case 'B':\n                return NumberFormat.UInt8LE\n            case 'b':\n                return NumberFormat.Int8LE\n            case 'H':\n                return isBig ? NumberFormat.UInt16BE : NumberFormat.UInt16LE\n            case 'h':\n                return isBig ? NumberFormat.Int16BE : NumberFormat.Int16LE\n            case 'I':\n            case 'L':\n                return isBig ? NumberFormat.UInt32BE : NumberFormat.UInt32LE\n            case 'i':\n            case 'l':\n                return isBig ? NumberFormat.Int32BE : NumberFormat.Int32LE\n            case 'f':\n                return isBig ? NumberFormat.Float32BE : NumberFormat.Float32LE\n            case 'd':\n                return isBig ? NumberFormat.Float64BE : NumberFormat.Float64LE\n            default:\n                return null as NumberFormat\n        }\n    }\n\n    function isDigit(ch: string) {\n        const code = ch.charCodeAt(0)\n        return 0x30 <= code && code <= 0x39\n    }\n\n    export function __packUnpackCore(format: string, nums: number[], buf: Buffer, isPack: boolean, off = 0) {\n        let isBig = false\n        let idx = 0\n        for (let i = 0; i < format.length; ++i) {\n            switch (format[i]) {\n                case ' ':\n                case '<':\n                case '=':\n                    isBig = false\n                    break\n                case '>':\n                case '!':\n                    isBig = true\n                    break\n                default:\n                    const i0 = i\n                    while (isDigit(format[i])) i++\n                    let reps = 1\n                    if (i0 != i)\n                        reps = parseInt(format.slice(i0, i))\n                    if (format[i] == 'x')\n                        off += reps\n                    else\n                        while (reps--) {\n                            let fmt = getFormat(format[i], isBig)\n                            if (fmt === null) {\n                                control.fail(\"Unsupported format character: \" + format[i])\n                            } else {\n                                if (buf) {\n                                    if (isPack)\n                                        buf.setNumber(fmt, off, nums[idx++])\n                                    else\n                                        nums.push(buf.getNumber(fmt, off))\n                                }\n\n                                off += sizeOfNumberFormat(fmt)\n                            }\n                        }\n                    break\n            }\n        }\n        return off\n    }\n\n    /**\n     * Get the size in bytes of specified number format.\n     */\n    export function sizeOfNumberFormat(format: NumberFormat) {\n        switch (format) {\n            case NumberFormat.Int8LE:\n            case NumberFormat.UInt8LE:\n            case NumberFormat.Int8BE:\n            case NumberFormat.UInt8BE:\n                return 1;\n            case NumberFormat.Int16LE:\n            case NumberFormat.UInt16LE:\n            case NumberFormat.Int16BE:\n            case NumberFormat.UInt16BE:\n                return 2;\n            case NumberFormat.Int32LE:\n            case NumberFormat.Int32BE:\n            case NumberFormat.UInt32BE:\n            case NumberFormat.UInt32LE:\n            case NumberFormat.Float32BE:\n            case NumberFormat.Float32LE:\n                return 4;\n            case NumberFormat.Float64BE:\n            case NumberFormat.Float64LE:\n                return 8;\n        }\n        return 0;\n    }\n}\n","codal.cpp":"#include \"pxt.h\"\n#include <stdarg.h>\n\nPXT_ABI(__aeabi_dadd)\nPXT_ABI(__aeabi_dcmplt)\nPXT_ABI(__aeabi_dcmpgt)\nPXT_ABI(__aeabi_dsub)\nPXT_ABI(__aeabi_ddiv)\nPXT_ABI(__aeabi_dmul)\n\n#if MICROBIT_CODAL\nnamespace codal {\nint list_fibers(Fiber **dest) {\n    int i = 0;\n    for (Fiber *fib = codal::get_fiber_list(); fib; fib = fib->next) {\n        if (dest)\n            dest[i] = fib;\n        i++;\n    }\n    return i;\n}\n\n} // namespace codal\n#endif\n\nextern \"C\" void target_panic(int error_code) {\n#if MICROBIT_CODAL\n    target_disable_irq();\n    DMESG(\"PANIC %d\", error_code);\n    pxt::dumpDmesg();\n#else\n    // wait for serial to flush\n    sleep_us(300000);\n#endif\n    microbit_panic(error_code);\n}\n\n#if !MICROBIT_CODAL\nextern \"C\" void target_reset() {\n    microbit_reset();\n}\n#endif\n\nuint32_t device_heap_size(uint8_t heap_index); // defined in microbit-dal\n\nnamespace pxt {\n\nMicroBit uBit;\nMicroBitEvent lastEvent;\nbool serialLoggingDisabled;\n\nvoid platform_init() {\n    int seed = microbit_random(0x7fffffff);\n    DMESG(\"random seed: %d\", seed);\n    seedRandom(seed);\n}\n\nvoid initMicrobitGC() {\n    uBit.init();\n    if (device_heap_size(1) > NON_GC_HEAP_RESERVATION + 4)\n        gcPreAllocateBlock(device_heap_size(1) - NON_GC_HEAP_RESERVATION);\n}\n\nvoid platform_init();\nvoid usb_init();\n\nstruct FreeList {\n    FreeList *next;\n};\n\nvoid dispatchForeground(MicroBitEvent e, void *action) {\n    lastEvent = e;\n    auto value = fromInt(e.value);\n    runAction1((Action)action, value);\n}\n\nvoid deleteListener(MicroBitListener *l) {\n    if (l->cb_param == (void (*)(MicroBitEvent, void *))dispatchForeground) {\n        decr((Action)(l->cb_arg));\n        unregisterGCPtr((Action)(l->cb_arg));\n    }\n}\n\nstatic void initCodal() {\n    // TODO!!!\n#ifndef MICROBIT_CODAL\n    uBit.messageBus.setListenerDeletionCallback(deleteListener);\n#endif\n\n    // repeat error 4 times and restart as needed\n    microbit_panic_timeout(4);\n}\n\n// ---------------------------------------------------------------------------\n// An adapter for the API expected by the run-time.\n// ---------------------------------------------------------------------------\n\nvoid registerWithDal(int id, int event, Action a, int flags) {\n    uBit.messageBus.ignore(id, event, dispatchForeground);\n    uBit.messageBus.listen(id, event, dispatchForeground, a, (uint16_t) flags);\n    incr(a);\n    registerGCPtr(a);\n}\n\nvoid fiberDone(void *a) {\n    decr((Action)a);\n    unregisterGCPtr((Action)a);\n    release_fiber();\n}\n\nvoid releaseFiber() {\n    release_fiber();\n}\n\nvoid sleep_ms(unsigned ms) {\n    fiber_sleep(ms);\n}\n\nvoid sleep_us(uint64_t us) {\n#if MICROBIT_CODAL\n    target_wait_us(us);\n#else\n    wait_us(us);\n#endif\n}\n\nvoid forever_stub(void *a) {\n    while (true) {\n        runAction0((Action)a);\n        fiber_sleep(20);\n    }\n}\n\nvoid runForever(Action a) {\n    if (a != 0) {\n        incr(a);\n        registerGCPtr(a);\n        create_fiber(forever_stub, (void *)a);\n    }\n}\n\nvoid runInParallel(Action a) {\n    if (a != 0) {\n        incr(a);\n        registerGCPtr(a);\n        create_fiber((void (*)(void *))runAction0, (void *)a, fiberDone);\n    }\n}\n\nvoid waitForEvent(int id, int event) {\n    fiber_wait_for_event(id, event);\n}\n\nvoid initRuntime() {\n    initCodal();\n    platform_init();\n}\n\n//%\nunsigned afterProgramPage() {\n    unsigned ptr = (unsigned)&bytecode[0];\n    ptr += programSize();\n    ptr = (ptr + (PAGE_SIZE - 1)) & ~(PAGE_SIZE - 1);\n    return ptr;\n}\n\nint current_time_ms() {\n    return system_timer_current_time();\n}\n\nstatic void logwriten(const char *msg, int l) {\n    if (!serialLoggingDisabled)\n        uBit.serial.send((uint8_t *)msg, l);\n}\n\nstatic void logwrite(const char *msg) {\n    logwriten(msg, strlen(msg));\n}\n\nstatic void writeNum(char *buf, uint32_t n, bool full) {\n    int i = 0;\n    int sh = 28;\n    while (sh >= 0) {\n        int d = (n >> sh) & 0xf;\n        if (full || d || sh == 0 || i) {\n            buf[i++] = d > 9 ? 'A' + d - 10 : '0' + d;\n        }\n        sh -= 4;\n    }\n    buf[i] = 0;\n}\n\nstatic void logwritenum(uint32_t n, bool full, bool hex) {\n    char buff[20];\n\n    if (hex) {\n        writeNum(buff, n, full);\n        logwrite(\"0x\");\n    } else {\n        itoa(n, buff);\n    }\n\n    logwrite(buff);\n}\n\nvoid vdebuglog(const char *format, va_list ap) {\n    const char *end = format;\n\n    while (*end) {\n        if (*end++ == '%') {\n            logwriten(format, end - format - 1);\n            uint32_t val = va_arg(ap, uint32_t);\n            switch (*end++) {\n            case 'c':\n                logwriten((const char *)&val, 1);\n                break;\n            case 'd':\n                logwritenum(val, false, false);\n                break;\n            case 'x':\n                logwritenum(val, false, true);\n                break;\n            case 'p':\n            case 'X':\n                logwritenum(val, true, true);\n                break;\n            case 's':\n                logwrite((char *)(void *)val);\n                break;\n            case '%':\n                logwrite(\"%\");\n                break;\n            default:\n                logwrite(\"???\");\n                break;\n            }\n            format = end;\n        }\n    }\n    logwriten(format, end - format);\n    logwrite(\"\\n\");\n}\n\nvoid debuglog(const char *format, ...) {\n    va_list arg;\n    va_start(arg, format);\n    vdebuglog(format, arg);\n    va_end(arg);\n}\n\nvoid sendSerial(const char *data, int len) {\n    logwriten(data, len);\n}\n\nThreadContext *getThreadContext() {\n    if (!currentFiber)\n        return NULL;\n    return (ThreadContext *)currentFiber->user_data;\n}\n\nvoid setThreadContext(ThreadContext *ctx) {\n    currentFiber->user_data = ctx;\n}\n\n#if !MICROBIT_CODAL\n#define tcb_get_stack_base(tcb) (tcb).stack_base\n#endif\n\nstatic void *threadAddressFor(Fiber *fib, void *sp) {\n    if (fib == currentFiber)\n        return sp;\n\n    return (uint8_t *)sp + ((uint8_t *)fib->stack_top - (uint8_t *)tcb_get_stack_base(fib->tcb));\n}\n\nvoid gcProcessStacks(int flags) {\n    // check scheduler is initialized\n    if (!currentFiber) {\n        // make sure we allocate something to at least initalize the memory allocator\n        void *volatile p = xmalloc(1);\n        xfree(p);\n        return;\n    }\n\n#ifdef MICROBIT_GET_FIBER_LIST_SUPPORTED\n    for (Fiber *fib = get_fiber_list(); fib; fib = fib->next) {\n        auto ctx = (ThreadContext *)fib->user_data;\n        if (!ctx)\n            continue;\n        for (auto seg = &ctx->stack; seg; seg = seg->next) {\n            auto ptr = (TValue *)threadAddressFor(fib, seg->top);\n            auto end = (TValue *)threadAddressFor(fib, seg->bottom);\n            if (flags & 2)\n                DMESG(\"RS%d:%p/%d\", cnt++, ptr, end - ptr);\n            // VLOG(\"mark: %p - %p\", ptr, end);\n            while (ptr < end) {\n                gcProcess(*ptr++);\n            }\n        }\n    }\n#else\n    int numFibers = list_fibers(NULL);\n    Fiber **fibers = (Fiber **)xmalloc(sizeof(Fiber *) * numFibers);\n    int num2 = list_fibers(fibers);\n    if (numFibers != num2)\n        oops(12);\n    int cnt = 0;\n\n    for (int i = 0; i < numFibers; ++i) {\n        auto fib = fibers[i];\n        auto ctx = (ThreadContext *)fib->user_data;\n        if (!ctx)\n            continue;\n        for (auto seg = &ctx->stack; seg; seg = seg->next) {\n            auto ptr = (TValue *)threadAddressFor(fib, seg->top);\n            auto end = (TValue *)threadAddressFor(fib, seg->bottom);\n            if (flags & 2) {\n                DMESG(\"RS%d:%p/%d\", cnt, ptr, end - ptr);\n                cnt++;\n            }\n            // VLOG(\"mark: %p - %p\", ptr, end);\n            while (ptr < end) {\n                gcProcess(*ptr++);\n            }\n        }\n    }\n    xfree(fibers);\n#endif\n}\n\n} // namespace pxt\n","configkeys.h":"#ifndef __PXT_CONFIGKEYS_H\n#define __PXT_CONFIGKEYS_H\n\n// used by pins.cpp to mask off the pin name from any config\n// lower 16 pins of value are the pin name\n#define CFG_PIN_NAME_MSK 0x0000ffff\n// upper 16 bits of value is any configuration of the pin.\n#define CFG_PIN_CONFIG_MSK 0xffff0000\n\n// begin optional pin configurations\n#define CFG_PIN_CONFIG_ACTIVE_LO 0x10000\n\n\n#define CFG_MAGIC0 0x1e9e10f1\n#define CFG_MAGIC1 0x20227a79\n\n// these define keys for getConfig() function\n#define CFG_PIN_ACCELEROMETER_INT 1\n#define CFG_PIN_ACCELEROMETER_SCL 2\n#define CFG_PIN_ACCELEROMETER_SDA 3\n#define CFG_PIN_BTN_A 4\n#define CFG_PIN_BTN_B 5\n#define CFG_PIN_BTN_SLIDE 6\n#define CFG_PIN_DOTSTAR_CLOCK 7\n#define CFG_PIN_DOTSTAR_DATA 8\n#define CFG_PIN_FLASH_CS 9\n#define CFG_PIN_FLASH_MISO 10\n#define CFG_PIN_FLASH_MOSI 11\n#define CFG_PIN_FLASH_SCK 12\n#define CFG_PIN_LED 13\n#define CFG_PIN_LIGHT 14\n#define CFG_PIN_MICROPHONE 15\n#define CFG_PIN_MIC_CLOCK 16\n#define CFG_PIN_MIC_DATA 17\n#define CFG_PIN_MISO 18\n#define CFG_PIN_MOSI 19\n// the preferred pin to drive an external neopixel strip\n#define CFG_PIN_NEOPIXEL 20\n#define CFG_PIN_RX 21\n#define CFG_PIN_RXLED 22\n#define CFG_PIN_SCK 23\n#define CFG_PIN_SCL 24\n#define CFG_PIN_SDA 25\n#define CFG_PIN_SPEAKER_AMP 26\n#define CFG_PIN_TEMPERATURE 27\n#define CFG_PIN_TX 28\n#define CFG_PIN_TXLED 29\n#define CFG_PIN_IR_OUT 30\n#define CFG_PIN_IR_IN 31\n#define CFG_PIN_DISPLAY_SCK 32\n#define CFG_PIN_DISPLAY_MISO 33\n#define CFG_PIN_DISPLAY_MOSI 34\n#define CFG_PIN_DISPLAY_CS 35\n#define CFG_PIN_DISPLAY_DC 36\n#define CFG_DISPLAY_WIDTH 37\n#define CFG_DISPLAY_HEIGHT 38\n#define CFG_DISPLAY_CFG0 39\n#define CFG_DISPLAY_CFG1 40\n#define CFG_DISPLAY_CFG2 41\n#define CFG_DISPLAY_CFG3 42\n#define CFG_PIN_DISPLAY_RST 43\n#define CFG_PIN_DISPLAY_BL 44\n#define CFG_PIN_SERVO_1 45\n#define CFG_PIN_SERVO_2 46\n#define CFG_PIN_BTN_LEFT 47\n#define CFG_PIN_BTN_RIGHT 48\n#define CFG_PIN_BTN_UP 49\n#define CFG_PIN_BTN_DOWN 50\n#define CFG_PIN_BTN_MENU 51\n#define CFG_PIN_LED_R 52\n#define CFG_PIN_LED_G 53\n#define CFG_PIN_LED_B 54\n#define CFG_PIN_LED1 55\n#define CFG_PIN_LED2 56\n#define CFG_PIN_LED3 57\n#define CFG_PIN_LED4 58\n#define CFG_SPEAKER_VOLUME 59\n\n#define CFG_PIN_JACK_TX 60\n#define CFG_PIN_JACK_SENSE 61\n#define CFG_PIN_JACK_HPEN 62\n#define CFG_PIN_JACK_BZEN 63\n#define CFG_PIN_JACK_PWREN 64\n#define CFG_PIN_JACK_SND 65\n#define CFG_PIN_JACK_BUSLED 66\n#define CFG_PIN_JACK_COMMLED 67\n\n#define CFG_PIN_BTN_SOFT_RESET 69\n#define CFG_ACCELEROMETER_TYPE 70\n#define CFG_PIN_BTNMX_LATCH 71\n#define CFG_PIN_BTNMX_CLOCK 72\n#define CFG_PIN_BTNMX_DATA 73\n#define CFG_PIN_BTN_MENU2 74\n#define CFG_PIN_BATTSENSE 75\n#define CFG_PIN_VIBRATION 76\n#define CFG_PIN_PWREN 77\n#define CFG_DISPLAY_TYPE 78\n\n#define CFG_PIN_ROTARY_ENCODER_A 79\n#define CFG_PIN_ROTARY_ENCODER_B 80\n\n#define CFG_ACCELEROMETER_SPACE 81\n\n#define CFG_PIN_WIFI_MOSI 82\n#define CFG_PIN_WIFI_MISO 83\n#define CFG_PIN_WIFI_SCK 84\n#define CFG_PIN_WIFI_TX 85\n#define CFG_PIN_WIFI_RX 86\n#define CFG_PIN_WIFI_CS 87\n#define CFG_PIN_WIFI_BUSY 88\n#define CFG_PIN_WIFI_RESET 89\n#define CFG_PIN_WIFI_GPIO0 90\n#define CFG_PIN_WIFI_AT_TX 91\n#define CFG_PIN_WIFI_AT_RX 92\n\n#define CFG_PIN_USB_POWER 93\n#define CFG_DISPLAY_DELAY 94\n#define CFG_SETTINGS_SIZE_DEFL 95\n#define CFG_SETTINGS_SIZE 96\n\n// default I2C address\n#define ACCELEROMETER_TYPE_LIS3DH 0x32\n#define ACCELEROMETER_TYPE_LIS3DH_ALT 0x30\n#define ACCELEROMETER_TYPE_MMA8453 0x38\n#define ACCELEROMETER_TYPE_FXOS8700 0x3C\n#define ACCELEROMETER_TYPE_MMA8653 0x3A\n#define ACCELEROMETER_TYPE_MSA300 0x4C\n#define ACCELEROMETER_TYPE_MPU6050 0x68\n\n#define DISPLAY_TYPE_ST7735 7735\n#define DISPLAY_TYPE_ILI9341 9341\n#define DISPLAY_TYPE_SMART 4242\n\n#define CFG_PIN_A0 100\n#define CFG_PIN_A1 101\n#define CFG_PIN_A2 102\n#define CFG_PIN_A3 103\n#define CFG_PIN_A4 104\n#define CFG_PIN_A5 105\n#define CFG_PIN_A6 106\n#define CFG_PIN_A7 107\n#define CFG_PIN_A8 108\n#define CFG_PIN_A9 109\n#define CFG_PIN_A10 110\n#define CFG_PIN_A11 111\n#define CFG_PIN_A12 112\n#define CFG_PIN_A13 113\n#define CFG_PIN_A14 114\n#define CFG_PIN_A15 115\n#define CFG_PIN_A16 116\n#define CFG_PIN_A17 117\n#define CFG_PIN_A18 118\n#define CFG_PIN_A19 119\n#define CFG_PIN_A20 120\n#define CFG_PIN_A21 121\n#define CFG_PIN_A22 122\n#define CFG_PIN_A23 123\n#define CFG_PIN_A24 124\n#define CFG_PIN_A25 125\n#define CFG_PIN_A26 126\n#define CFG_PIN_A27 127\n#define CFG_PIN_A28 128\n#define CFG_PIN_A29 129\n#define CFG_PIN_A30 130\n#define CFG_PIN_A31 131\n\n#define CFG_PIN_D0 150\n#define CFG_PIN_D1 151\n#define CFG_PIN_D2 152\n#define CFG_PIN_D3 153\n#define CFG_PIN_D4 154\n#define CFG_PIN_D5 155\n#define CFG_PIN_D6 156\n#define CFG_PIN_D7 157\n#define CFG_PIN_D8 158\n#define CFG_PIN_D9 159\n#define CFG_PIN_D10 160\n#define CFG_PIN_D11 161\n#define CFG_PIN_D12 162\n#define CFG_PIN_D13 163\n#define CFG_PIN_D14 164\n#define CFG_PIN_D15 165\n#define CFG_PIN_D16 166\n#define CFG_PIN_D17 167\n#define CFG_PIN_D18 168\n#define CFG_PIN_D19 169\n#define CFG_PIN_D20 170\n#define CFG_PIN_D21 171\n#define CFG_PIN_D22 172\n#define CFG_PIN_D23 173\n#define CFG_PIN_D24 174\n#define CFG_PIN_D25 175\n#define CFG_PIN_D26 176\n#define CFG_PIN_D27 177\n#define CFG_PIN_D28 178\n#define CFG_PIN_D29 179\n#define CFG_PIN_D30 180\n#define CFG_PIN_D31 181\n\n#define CFG_NUM_NEOPIXELS 200\n#define CFG_NUM_DOTSTARS 201\n#define CFG_DEFAULT_BUTTON_MODE 202\n#define CFG_SWD_ENABLED 203\n#define CFG_FLASH_BYTES 204\n#define CFG_RAM_BYTES 205\n#define CFG_SYSTEM_HEAP_BYTES 206\n#define CFG_LOW_MEM_SIMULATION_KB 207\n#define CFG_BOOTLOADER_BOARD_ID 208\n#define CFG_UF2_FAMILY 209\n#define CFG_PINS_PORT_SIZE 210\n#define CFG_BOOTLOADER_PROTECTION 211\n#define CFG_POWER_DEEPSLEEP_TIMEOUT 212\n#define CFG_ANALOG_BUTTON_THRESHOLD 213\n#define CFG_CPU_MHZ 214\n#define CFG_CONTROLLER_LIGHT_MAX_BRIGHTNESS 215\n#define CFG_ANALOG_JOYSTICK_MIN 216\n#define CFG_ANALOG_JOYSTICK_MAX 217\n#define CFG_TIMERS_TO_USE 218\n// configs to specify the onboard (built-in) dotstar or neopixel strips\n// some boards have a combination of dotstar, neopixel strips like neotrellis\n#define CFG_PIN_ONBOARD_DOTSTAR_CLOCK 219\n#define CFG_PIN_ONBOARD_DOTSTAR_DATA 220\n#define CFG_NUM_ONBOARD_DOTSTARS 221\n#define CFG_PIN_ONBOARD_NEOPIXEL 222\n#define CFG_NUM_ONBOARD_NEOPIXELS 223\n\n#define CFG_MATRIX_KEYPAD_MESSAGE_ID 239\n#define CFG_NUM_MATRIX_KEYPAD_ROWS 240\n#define CFG_PIN_MATRIX_KEYPAD_ROW0 241\n#define CFG_PIN_MATRIX_KEYPAD_ROW1 242\n#define CFG_PIN_MATRIX_KEYPAD_ROW2 243\n#define CFG_PIN_MATRIX_KEYPAD_ROW3 244\n#define CFG_PIN_MATRIX_KEYPAD_ROW4 245\n#define CFG_PIN_MATRIX_KEYPAD_ROW5 246\n#define CFG_PIN_MATRIX_KEYPAD_ROW6 247\n#define CFG_PIN_MATRIX_KEYPAD_ROW7 248\n#define CFG_NUM_MATRIX_KEYPAD_COLS 250\n#define CFG_PIN_MATRIX_KEYPAD_COL0 251\n#define CFG_PIN_MATRIX_KEYPAD_COL1 252\n#define CFG_PIN_MATRIX_KEYPAD_COL2 253\n#define CFG_PIN_MATRIX_KEYPAD_COL3 254\n#define CFG_PIN_MATRIX_KEYPAD_COL4 255\n#define CFG_PIN_MATRIX_KEYPAD_COL5 256\n#define CFG_PIN_MATRIX_KEYPAD_COL6 257\n#define CFG_PIN_MATRIX_KEYPAD_COL7 258\n\n#define CFG_PIN_B0 300\n#define CFG_PIN_B1 301\n#define CFG_PIN_B2 302\n#define CFG_PIN_B3 303\n#define CFG_PIN_B4 304\n#define CFG_PIN_B5 305\n#define CFG_PIN_B6 306\n#define CFG_PIN_B7 307\n#define CFG_PIN_B8 308\n#define CFG_PIN_B9 309\n#define CFG_PIN_B10 310\n#define CFG_PIN_B11 311\n#define CFG_PIN_B12 312\n#define CFG_PIN_B13 313\n#define CFG_PIN_B14 314\n#define CFG_PIN_B15 315\n#define CFG_PIN_B16 316\n#define CFG_PIN_B17 317\n#define CFG_PIN_B18 318\n#define CFG_PIN_B19 319\n#define CFG_PIN_B20 320\n#define CFG_PIN_B21 321\n#define CFG_PIN_B22 322\n#define CFG_PIN_B23 323\n#define CFG_PIN_B24 324\n#define CFG_PIN_B25 325\n#define CFG_PIN_B26 326\n#define CFG_PIN_B27 327\n#define CFG_PIN_B28 328\n#define CFG_PIN_B29 329\n#define CFG_PIN_B30 330\n#define CFG_PIN_B31 331\n\n#define CFG_PIN_C0 350\n#define CFG_PIN_C1 351\n#define CFG_PIN_C2 352\n#define CFG_PIN_C3 353\n#define CFG_PIN_C4 354\n#define CFG_PIN_C5 355\n#define CFG_PIN_C6 356\n#define CFG_PIN_C7 357\n#define CFG_PIN_C8 358\n#define CFG_PIN_C9 359\n#define CFG_PIN_C10 360\n#define CFG_PIN_C11 361\n#define CFG_PIN_C12 362\n#define CFG_PIN_C13 363\n#define CFG_PIN_C14 364\n#define CFG_PIN_C15 365\n#define CFG_PIN_C16 366\n#define CFG_PIN_C17 367\n#define CFG_PIN_C18 368\n#define CFG_PIN_C19 369\n#define CFG_PIN_C20 370\n#define CFG_PIN_C21 371\n#define CFG_PIN_C22 372\n#define CFG_PIN_C23 373\n#define CFG_PIN_C24 374\n#define CFG_PIN_C25 375\n#define CFG_PIN_C26 376\n#define CFG_PIN_C27 377\n#define CFG_PIN_C28 378\n#define CFG_PIN_C29 379\n#define CFG_PIN_C30 380\n#define CFG_PIN_C31 381\n\n#define CFG_PIN_P0 400\n#define CFG_PIN_P1 401\n#define CFG_PIN_P2 402\n#define CFG_PIN_P3 403\n#define CFG_PIN_P4 404\n#define CFG_PIN_P5 405\n#define CFG_PIN_P6 406\n#define CFG_PIN_P7 407\n#define CFG_PIN_P8 408\n#define CFG_PIN_P9 409\n#define CFG_PIN_P10 410\n#define CFG_PIN_P11 411\n#define CFG_PIN_P12 412\n#define CFG_PIN_P13 413\n#define CFG_PIN_P14 414\n#define CFG_PIN_P15 415\n#define CFG_PIN_P16 416\n#define CFG_PIN_P17 417\n#define CFG_PIN_P18 418\n#define CFG_PIN_P19 419\n#define CFG_PIN_P20 420\n#define CFG_PIN_P21 421\n#define CFG_PIN_P22 422\n#define CFG_PIN_P23 423\n#define CFG_PIN_P24 424\n#define CFG_PIN_P25 425\n#define CFG_PIN_P26 426\n#define CFG_PIN_P27 427\n#define CFG_PIN_P28 428\n#define CFG_PIN_P29 429\n#define CFG_PIN_P30 430\n#define CFG_PIN_P31 431\n#define CFG_PIN_P32 432\n#define CFG_PIN_P33 433\n#define CFG_PIN_P34 434\n#define CFG_PIN_P35 435\n#define CFG_PIN_P36 436\n#define CFG_PIN_P37 437\n#define CFG_PIN_P38 438\n#define CFG_PIN_P39 439\n#define CFG_PIN_P40 440\n#define CFG_PIN_P41 441\n#define CFG_PIN_P42 442\n#define CFG_PIN_P43 443\n#define CFG_PIN_P44 444\n#define CFG_PIN_P45 445\n#define CFG_PIN_P46 446\n#define CFG_PIN_P47 447\n#define CFG_PIN_P48 448\n#define CFG_PIN_P49 449\n#define CFG_PIN_P50 450\n#define CFG_PIN_P51 451\n#define CFG_PIN_P52 452\n#define CFG_PIN_P53 453\n#define CFG_PIN_P54 454\n#define CFG_PIN_P55 455\n#define CFG_PIN_P56 456\n#define CFG_PIN_P57 457\n#define CFG_PIN_P58 458\n#define CFG_PIN_P59 459\n#define CFG_PIN_P60 460\n#define CFG_PIN_P61 461\n#define CFG_PIN_P62 462\n#define CFG_PIN_P63 463\n\n#define CFG_PIN_LORA_MISO 1001\n#define CFG_PIN_LORA_MOSI 1002\n#define CFG_PIN_LORA_SCK 1003\n#define CFG_PIN_LORA_CS 1004\n#define CFG_PIN_LORA_BOOT 1005\n#define CFG_PIN_LORA_RESET 1006\n#define CFG_PIN_IRRXLED 1007\n#define CFG_PIN_IRTXLED 1008\n#define CFG_PIN_LCD_RESET 1009\n#define CFG_PIN_LCD_ENABLE 1010\n#define CFG_PIN_LCD_DATALINE4 1011\n#define CFG_PIN_LCD_DATALINE5 1012\n#define CFG_PIN_LCD_DATALINE6 1013\n#define CFG_PIN_LCD_DATALINE7 1014\n#define CFG_NUM_LCD_COLUMNS 1015\n#define CFG_NUM_LCD_ROWS 1016\n\n//RoboHAT MM1 pinout\n#define CFG_PIN_RCC0 1017\n#define CFG_PIN_RCC1 1018\n#define CFG_PIN_RCC2 1019\n#define CFG_PIN_RCC3 1020\n#define CFG_PIN_RCC4 1021\n#define CFG_PIN_RCC5 1022\n#define CFG_PIN_RCC6 1023\n#define CFG_PIN_RCC7 1024\n#define CFG_PIN_SERVO0 1025\n#define CFG_PIN_SERVO1 1026\n#define CFG_PIN_SERVO2 1027\n#define CFG_PIN_SERVO3 1028\n#define CFG_PIN_SERVO4 1029\n#define CFG_PIN_SERVO5 1030\n#define CFG_PIN_SERVO6 1031\n#define CFG_PIN_SERVO7 1032\n#define CFG_PIN_SERVO8 1033\n#define CFG_PIN_PI_TX 1034\n#define CFG_PIN_PI_RX 1035\n#define CFG_PIN_GPS_SDA 1036\n#define CFG_PIN_GPS_SCL 1037\n#define CFG_PIN_GPS_TX 1038\n#define CFG_PIN_GPS_RX 1039\n#define CFG_PIN_GROVE0 1040\n#define CFG_PIN_GROVE1 1041\n#define CFG_PIN_SS 1042\n\n// Adafruit Grand Central M4\n#define CFG_PIN_D33 183\n#define CFG_PIN_D34 184\n#define CFG_PIN_D35 185\n#define CFG_PIN_D36 186\n#define CFG_PIN_D37 187\n#define CFG_PIN_D38 188\n#define CFG_PIN_D39 189\n#define CFG_PIN_D40 190\n#define CFG_PIN_D41 191\n#define CFG_PIN_D42 192\n#define CFG_PIN_D43 193\n#define CFG_PIN_D44 194\n#define CFG_PIN_D45 195\n#define CFG_PIN_D46 196\n#define CFG_PIN_D47 197\n#define CFG_PIN_D48 198\n#define CFG_PIN_D49 199\n#define CFG_PIN_D50 259\n#define CFG_PIN_D51 260\n#define CFG_PIN_D52 261\n#define CFG_PIN_D53 262\n\n#define CFG_PIN_TX1 263\n#define CFG_PIN_TX2 264\n#define CFG_PIN_TX3 265\n#define CFG_PIN_RX1 266\n#define CFG_PIN_RX2 267\n#define CFG_PIN_RX3 268\n#define CFG_PIN_SCL1 269\n#define CFG_PIN_SDA1 270\n#define CFG_PIN_PCC_D0 271\n#define CFG_PIN_PCC_D1 272\n#define CFG_PIN_PCC_D2 273\n#define CFG_PIN_PCC_D3 274\n#define CFG_PIN_PCC_D4 275\n#define CFG_PIN_PCC_D5 276\n#define CFG_PIN_PCC_D6 277\n#define CFG_PIN_PCC_D7 278\n#define CFG_PIN_PCC_D8 279\n#define CFG_PIN_PCC_D9 280\n#define CFG_PIN_PCC_D10 281\n#define CFG_PIN_PCC_D11 282\n#define CFG_PIN_PCC_D12 283\n#define CFG_PIN_PCC_D13 284\n#define CFG_PIN_CC_DEN1 285\n#define CFG_PIN_CC_DEN2 286\n#define CFG_PIN_CC_CLK 287\n#define CFG_PIN_XCC_CLK 288\n\n\n#define CFG_PIN_JDPWR_PRE_SENSE 1100\n#define CFG_PIN_JDPWR_GND_SENSE 1101\n#define CFG_PIN_JDPWR_PULSE 1102\n#define CFG_PIN_JDPWR_OVERLOAD_LED 1103\n#define CFG_PIN_JDPWR_ENABLE 1104\n#define CFG_PIN_JDPWR_FAULT 1105\n\n#define CFG_USER_CFG_0 2000\n#define CFG_USER_CFG_1 2001\n#define CFG_USER_CFG_2 2002\n#define CFG_USER_CFG_3 2003\n#define CFG_USER_CFG_4 2004\n#define CFG_USER_CFG_5 2005\n#define CFG_USER_CFG_6 2006\n#define CFG_USER_CFG_7 2007\n#define CFG_USER_CFG_8 2008\n#define CFG_USER_CFG_9 2009\n\n#define CFG_ARCADE_CFG_0 2100\n#define CFG_ARCADE_CFG_1 2101\n#define CFG_ARCADE_SCREEN_WIDTH 2102\n#define CFG_ARCADE_SCREEN_HEIGHT 2103\n\n#endif\n","console.ts":"/// <reference no-default-lib=\"true\"/>\n\nenum ConsolePriority {\n    Debug = 0,\n    Log = 1,\n    Warning = 2,\n    Error = 3,\n    Silent = 4\n}\n\n/**\n * Reading and writing data to the console output.\n */\n//% weight=12 color=#002050 icon=\"\\uf120\"\n//% advanced=true\nnamespace console {\n    type Listener = (priority: ConsolePriority, text: string) => void;\n\n    /**\n     * Minimum priority to send messages to listeners\n     */\n    export let minPriority = ConsolePriority.Log;\n\n    let listeners: Listener[]\n\n    export function add(priority: ConsolePriority, message: any) {\n        if (priority < minPriority) return;\n        let text = inspect(message);\n        // add new line\n        text += \"\\n\";\n        control.__log(priority, text)\n        // send to listeners\n        if (listeners)\n            for (let i = 0; i < listeners.length; ++i)\n                listeners[i](priority, text);\n    }\n\n    export function debug(text: any) {\n        add(ConsolePriority.Debug, text);\n    }\n\n    export function warn(text: any) {\n        add(ConsolePriority.Warning, text);\n    }\n\n    export function error(text: any) {\n        add(ConsolePriority.Error, text);\n    }\n\n    /**\n     * Write a line of text to the console output.\n     * @param value to send\n     */\n    //% weight=90\n    //% help=console/log blockGap=8\n    export function log(value: any): void {\n        add(ConsolePriority.Log, value);\n    }\n\n    /**\n     * Write a name:value pair as a line of text to the console output.\n     * @param name name of the value stream, eg: \"x\"\n     * @param value to write\n     */\n    //% weight=88 blockGap=8\n    //% help=console/log-value\n    export function logValue(name: any, value: any): void {\n        log(name ? `${inspect(name)}: ${inspect(value)}` : `${inspect(value)}`)\n    }\n\n    /**\n     * Convert any object or value to a string representation\n     * @param obj value to be converted to a string\n     * @param maxElements [optional] max number values in an object to include in output\n     */\n    export function inspect(obj: any, maxElements = 20): string {\n        if (typeof obj == \"string\") {\n            return obj;\n        } else if (typeof obj == \"number\") {\n            return \"\" + obj;\n        } else if (Array.isArray(obj)) {\n            const asArr = (obj as Array<string>);\n            if (asArr.length <= maxElements) {\n                return asArr.join(\",\");\n            } else {\n                return `${asArr.slice(0, maxElements).join(\",\")}...`;\n            }\n        } else {\n            const asString = obj + \"\";\n            if (asString != \"[object Object]\"\n                && asString != \"[Object]\") { // on arcade at least, default toString is [Object] on hardware instead of standard\n                return asString;\n            }\n\n            let keys = Object.keys(obj);\n            const snipped = keys.length > maxElements;\n            if (snipped) {\n                keys = keys.slice(0, maxElements);\n            }\n\n            return `{${keys.reduce(\n                (prev, currKey) => prev + `\\n    ${currKey}: ${obj[currKey]}`,\n                \"\"\n            ) + (snipped ? \"\\n    ...\" : \"\")\n                }\n}`;\n        }\n    }\n\n    /**\n     * Adds a listener for the log messages\n     * @param listener\n     */\n    //%\n    export function addListener(listener: (priority: ConsolePriority, text: string) => void) {\n        if (!listeners) listeners = []\n        if (!listener || listeners.indexOf(listener) > -1) return;\n        listeners.push(listener);\n    }\n\n    /**\n     * Removes a listener\n     * @param listener\n     */\n    //%\n    export function removeListener(listener: (priority: ConsolePriority, text: string) => void) {\n        if (!listener || !listeners) return;\n        const i = listeners.indexOf(listener);\n        if (i > -1)\n            listeners.splice(i, 1);\n    }\n}","control.cpp":"#include \"pxt.h\"\n\nextern uint32_t __StackTop;\n\n/**\n * How to create the event.\n */\nenum class EventCreationMode {\n    /**\n     * MicroBitEvent is initialised, and no further processing takes place.\n     */\n    CreateOnly = CREATE_ONLY,\n    /**\n     * MicroBitEvent is initialised, and its event handlers are immediately fired (not suitable for use in interrupts!).\n     */\n    CreateAndFire = CREATE_AND_FIRE,\n};\n\nconst char *MICROBIT_BOARD_VERSION[3] = { \"2.0\", \"2.2\", \"2.X\" };\n\n// note the trailing '_' in names - otherwise we get conflict with the pre-processor\n// this trailing underscore is removed by enums.d.ts generation process\n\n// TODO shouldn't these be renamed to something more sensible anyways?\n\nenum EventBusSource {\n    //% blockIdentity=\"control.eventSourceId\"\n    MICROBIT_ID_BUTTON_A_ = MICROBIT_ID_BUTTON_A,\n    //% blockIdentity=\"control.eventSourceId\"\n    MICROBIT_ID_BUTTON_B_ = MICROBIT_ID_BUTTON_B,\n    //% blockIdentity=\"control.eventSourceId\"\n    MICROBIT_ID_BUTTON_AB_ = MICROBIT_ID_BUTTON_AB,\n    //% blockIdentity=\"control.eventSourceId\"\n    MICROBIT_ID_RADIO_ = MICROBIT_ID_RADIO,\n    //% blockIdentity=\"control.eventSourceId\"\n    MICROBIT_ID_GESTURE_ = MICROBIT_ID_GESTURE,\n    //% blockIdentity=\"control.eventSourceId\"\n    MICROBIT_ID_ACCELEROMETER_ = MICROBIT_ID_ACCELEROMETER,\n    //% blockIdentity=\"control.eventSourceId\"\n    MICROBIT_ID_IO_P0_ = MICROBIT_ID_IO_P0,\n    //% blockIdentity=\"control.eventSourceId\"\n    MICROBIT_ID_IO_P1_ = MICROBIT_ID_IO_P1,\n    //% blockIdentity=\"control.eventSourceId\"\n    MICROBIT_ID_IO_P2_ = MICROBIT_ID_IO_P2,\n    //% blockIdentity=\"control.eventSourceId\"\n    MICROBIT_ID_IO_P3_ = MICROBIT_ID_IO_P3,\n    //% blockIdentity=\"control.eventSourceId\"\n    MICROBIT_ID_IO_P4_ = MICROBIT_ID_IO_P4,\n    //% blockIdentity=\"control.eventSourceId\"\n    MICROBIT_ID_IO_P5_ = MICROBIT_ID_IO_P5,\n    //% blockIdentity=\"control.eventSourceId\"\n    MICROBIT_ID_IO_P6_ = MICROBIT_ID_IO_P6,\n    //% blockIdentity=\"control.eventSourceId\"\n    MICROBIT_ID_IO_P7_ = MICROBIT_ID_IO_P7,\n    //% blockIdentity=\"control.eventSourceId\"\n    MICROBIT_ID_IO_P8_ = MICROBIT_ID_IO_P8,\n    //% blockIdentity=\"control.eventSourceId\"\n    MICROBIT_ID_IO_P9_ = MICROBIT_ID_IO_P9,\n    //% blockIdentity=\"control.eventSourceId\"\n    MICROBIT_ID_IO_P10_ = MICROBIT_ID_IO_P10,\n    //% blockIdentity=\"control.eventSourceId\"\n    MICROBIT_ID_IO_P11_ = MICROBIT_ID_IO_P11,\n    //% blockIdentity=\"control.eventSourceId\"\n    MICROBIT_ID_IO_P12_ = MICROBIT_ID_IO_P12,\n    //% blockIdentity=\"control.eventSourceId\"\n    MICROBIT_ID_IO_P13_ = MICROBIT_ID_IO_P13,\n    //% blockIdentity=\"control.eventSourceId\"\n    MICROBIT_ID_IO_P14_ = MICROBIT_ID_IO_P14,\n    //% blockIdentity=\"control.eventSourceId\"\n    MICROBIT_ID_IO_P15_ = MICROBIT_ID_IO_P15,\n    //% blockIdentity=\"control.eventSourceId\"\n    MICROBIT_ID_IO_P16_ = MICROBIT_ID_IO_P16,\n    //% blockIdentity=\"control.eventSourceId\"\n    MICROBIT_ID_IO_P19_ = MICROBIT_ID_IO_P19,\n    //% blockIdentity=\"control.eventSourceId\"\n    MICROBIT_ID_IO_P20_ = MICROBIT_ID_IO_P20,\n    //% blockIdentity=\"control.eventSourceId\"\n    MES_DEVICE_INFO_ID_ = MES_DEVICE_INFO_ID,\n    //% blockIdentity=\"control.eventSourceId\"\n    MES_SIGNAL_STRENGTH_ID_ = MES_SIGNAL_STRENGTH_ID,\n    //% blockIdentity=\"control.eventSourceId\"\n    MES_DPAD_CONTROLLER_ID_ = MES_DPAD_CONTROLLER_ID,\n    //% blockIdentity=\"control.eventSourceId\"\n    MES_BROADCAST_GENERAL_ID_ = MES_BROADCAST_GENERAL_ID,\n};\n\nenum EventBusValue {\n    //% blockIdentity=\"control.eventValueId\"\n    MICROBIT_EVT_ANY_ = MICROBIT_EVT_ANY,\n    //% blockIdentity=\"control.eventValueId\"\n    MICROBIT_BUTTON_EVT_DOWN_ = MICROBIT_BUTTON_EVT_DOWN,\n    //% blockIdentity=\"control.eventValueId\"\n    MICROBIT_BUTTON_EVT_UP_ = MICROBIT_BUTTON_EVT_UP,\n    //% blockIdentity=\"control.eventValueId\"\n    MICROBIT_BUTTON_EVT_CLICK_ = MICROBIT_BUTTON_EVT_CLICK,\n    //% blockIdentity=\"control.eventValueId\"\n    MICROBIT_RADIO_EVT_DATAGRAM_ = MICROBIT_RADIO_EVT_DATAGRAM,\n    //% blockIdentity=\"control.eventValueId\"\n    MICROBIT_ACCELEROMETER_EVT_DATA_UPDATE_ = MICROBIT_ACCELEROMETER_EVT_DATA_UPDATE,\n    //% blockIdentity=\"control.eventValueId\"\n    MICROBIT_PIN_EVT_RISE_ = MICROBIT_PIN_EVT_RISE,\n    //% blockIdentity=\"control.eventValueId\"\n    MICROBIT_PIN_EVT_FALL_ = MICROBIT_PIN_EVT_FALL,\n    //% blockIdentity=\"control.eventValueId\"\n    MICROBIT_PIN_EVT_PULSE_HI_ = MICROBIT_PIN_EVT_PULSE_HI,\n    //% blockIdentity=\"control.eventValueId\"\n    MICROBIT_PIN_EVT_PULSE_LO_ = MICROBIT_PIN_EVT_PULSE_LO,\n    //% blockIdentity=\"control.eventValueId\"\n    MES_ALERT_EVT_ALARM1_ = MES_ALERT_EVT_ALARM1,\n    //% blockIdentity=\"control.eventValueId\"\n    MES_ALERT_EVT_ALARM2_ = MES_ALERT_EVT_ALARM2,\n    //% blockIdentity=\"control.eventValueId\"\n    MES_ALERT_EVT_ALARM3_ = MES_ALERT_EVT_ALARM3,\n    //% blockIdentity=\"control.eventValueId\"\n    MES_ALERT_EVT_ALARM4_ = MES_ALERT_EVT_ALARM4,\n    //% blockIdentity=\"control.eventValueId\"\n    MES_ALERT_EVT_ALARM5_ = MES_ALERT_EVT_ALARM5,\n    //% blockIdentity=\"control.eventValueId\"\n    MES_ALERT_EVT_ALARM6_ = MES_ALERT_EVT_ALARM6,\n    //% blockIdentity=\"control.eventValueId\"\n    MES_ALERT_EVT_DISPLAY_TOAST_ = MES_ALERT_EVT_DISPLAY_TOAST,\n    //% blockIdentity=\"control.eventValueId\"\n    MES_ALERT_EVT_FIND_MY_PHONE_ = MES_ALERT_EVT_FIND_MY_PHONE,\n    //% blockIdentity=\"control.eventValueId\"\n    MES_ALERT_EVT_PLAY_RINGTONE_ = MES_ALERT_EVT_PLAY_RINGTONE,\n    //% blockIdentity=\"control.eventValueId\"\n    MES_ALERT_EVT_PLAY_SOUND_ = MES_ALERT_EVT_PLAY_SOUND,\n    //% blockIdentity=\"control.eventValueId\"\n    MES_ALERT_EVT_VIBRATE_ = MES_ALERT_EVT_VIBRATE,\n    //% blockIdentity=\"control.eventValueId\"\n    MES_CAMERA_EVT_LAUNCH_PHOTO_MODE_ = MES_CAMERA_EVT_LAUNCH_PHOTO_MODE,\n    //% blockIdentity=\"control.eventValueId\"\n    MES_CAMERA_EVT_LAUNCH_VIDEO_MODE_ = MES_CAMERA_EVT_LAUNCH_VIDEO_MODE,\n    //% blockIdentity=\"control.eventValueId\"\n    MES_CAMERA_EVT_START_VIDEO_CAPTURE_ = MES_CAMERA_EVT_START_VIDEO_CAPTURE,\n    //% blockIdentity=\"control.eventValueId\"\n    MES_CAMERA_EVT_STOP_PHOTO_MODE_ = MES_CAMERA_EVT_STOP_PHOTO_MODE,\n    //% blockIdentity=\"control.eventValueId\"\n    MES_CAMERA_EVT_STOP_VIDEO_CAPTURE_ = MES_CAMERA_EVT_STOP_VIDEO_CAPTURE,\n    //% blockIdentity=\"control.eventValueId\"\n    MES_CAMERA_EVT_STOP_VIDEO_MODE_ = MES_CAMERA_EVT_STOP_VIDEO_MODE,\n    //% blockIdentity=\"control.eventValueId\"\n    MES_CAMERA_EVT_TAKE_PHOTO_ = MES_CAMERA_EVT_TAKE_PHOTO,\n    //% blockIdentity=\"control.eventValueId\"\n    MES_CAMERA_EVT_TOGGLE_FRONT_REAR_ = MES_CAMERA_EVT_TOGGLE_FRONT_REAR,\n    //% blockIdentity=\"control.eventValueId\"\n    MES_DEVICE_DISPLAY_OFF_ = MES_DEVICE_DISPLAY_OFF,\n    //% blockIdentity=\"control.eventValueId\"\n    MES_DEVICE_DISPLAY_ON_ = MES_DEVICE_DISPLAY_ON,\n    //% blockIdentity=\"control.eventValueId\"\n    MES_DEVICE_GESTURE_DEVICE_SHAKEN_ = MES_DEVICE_GESTURE_DEVICE_SHAKEN,\n    //% blockIdentity=\"control.eventValueId\"\n    MES_DEVICE_INCOMING_CALL_ = MES_DEVICE_INCOMING_CALL,\n    //% blockIdentity=\"control.eventValueId\"\n    MES_DEVICE_INCOMING_MESSAGE_ = MES_DEVICE_INCOMING_MESSAGE,\n    //% blockIdentity=\"control.eventValueId\"\n    MES_DEVICE_ORIENTATION_LANDSCAPE_ = MES_DEVICE_ORIENTATION_LANDSCAPE,\n    //% blockIdentity=\"control.eventValueId\"\n    MES_DEVICE_ORIENTATION_PORTRAIT_ = MES_DEVICE_ORIENTATION_PORTRAIT,\n    //% blockIdentity=\"control.eventValueId\"\n    MES_DPAD_BUTTON_1_DOWN_ = MES_DPAD_BUTTON_1_DOWN,\n    //% blockIdentity=\"control.eventValueId\"\n    MES_DPAD_BUTTON_1_UP_ = MES_DPAD_BUTTON_1_UP,\n    //% blockIdentity=\"control.eventValueId\"\n    MES_DPAD_BUTTON_2_DOWN_ = MES_DPAD_BUTTON_2_DOWN,\n    //% blockIdentity=\"control.eventValueId\"\n    MES_DPAD_BUTTON_2_UP_ = MES_DPAD_BUTTON_2_UP,\n    //% blockIdentity=\"control.eventValueId\"\n    MES_DPAD_BUTTON_3_DOWN_ = MES_DPAD_BUTTON_3_DOWN,\n    //% blockIdentity=\"control.eventValueId\"\n    MES_DPAD_BUTTON_3_UP_ = MES_DPAD_BUTTON_3_UP,\n    //% blockIdentity=\"control.eventValueId\"\n    MES_DPAD_BUTTON_4_DOWN_ = MES_DPAD_BUTTON_4_DOWN,\n    //% blockIdentity=\"control.eventValueId\"\n    MES_DPAD_BUTTON_4_UP_ = MES_DPAD_BUTTON_4_UP,\n    //% blockIdentity=\"control.eventValueId\"\n    MES_DPAD_BUTTON_A_DOWN_ = MES_DPAD_BUTTON_A_DOWN,\n    //% blockIdentity=\"control.eventValueId\"\n    MES_DPAD_BUTTON_A_UP_ = MES_DPAD_BUTTON_A_UP,\n    //% blockIdentity=\"control.eventValueId\"\n    MES_DPAD_BUTTON_B_DOWN_ = MES_DPAD_BUTTON_B_DOWN,\n    //% blockIdentity=\"control.eventValueId\"\n    MES_DPAD_BUTTON_B_UP_ = MES_DPAD_BUTTON_B_UP,\n    //% blockIdentity=\"control.eventValueId\"\n    MES_DPAD_BUTTON_C_DOWN_ = MES_DPAD_BUTTON_C_DOWN,\n    //% blockIdentity=\"control.eventValueId\"\n    MES_DPAD_BUTTON_C_UP_ = MES_DPAD_BUTTON_C_UP,\n    //% blockIdentity=\"control.eventValueId\"\n    MES_DPAD_BUTTON_D_DOWN_ = MES_DPAD_BUTTON_D_DOWN,\n    //% blockIdentity=\"control.eventValueId\"\n    MES_DPAD_BUTTON_D_UP_ = MES_DPAD_BUTTON_D_UP,\n    //% blockIdentity=\"control.eventValueId\"\n    MES_REMOTE_CONTROL_EVT_FORWARD_ = MES_REMOTE_CONTROL_EVT_FORWARD,\n    //% blockIdentity=\"control.eventValueId\"\n    MES_REMOTE_CONTROL_EVT_NEXTTRACK_ = MES_REMOTE_CONTROL_EVT_NEXTTRACK,\n    //% blockIdentity=\"control.eventValueId\"\n    MES_REMOTE_CONTROL_EVT_PAUSE_ = MES_REMOTE_CONTROL_EVT_PAUSE,\n    //% blockIdentity=\"control.eventValueId\"\n    MES_REMOTE_CONTROL_EVT_PLAY_ = MES_REMOTE_CONTROL_EVT_PLAY,\n    //% blockIdentity=\"control.eventValueId\"\n    MES_REMOTE_CONTROL_EVT_PREVTRACK_ = MES_REMOTE_CONTROL_EVT_PREVTRACK,\n    //% blockIdentity=\"control.eventValueId\"\n    MES_REMOTE_CONTROL_EVT_REWIND_ = MES_REMOTE_CONTROL_EVT_REWIND,\n    //% blockIdentity=\"control.eventValueId\"\n    MES_REMOTE_CONTROL_EVT_STOP_ = MES_REMOTE_CONTROL_EVT_STOP,\n    //% blockIdentity=\"control.eventValueId\"\n    MES_REMOTE_CONTROL_EVT_VOLUMEDOWN_ = MES_REMOTE_CONTROL_EVT_VOLUMEDOWN,\n    //% blockIdentity=\"control.eventValueId\"\n    MES_REMOTE_CONTROL_EVT_VOLUMEUP_ = MES_REMOTE_CONTROL_EVT_VOLUMEUP,\n};\n\nenum EventFlags {\n    //%\n    QueueIfBusy = MESSAGE_BUS_LISTENER_QUEUE_IF_BUSY,\n    //%\n    DropIfBusy = MESSAGE_BUS_LISTENER_DROP_IF_BUSY,\n    //%\n    Reentrant = MESSAGE_BUS_LISTENER_REENTRANT\n};\n\n//% weight=1 color=\"#333333\"\n//% advanced=true\nnamespace control {\n    void fiberDone(void *a)\n    {\n      decr((Action)a);\n      release_fiber();\n    }\n\n    /**\n    * Gets the number of milliseconds elapsed since power on.\n    */\n    //% help=control/millis weight=50\n    //% blockId=control_running_time block=\"millis (ms)\"\n    int millis() {\n        return system_timer_current_time();\n    }\n\n    /**\n    * Gets current time in microseconds. Overflows every ~18 minutes.\n    */\n    //%\n    int micros() {\n        return system_timer_current_time_us() & 0x3fffffff;\n    }\n\n    /**\n     * Schedules code that run in the background.\n     */\n    //% help=control/in-background blockAllowMultiple=1 afterOnStart=true\n    //% blockId=\"control_in_background\" block=\"run in background\" blockGap=8\n    void inBackground(Action a) {\n      runInParallel(a);\n    }\n\n    /**\n    * Blocks the calling thread until the specified event is raised.\n    */\n    //% help=control/wait-for-event async\n    //% blockId=control_wait_for_event block=\"wait for event|from %src|with value %value\"\n    void waitForEvent(int src, int value) {\n        pxt::waitForEvent(src, value);\n    }\n\n    /**\n     * Resets the BBC micro:bit.\n     */\n    //% weight=30 async help=control/reset blockGap=8\n    //% blockId=\"control_reset\" block=\"reset\"\n    void reset() {\n      microbit_reset();\n    }\n\n\n    \n\n    //%\n    void singleSimulator() { }\n\n    /**\n    * Blocks the current fiber for the given microseconds\n    * @param micros number of micro-seconds to wait. eg: 4\n    */\n    //% help=control/wait-micros weight=29 async\n    //% blockId=\"control_wait_us\" block=\"wait (µs)%micros\"\n    //% micros.min=0 micros.max=6000\n    void waitMicros(int micros) {\n        sleep_us(micros);\n    }\n\n    /**\n     * Raises an event in the event bus.\n     * @param src ID of the MicroBit Component that generated the event e.g. MICROBIT_ID_BUTTON_A.\n     * @param value Component specific code indicating the cause of the event.\n     * @param mode optional definition of how the event should be processed after construction (default is CREATE_AND_FIRE).\n     */\n    //% weight=21 blockGap=12 blockId=\"control_raise_event\" block=\"raise event|from source %src=control_event_source_id|with value %value=control_event_value_id\" blockExternalInputs=1\n    //% help=control/raise-event\n    //% mode.defl=CREATE_AND_FIRE\n    void raiseEvent(int src, int value, EventCreationMode mode) {\n        MicroBitEvent evt(src, value, (MicroBitEventLaunchMode)mode);\n    }\n\n    /**\n     * Registers an event handler.\n     */\n    //% weight=20 blockGap=8 blockId=\"control_on_event\" block=\"on event|from %src=control_event_source_id|with value %value=control_event_value_id\"\n    //% help=control/on-event\n    //% blockExternalInputs=1\n    void onEvent(int src, int value, Action handler, int flags = 0) {\n        if (!flags) flags = ::EventFlags::QueueIfBusy;\n        registerWithDal(src, value, handler, (int)flags);\n    }\n\n    /**\n    * Gets the value of the last event executed on the bus\n    */\n    //% blockId=control_event_value\" block=\"event value\"\n    //% help=control/event-value\n    //% weight=18\n    int eventValue() {\n        return pxt::lastEvent.value;\n    }\n\n    /**\n    * Gets the timestamp of the last event executed on the bus\n    */\n    //% blockId=control_event_timestamp\" block=\"event timestamp\"\n    //% help=control/event-timestamp\n    //% weight=19 blockGap=8\n    int eventTimestamp() {\n        return pxt::lastEvent.timestamp;\n    }\n\n    /**\n     * Make a friendly name for the device based on its serial number\n     */\n    //% blockId=\"control_device_name\" block=\"device name\" weight=10 blockGap=8\n    //% help=control/device-name\n    //% advanced=true\n    String deviceName() {\n        return mkString(microbit_friendly_name(), -1);\n    }\n\n    /**\n     * Returns the major version of the microbit\n     */\n    //% help=control/hardware-version\n    String _hardwareVersion() {\n        #if MICROBIT_CODAL\n            MicroBitVersion v = uBit.power.getVersion();\n            int versionIdx;\n            switch (v.board) {\n                case 0x9903:\n                case 0x9904:\n                    versionIdx = 0;\n                    break;\n                case 0x9905:\n                case 0x9906:\n                    versionIdx = 1;\n                    break;\n                default:\n                    versionIdx = 2;\n                    break;\n            }\n            return mkString(MICROBIT_BOARD_VERSION[versionIdx], -1);\n        #else\n            return mkString(\"1.X\", 1);\n        #endif\n    }\n\n    /**\n    * Derive a unique, consistent serial number of this device from internal data.\n    */\n    //% blockId=\"control_device_serial_number\" block=\"device serial number\" weight=9\n    //% help=control/device-serial-number\n    //% advanced=true\n    int deviceSerialNumber() {\n        return microbit_serial_number();\n    }\n\n   /**\n    * Derive a unique, consistent 64-bit serial number of this device from internal data.\n    */\n    //% help=control/device-long-serial-number\n    //% advanced=true\n    Buffer deviceLongSerialNumber() {\n        return mkBuffer((uint8_t*)&NRF_FICR->DEVICEID[0], sizeof(uint64_t));\n    }\n\n    /**\n    * Informs simulator/runtime of a MIDI message\n    * Internal function to support the simulator.\n    */\n    //% part=midioutput blockHidden=1\n    void __midiSend(Buffer buffer) {\n        // this is a stub to support the simulator\n    }\n\n    /**\n    *\n    */\n    //%\n    void __log(int priority, String text) {\n        if (NULL == text) return;\n        pxt::sendSerial(text->getUTF8Data(), text->getUTF8Size());\n    }\n\n\n\n/**\n* Allocates the next user notification event\n*/\n//% help=control/allocate-notify-event\nint allocateNotifyEvent() {\n#if MICROBIT_CODAL\n    return ::allocateNotifyEvent();\n#else\n    static int notifyEv = 1024;\n    return ++notifyEv;\n#endif\n}\n\n/** Write a message to DMESG debugging buffer. */\n//%\nvoid dmesg(String s) {\n    // this is no-op on v1\n    DMESG(\"# %s\", s->getUTF8Data());\n}\n\n/** Write a message and value (pointer) to DMESG debugging buffer. */\n//%\nvoid dmesgPtr(String str, Object_ ptr) {\n    // this is no-op on v1\n    DMESG(\"# %s: %p\", str->getUTF8Data(), ptr);\n}\n\n//%\nuint32_t _ramSize()\n{\n    return (uint32_t)&__StackTop & 0x1fffffff;\n}\n\n}\n","control.ts":"/**\n* Runtime and event utilities.\n*/\n//% weight=1 color=\"#333333\" icon=\"\\uf233\"\n//% advanced=true\nnamespace control {\n    /**\n     * Run other code in the parallel.\n     */\n    //% hidden=1\n    export function runInParallel(a: () => void) {\n        control.inBackground(a);\n    }\n\n    //% hidden=1 deprecated=1\n    export function runInBackground(a: () => void) {\n        control.inBackground(a);\n    }\n    \n    /**\n     * Allow only one simulator\n     */\n    //% shim=control::singleSimulator\n    export function singleSimulator() { \n\n    }\n\n    /**\n     * Returns the value of a C++ runtime constant\n     */\n    //% weight=2 weight=19 blockId=\"control_event_source_id\" block=\"%id\" blockGap=8\n    //% help=control/event-source-id\n    //% shim=TD_ID advanced=true\n    export function eventSourceId(id: EventBusSource): number {\n        return id;\n    }\n    /**\n     * Returns the value of a C++ runtime constant\n     */\n    //% weight=1 weight=19 blockId=\"control_event_value_id\" block=\"%id\"\n    //% help=control/event-value-id\n    //% shim=TD_ID advanced=true\n    export function eventValueId(id: EventBusValue): number {\n        return id;\n    }\n\n    export const enum PXT_PANIC {\n        CODAL_OOM = 20,\n        GC_OOM = 21,\n        GC_TOO_BIG_ALLOCATION = 22,\n        CODAL_HEAP_ERROR = 30,\n        CODAL_NULL_DEREFERENCE = 40,\n        CODAL_USB_ERROR = 50,\n        CODAL_HARDWARE_CONFIGURATION_ERROR = 90,\n\n        INVALID_BINARY_HEADER = 901,\n        OUT_OF_BOUNDS = 902,\n        REF_DELETED = 903,\n        SIZE = 904,\n        INVALID_VTABLE = 905,\n        INTERNAL_ERROR = 906,\n        NO_SUCH_CONFIG = 907,\n        NO_SUCH_PIN = 908,\n        INVALID_ARGUMENT = 909,\n        MEMORY_LIMIT_EXCEEDED = 910,\n        SCREEN_ERROR = 911,\n        MISSING_PROPERTY = 912,\n        INVALID_IMAGE = 913,\n        CALLED_FROM_ISR = 914,\n        HEAP_DUMPED = 915,\n        STACK_OVERFLOW = 916,\n        BLOCKING_TO_STRING = 917,\n        VM_ERROR = 918,\n        SETTINGS_CLEARED = 920,\n        SETTINGS_OVERLOAD = 921,\n        SETTINGS_SECRET_MISSING = 922,\n        DELETE_ON_CLASS = 923,\n\n        CAST_FIRST = 980,\n        CAST_FROM_UNDEFINED = 980,\n        CAST_FROM_BOOLEAN = 981,\n        CAST_FROM_NUMBER = 982,\n        CAST_FROM_STRING = 983,\n        CAST_FROM_OBJECT = 984,\n        CAST_FROM_FUNCTION = 985,\n        CAST_FROM_NULL = 989,\n\n        UNHANDLED_EXCEPTION = 999,\n    }\n\n    /**\n     * Display specified error code and stop the program.\n     */\n    //% shim=pxtrt::panic\n    export function panic(code: number) { }\n\n    /**\n     * If the condition is false, display msg on serial console, and panic with code 098.\n     */\n    export function assert(condition: boolean, msg?: string) {\n        if (!condition) {\n            console.log(\"ASSERTION FAILED\")\n            if (msg != null) {\n                console.log(msg)\n            }\n            panic(98)\n        }\n    }\n\n    export function fail(message: string) {\n        console.log(\"Fatal failure: \")\n        console.log(message)\n        panic(108)\n    }\n\n    let _evSource = 0x8000\n    /**\n     * Incrementally allocates event source identifiers.\n     */\n    export function allocateEventSource() {\n        return ++_evSource\n    }    \n\n    /**\n     * Display warning in the simulator.\n     */\n    //% shim=pxtrt::runtimeWarning\n    export function runtimeWarning(message: string) { }\n\n    //% shim=pxt::programHash\n    export declare function programHash(): number;\n\n    //% shim=pxt::programName\n    export declare function programName(): string;\n\n    /** Returns estimated size of memory in bytes. */\n    //% shim=control::_ramSize\n    export function ramSize() {\n        return 32 * 1024 * 1024;\n    }\n\n    /** Runs the function and returns run time in microseconds. */\n    export function benchmark(f: () => void) {\n        const t0 = micros()\n        f()\n        let t = micros() - t0\n        if (t < 0)\n            t += 0x3fffffff\n        return t\n    }\n\n    /**\n     * Given two versions, returns -1 if the first version is less than\n     * the second, 1 if it's greater, and 0 if it's the same.\n     */\n    //%\n    export function compareVersion(version1: string, version2: string): number {\n        let v1Arr = version1.split(\".\");\n        let v2Arr = version2.split(\".\");\n\n        v1Arr = v1Arr.map((str) => {\n            if (str.includes(\"x\") || str.includes(\"X\")) {\n                return \"0\"\n            } else {\n                return str;\n            }\n        })\n        v2Arr = v2Arr.map((str) => {\n            if (str.includes(\"x\") || str.includes(\"X\")) {\n                return \"0\"\n            } else {\n                return str;\n            }\n        })\n\n        for (let i = v1Arr.length; i < Math.max(v1Arr.length, v2Arr.length); i++) {\n            v1Arr.push(\"0\");\n        }\n\n        for (let i = v2Arr.length; i < Math.max(v1Arr.length, v2Arr.length); i++) {\n            v2Arr.push(\"0\");\n        }\n\n        for (let i = 0; i < v1Arr.length; i++) {\n            if (parseInt(v1Arr[i]) != parseInt(v2Arr[i])) {\n                return parseInt(v1Arr[i]) - parseInt(v2Arr[i]);\n            }\n        }\n        return 0;\n    }\n\n    //% shim=control::_hardwareVersion\n    export function hardwareVersion(): string {\n        return \"2.0\";\n    }\n}\n\n/**\n * Convert any value to text\n * @param value value to be converted to text\n */\n//% help=text/convert-to-text weight=1\n//% block=\"convert $value=math_number to text\"\n//% blockId=variable_to_text blockNamespace=\"text\"\nfunction convertToText(value: any): string {\n    return \"\" + value;\n}","controlgc.cpp":"#include \"pxtbase.h\"\n\n\nnamespace control {\n    /**\n     * Force GC and dump basic information about heap.\n     */\n    //%\n    void gc() {\n        pxt::gc(1);\n    }\n\n    /**\n     * Force GC and halt waiting for debugger to do a full heap dump.\n     */\n    //%\n    void heapDump() {\n        pxt::gc(2);\n        soft_panic(PANIC_HEAP_DUMPED);\n    }\n\n\n    /**\n     * Set flags used when connecting an external debugger.\n     */\n    //%\n    void setDebugFlags(int flags) {\n        debugFlags = flags;\n    }\n\n    /**\n     * Record a heap snapshot to debug memory leaks.\n     */\n    //%\n    void heapSnapshot() {\n        // only in JS backend for now\n    }\n\n    /**\n     * Return true if profiling is enabled in the current build.\n     */\n    //%\n    bool profilingEnabled() {\n#ifdef PXT_PROFILE\n        return true;\n#else\n        return false;\n#endif\n    }\n}\n","controlmessage.ts":"namespace control.simmessages {\n    // these events are raised by JS simulator when messages come in\n    export const CONTROL_MESSAGE_EVT_ID = 2999;\n    export const CONTROL_MESSAGE_RECEIVED = 1;\n\n    //% shim=pxt::sendMessage\n    export declare function send(channel: string, message: Buffer, parentOnly?: boolean) : void;\n\n    //% shim=pxt::peekMessageChannel\n    declare function peekMessageChannel(): string;\n\n    //% shim=pxt::readMessageData\n    declare function readMessageData(): Buffer;\n\n    let handlers: { [channel: string] : (msg: Buffer) => void}\n    function consumeMessages() {\n        while(true) {\n            // peek channel of next message\n            const channel = peekMessageChannel();\n            if (!channel) break;\n            // read next message\n            const msg = readMessageData();\n            // send to handler\n            const handler = handlers && handlers[channel];\n            if (handler)\n                handler(msg);\n        }\n    }\n\n    /**\n     * Registers the handler for a message on a given channel\n     **/\n    export function onReceived(channel: string, handler: (msg: Buffer) => void) {\n        if (!channel) return;\n\n        if (!handlers)\n            handlers = {};\n        handlers[channel] = handler;\n        control.onEvent(CONTROL_MESSAGE_EVT_ID, CONTROL_MESSAGE_RECEIVED, consumeMessages);\n    }\n}","core.cpp":"#include \"pxtbase.h\"\n#include <limits.h>\n#include <stdlib.h>\n\nusing namespace std;\n\n#define p10(v) __builtin_powi(10, v)\n\n// try not to create cons-strings shorter than this\n#define SHORT_CONCAT_STRING 50\n\nnamespace pxt {\n\nPXT_DEF_STRING(emptyString, \"\")\n\nstatic HandlerBinding *handlerBindings;\n\nHandlerBinding *nextBinding(HandlerBinding *curr, int source, int value) {\n    for (auto p = curr; p; p = p->next) {\n        // DEVICE_ID_ANY == DEVICE_EXT_ANY == 0\n        if ((p->source == source || p->source == 0) &&\n            (value == -1 || p->value == value || p->value == 0)) {\n            return p;\n        }\n    }\n    return 0;\n}\n\nHandlerBinding *findBinding(int source, int value) {\n    return nextBinding(handlerBindings, source, value);\n}\n\nvoid setBinding(int source, int value, Action act) {\n    HandlerBinding *curr = NULL;\n    for (auto p = handlerBindings; p; p = p->next) {\n        if ((p->source == source) && (p->value == value)) {\n            curr = p;\n            break;\n        }\n    }\n    if (curr) {\n        curr->action = act;\n        return;\n    }\n    curr = new (app_alloc(sizeof(HandlerBinding))) HandlerBinding();\n    curr->next = handlerBindings;\n    curr->source = source;\n    curr->value = value;\n    curr->action = act;\n    registerGC(&curr->action);\n    handlerBindings = curr;\n}\n\nvoid coreReset() {\n    // these are allocated on GC heap, so they will go away together with the reset\n    handlerBindings = NULL;\n}\n\nstruct EmptyBufferLayout {\n    const void *vtable;\n    // data needs to be word-aligned, so we use 32 bits for length\n    int length;\n    uint8_t data[1];\n};\n\nstatic const EmptyBufferLayout emptyBuffer[1] = {{&pxt::buffer_vt, 0, {0}}};\n\n#if PXT_UTF8\nint utf8Len(const char *data, int size) {\n    int len = 0;\n    for (int i = 0; i < size; ++i) {\n        char c = data[i];\n        len++;\n        if ((c & 0x80) == 0x00) {\n            // skip\n        } else if ((c & 0xe0) == 0xc0) {\n            i++;\n        } else if ((c & 0xf0) == 0xe0) {\n            i += 2;\n        } else {\n            // error; just skip\n        }\n    }\n    return len;\n}\n\nconst char *utf8Skip(const char *data, int size, int skip) {\n    int len = 0;\n    for (int i = 0; i <= size; ++i) {\n        char c = data[i];\n        len++;\n        if (len > skip)\n            return data + i;\n        if ((c & 0x80) == 0x00) {\n            // skip\n        } else if ((c & 0xe0) == 0xc0) {\n            i++;\n        } else if ((c & 0xf0) == 0xe0) {\n            i += 2;\n        } else {\n            // error; just skip over\n        }\n    }\n    return NULL;\n}\n\nstatic char *write3byte(char *dst, uint32_t charCode) {\n    if (dst) {\n        *dst++ = 0xe0 | (charCode >> 12);\n        *dst++ = 0x80 | (0x3f & (charCode >> 6));\n        *dst++ = 0x80 | (0x3f & (charCode >> 0));\n    }\n    return dst;\n}\n\nstatic char *write2byte(char *dst, uint32_t charCode) {\n    if (dst) {\n        *dst++ = 0xc0 | (charCode >> 6);\n        *dst++ = 0x80 | (0x3f & charCode);\n    }\n    return dst;\n}\n\nstatic int utf8canon(char *dst, const char *data, int size) {\n    int outsz = 0;\n    for (int i = 0; i < size;) {\n        uint8_t c = data[i];\n        uint32_t charCode = c;\n        if ((c & 0x80) == 0x00) {\n            charCode = c;\n            i++;\n        } else if ((c & 0xe0) == 0xc0 && i + 1 < size && (data[i + 1] & 0xc0) == 0x80) {\n            charCode = ((c & 0x1f) << 6) | (data[i + 1] & 0x3f);\n            if (charCode < 0x80)\n                goto error;\n            else\n                i += 2;\n        } else if ((c & 0xf0) == 0xe0 && i + 2 < size && (data[i + 1] & 0xc0) == 0x80 &&\n                   (data[i + 2] & 0xc0) == 0x80) {\n            charCode = ((c & 0x0f) << 12) | (data[i + 1] & 0x3f) << 6 | (data[i + 2] & 0x3f);\n            // don't exclude surrogate pairs, since we're generating them\n            if (charCode < 0x800 /*|| (0xd800 <= charCode && charCode <= 0xdfff)*/)\n                goto error;\n            else\n                i += 3;\n        } else if ((c & 0xf8) == 0xf0 && i + 3 < size && (data[i + 1] & 0xc0) == 0x80 &&\n                   (data[i + 2] & 0xc0) == 0x80 && (data[i + 3] & 0xc0) == 0x80) {\n            charCode = ((c & 0x07) << 18) | (data[i + 1] & 0x3f) << 12 | (data[i + 2] & 0x3f) << 6 |\n                       (data[i + 3] & 0x3f);\n            if (charCode < 0x10000 || charCode > 0x10ffff)\n                goto error;\n            else\n                i += 4;\n        } else {\n            goto error;\n        }\n\n        if (charCode < 0x80) {\n            outsz += 1;\n            if (dst)\n                *dst++ = charCode;\n        } else if (charCode < 0x800) {\n            outsz += 2;\n            dst = write2byte(dst, charCode);\n        } else if (charCode < 0x10000) {\n            outsz += 3;\n            dst = write3byte(dst, charCode);\n        } else {\n            outsz += 6; // a surrogate pair\n            charCode -= 0x10000;\n            dst = write3byte(dst, 0xd800 + (charCode >> 10));\n            dst = write3byte(dst, 0xdc00 + (charCode & 0x3ff));\n        }\n\n        continue;\n\n    error:\n        i++;\n        outsz += 2;\n        dst = write2byte(dst, c);\n    }\n    return outsz;\n}\n\nstatic int utf8CharCode(const char *data) {\n    unsigned char c = *data;\n    if ((c & 0x80) == 0) {\n        return c;\n    } else if ((c & 0xe0) == 0xc0) {\n        return ((c & 0x1f) << 6) | (data[1] & 0x3f);\n    } else if ((c & 0xf0) == 0xe0) {\n        return ((c & 0x0f) << 12) | (data[1] & 0x3f) << 6 | (data[2] & 0x3f);\n    } else {\n        return c; // error\n    }\n}\n\nstatic bool isUTF8(const char *data, int len) {\n    for (int i = 0; i < len; ++i) {\n        if (data[i] & 0x80)\n            return true;\n    }\n    return false;\n}\n\nstatic void setupSkipList(String r, const char *data, int packed) {\n    char *dst = (char *)(packed ? PXT_SKIP_DATA_PACK(r) : PXT_SKIP_DATA_IND(r));\n    auto len = r->skip.size;\n    if (data)\n        memcpy(dst, data, len);\n#pragma GCC diagnostic push\n#pragma GCC diagnostic ignored \"-Wstringop-overflow\"\n    dst[len] = 0;\n#pragma GCC diagnostic pop\n    const char *ptr = dst;\n    auto skipEntries = PXT_NUM_SKIP_ENTRIES(r);\n    auto lst = packed ? r->skip_pack.list : r->skip.list;\n    for (int i = 0; i < skipEntries; ++i) {\n        ptr = utf8Skip(ptr, (int)(len - (ptr - dst)), PXT_STRING_SKIP_INCR);\n        if (!ptr)\n            oops(80);\n        lst[i] = ptr - dst;\n    }\n}\n#endif\n\nString mkStringCore(const char *data, int len) {\n    if (len < 0)\n        len = (int)strlen(data);\n    if (len == 0)\n        return (String)emptyString;\n\n    auto vt = &string_inline_ascii_vt;\n    String r;\n\n#if PXT_UTF8\n    if (data && isUTF8(data, len)) {\n        vt = len >= PXT_STRING_MIN_SKIP ? &string_skiplist16_packed_vt : &string_inline_utf8_vt;\n    }\n    if (vt == &string_skiplist16_packed_vt) {\n        int ulen = utf8Len(data, len);\n        r = new (gcAllocate(sizeof(void *) + 2 + 2 + (ulen / PXT_STRING_SKIP_INCR) * 2 + len + 1))\n            BoxedString(vt);\n        r->skip_pack.size = len;\n        r->skip_pack.length = ulen;\n        setupSkipList(r, data, 1);\n    } else\n#endif\n    {\n        // for ASCII and UTF8 the layout is the same\n        r = new (gcAllocate(sizeof(void *) + 2 + len + 1)) BoxedString(vt);\n        r->ascii.length = len;\n        if (data)\n            memcpy(r->ascii.data, data, len);\n        r->ascii.data[len] = 0;\n    }\n\n    MEMDBG(\"mkString: len=%d => %p\", len, r);\n    return r;\n}\n\nString mkString(const char *data, int len) {\n#if PXT_UTF8\n    if (len < 0)\n        len = (int)strlen(data);\n    if (len == 0)\n        return (String)emptyString;\n\n    int sz = utf8canon(NULL, data, len);\n    if (sz == len)\n        return mkStringCore(data, len);\n    // this could be optimized, but it only kicks in when the string isn't valid utf8\n    // (or we need to introduce surrogate pairs) which is unlikely to be performance critical\n    char *tmp = (char *)app_alloc(sz);\n    utf8canon(tmp, data, len);\n    auto r = mkStringCore(tmp, sz);\n    app_free(tmp);\n    return r;\n#else\n    return mkStringCore(data, len);\n#endif\n}\n\n#if PXT_UTF8\n// This converts surrogate pairs, which are encoded as 2 characters of 3 bytes each\n// into a proper 4 byte utf-8 character.\nuint32_t toRealUTF8(String str, uint8_t *dst) {\n    auto src = str->getUTF8Data();\n    auto len = str->getUTF8Size();\n    auto dlen = 0;\n\n    for (unsigned i = 0; i < len; ++i) {\n        if ((uint8_t)src[i] == 0xED && i + 5 < len) {\n            auto c0 = utf8CharCode(src + i);\n            auto c1 = utf8CharCode(src + i + 3);\n            if (0xd800 <= c0 && c0 < 0xdc00 && 0xdc00 <= c1 && c1 < 0xe000) {\n                i += 5;\n                auto charCode = ((c0 - 0xd800) << 10) + (c1 - 0xdc00) + 0x10000;\n                if (dst) {\n                    dst[dlen] = 0xf0 | (charCode >> 18);\n                    dst[dlen + 1] = 0x80 | (0x3f & (charCode >> 12));\n                    dst[dlen + 2] = 0x80 | (0x3f & (charCode >> 6));\n                    dst[dlen + 3] = 0x80 | (0x3f & (charCode >> 0));\n                }\n                dlen += 4;\n            }\n        } else {\n            if (dst)\n                dst[dlen] = src[i];\n            dlen++;\n        }\n    }\n    return dlen;\n}\n#endif\n\nBuffer mkBuffer(const void *data, int len) {\n    if (len <= 0)\n        return (Buffer)emptyBuffer;\n    Buffer r = new (gcAllocate(sizeof(BoxedBuffer) + len)) BoxedBuffer();\n    r->length = len;\n    if (data)\n        memcpy(r->data, data, len);\n    else\n        memset(r->data, 0, len);\n    MEMDBG(\"mkBuffer: len=%d => %p\", len, r);\n    return r;\n}\n\nstatic unsigned random_value = 0xC0DA1;\n\n//%\nvoid seedRandom(unsigned seed) {\n    random_value = seed;\n}\n\n//% expose\nvoid seedAddRandom(unsigned seed) {\n    random_value ^= 0xCA2557CB * seed;\n}\n\nunsigned getRandom(unsigned max) {\n    unsigned m, result;\n\n    do {\n        m = (unsigned)max;\n        result = 0;\n\n        do {\n            // Cycle the LFSR (Linear Feedback Shift Register).\n            // We use an optimal sequence with a period of 2^32-1, as defined by Bruce Schneier here\n            // (a true legend in the field!),\n            // For those interested, it's documented in his paper:\n            // \"Pseudo-Random Sequence Generator for 32-Bit CPUs: A fast, machine-independent\n            // generator for 32-bit Microprocessors\"\n            // https://www.schneier.com/paper-pseudorandom-sequence.html\n            unsigned r = random_value;\n\n            r = ((((r >> 31) ^ (r >> 6) ^ (r >> 4) ^ (r >> 2) ^ (r >> 1) ^ r) & 1) << 31) |\n                (r >> 1);\n\n            random_value = r;\n\n            result = ((result << 1) | (r & 0x00000001));\n        } while (m >>= 1);\n    } while (result > (unsigned)max);\n\n    return result;\n}\n\nTNumber BoxedString::charCodeAt(int pos) {\n#if PXT_UTF8\n    auto ptr = this->getUTF8DataAt(pos);\n    if (!ptr)\n        return TAG_NAN;\n    auto code = utf8CharCode(ptr);\n    if (!code && ptr == this->getUTF8Data() + this->getUTF8Size())\n        return TAG_NAN;\n    return fromInt(code);\n#else\n    if (0 <= pos && pos < this->ascii.length) {\n        return fromInt(this->ascii.data[pos]);\n    } else {\n        return TAG_NAN;\n    }\n#endif\n}\n\nPXT_DEF_STRING(sTrue, \"true\")\nPXT_DEF_STRING(sFalse, \"false\")\nPXT_DEF_STRING(sUndefined, \"undefined\")\nPXT_DEF_STRING(sNull, \"null\")\nPXT_DEF_STRING(sObject, \"[Object]\")\nPXT_DEF_STRING(sFunction, \"[Function]\")\nPXT_DEF_STRING(sNaN, \"NaN\")\nPXT_DEF_STRING(sInf, \"Infinity\")\nPXT_DEF_STRING(sMInf, \"-Infinity\")\n} // namespace pxt\n\n#ifndef X86_64\n\nnamespace String_ {\n\n//%\nString mkEmpty() {\n    return (String)emptyString;\n}\n\n// TODO support var-args somehow?\n\n//%\nString fromCharCode(int code) {\n#if PXT_UTF8\n    char buf[3];\n    int len;\n    code &= 0xffff; // JS semantics\n    if (code < 0x80) {\n        buf[0] = code;\n        len = 1;\n    } else if (code < 0x800) {\n        buf[0] = 0xc0 | (code >> 6);\n        buf[1] = 0x80 | ((code >> 0) & 0x3f);\n        len = 2;\n    } else {\n        buf[0] = 0xe0 | (code >> 12);\n        buf[1] = 0x80 | ((code >> 6) & 0x3f);\n        buf[2] = 0x80 | ((code >> 0) & 0x3f);\n        len = 3;\n    }\n    return mkStringCore(buf, len);\n#else\n    char buf[] = {(char)code, 0};\n    return mkStringCore(buf, 1);\n#endif\n}\n\n//%\nTNumber charCodeAt(String s, int pos) {\n    if (!s)\n        return TAG_NAN;\n    return s->charCodeAt(pos);\n}\n\n//%\nString charAt(String s, int pos) {\n    auto v = charCodeAt(s, pos);\n    if (v == TAG_NAN)\n        return mkEmpty();\n    if (!isInt(v))\n        oops(81);\n    return fromCharCode(numValue(v));\n}\n\n#define IS_CONS(s) ((s)->vtable == &string_cons_vt)\n#define IS_EMPTY(s) ((s) == (String)emptyString)\n\n//%\nString concat(String s, String other) {\n    if (!s)\n        s = (String)sNull;\n    if (!other)\n        other = (String)sNull;\n    if (IS_EMPTY(s))\n        return other;\n    if (IS_EMPTY(other))\n        return s;\n\n    uint32_t lenA, lenB;\n\n#if PXT_UTF8\n    if (IS_CONS(s)) {\n        // (s->cons.left + s->cons.right) + other = s->cons.left + (s->cons.right + other)\n        if (IS_CONS(other) || IS_CONS(s->cons.right))\n            goto mkCons;\n        auto lenAR = s->cons.right->getUTF8Size();\n        lenB = other->getUTF8Size(); // de-consify other\n        if (lenAR + lenB > SHORT_CONCAT_STRING)\n            goto mkCons;\n        // if (s->cons.right + other) is short enough, use associativity\n        // to construct a shallower tree; this should keep the live set reasonable\n        // when someone decides to construct a long string by concatenating\n        // single characters\n\n        // allocate [r] first, and keep it alive\n        String r = new (gcAllocate(3 * sizeof(void *))) BoxedString(&string_cons_vt);\n        registerGCObj(r);\n        r->cons.left = s->cons.left;\n        // this concat() might trigger GC\n        r->cons.right = concat(s->cons.right, other);\n        unregisterGCObj(r);\n        return r;\n    }\n#endif\n\n    lenA = s->getUTF8Size();\n    lenB = other->getUTF8Size();\n#if PXT_UTF8\n    if (lenA + lenB > SHORT_CONCAT_STRING)\n        goto mkCons;\n#endif\n    String r;\n    {\n        auto dataA = s->getUTF8Data();\n        auto dataB = other->getUTF8Data();\n        r = mkStringCore(NULL, lenA + lenB);\n        auto dst = (char *)r->getUTF8Data();\n        memcpy(dst, dataA, lenA);\n        memcpy(dst + lenA, dataB, lenB);\n#if PXT_UTF8\n        if (isUTF8(dst, lenA + lenB))\n            r->vtable = &string_inline_utf8_vt;\n#endif\n        return r;\n    }\n\n#if PXT_UTF8\nmkCons:\n    r = new (gcAllocate(3 * sizeof(void *))) BoxedString(&string_cons_vt);\n    r->cons.left = s;\n    r->cons.right = other;\n    return r;\n#endif\n}\n\nint compare(String a, String b) {\n    if (a == b)\n        return 0;\n\n    auto lenA = a->getUTF8Size();\n    auto lenB = b->getUTF8Size();\n    auto dataA = a->getUTF8Data();\n    auto dataB = b->getUTF8Data();\n    auto len = lenA < lenB ? lenA : lenB;\n\n    // this also works for UTF8, provided canonical encoding\n    // which is guaranteed by the constructor\n    for (unsigned i = 0; i <= len; ++i) {\n        unsigned char cA = dataA[i];\n        unsigned char cB = dataB[i];\n        if (cA == cB)\n            continue;\n        return cA < cB ? -1 : 1;\n    }\n    return 0;\n}\n\n//%\nint length(String s) {\n    return s->getLength();\n}\n\n#define isspace(c) ((c) == ' ')\n#define iswhitespace(c)                                                                            \\\n    ((c) == 0x09 || (c) == 0x0B || (c) == 0x0C || (c) == 0x20 || (uint8_t)(c) == 0xA0 ||           \\\n     (c) == 0x0A || (c) == 0x0D)\n\nNUMBER mystrtod(const char *p, char **endp) {\n    while (iswhitespace(*p))\n        p++;\n    NUMBER m = 1;\n    NUMBER v = 0;\n    int dot = 0;\n    int hasDigit = 0;\n    if (*p == '+')\n        p++;\n    if (*p == '-') {\n        m = -1;\n        p++;\n    }\n\n    while (*p) {\n        int c = *p - '0';\n        if (0 <= c && c <= 9) {\n            v *= 10;\n            v += c;\n            if (dot)\n                m /= 10;\n            hasDigit = 1;\n        } else if (!dot && *p == '.') {\n            dot = 1;\n        } else if (!hasDigit) {\n            return NAN;\n        } else {\n            break;\n        }\n        p++;\n    }\n\n    v *= m;\n\n    if (*p == 'e' || *p == 'E') {\n        p++;\n        int pw = (int)strtol(p, endp, 10);\n        v *= p10(pw);\n    } else {\n        *endp = (char *)p;\n    }\n\n    return v;\n}\n\n//%\nTNumber toNumber(String s) {\n    // JSCHECK\n    char *endptr;\n    auto data = s->getUTF8Data();\n    NUMBER v = mystrtod(data, &endptr);\n    if (v == 0.0 || v == -0.0) {\n        // nothing\n    } else if (!isnormal(v))\n        v = NAN;\n    return fromDouble(v);\n}\n\n//%\nString substr(String s, int start, int length) {\n    if (length <= 0)\n        return mkEmpty();\n    auto slen = (int)s->getLength();\n    if (start < 0)\n        start = pxt::max(slen + start, 0);\n    length = pxt::min(length, slen - start);\n    if (length <= 0)\n        return mkEmpty();\n    auto p = s->getUTF8DataAt(start);\n#if PXT_UTF8\n    auto ep = s->getUTF8DataAt(start + length);\n    if (ep == NULL)\n        oops(82);\n    return mkStringCore(p, (int)(ep - p));\n#else\n    return mkStringCore(p, length);\n#endif\n}\n\n//%\nint indexOf(String s, String searchString, int start) {\n    if (!s || !searchString)\n        return -1;\n\n    if (start < 0)\n        start = 0;\n\n    auto dataA0 = s->getUTF8Data();\n    auto dataA = s->getUTF8DataAt(start);\n    auto offset = dataA - dataA0;\n    auto lenA = s->getUTF8Size() - offset;\n    auto lenB = searchString->getUTF8Size();\n\n    if (dataA == NULL || lenB > lenA)\n        return -1;\n\n    auto dataB = searchString->getUTF8Data();\n    auto firstB = dataB[0];\n    while (lenA >= lenB) {\n        if (*dataA == firstB && !memcmp(dataA, dataB, lenB))\n#if PXT_UTF8\n            return utf8Len(dataA0, (int)(dataA - dataA0));\n#else\n            return dataA - dataA0;\n#endif\n        dataA++;\n        lenA--;\n    }\n    return -1;\n}\n\n//%\nint includes(String s, String searchString, int start) {\n    return -1 != indexOf(s, searchString, start);\n}\n\n} // namespace String_\n\nnamespace Boolean_ {\n//%\nbool bang(bool v) {\n    return v == 0;\n}\n} // namespace Boolean_\n\nnamespace pxt {\n\n// ES5 9.5, 9.6\nunsigned toUInt(TNumber v) {\n    if (isInt(v))\n        return numValue(v);\n    if (isSpecial(v)) {\n        if ((intptr_t)v >> 6)\n            return 1;\n        else\n            return 0;\n    }\n    if (!v)\n        return 0;\n\n    NUMBER num = toDouble(v);\n    if (!isnormal(num))\n        return 0;\n#ifdef PXT_USE_FLOAT\n    float rem = fmodf(truncf(num), 4294967296.0);\n#else\n    double rem = fmod(trunc(num), 4294967296.0);\n#endif\n    if (rem < 0.0)\n        rem += 4294967296.0;\n    return (unsigned)rem;\n}\nint toInt(TNumber v) {\n    return (int)toUInt(v);\n}\n\nNUMBER toDouble(TNumber v) {\n    if (v == TAG_NAN || v == TAG_UNDEFINED)\n        return NAN;\n    if (isTagged(v))\n        return toInt(v);\n\n#ifdef PXT64\n    if (isDouble(v))\n        return doubleVal(v);\n#endif\n\n    ValType t = valType(v);\n\n#ifndef PXT64\n    if (t == ValType::Number) {\n        BoxedNumber *p = (BoxedNumber *)v;\n        return p->num;\n    }\n#endif\n\n    if (t == ValType::String) {\n        // TODO avoid allocation\n        auto tmp = String_::toNumber((String)v);\n        auto r = toDouble(tmp);\n        return r;\n    } else {\n        return NAN;\n    }\n}\n\nfloat toFloat(TNumber v) {\n    if (v == TAG_NAN || v == TAG_UNDEFINED)\n        return NAN;\n    // optimize for the int case - this will avoid software conversion when FPU is present\n    if (isTagged(v))\n        return toInt(v);\n    return (float)toDouble(v);\n}\n\n#if !defined(PXT_HARD_FLOAT) && !defined(PXT_USE_FLOAT)\nunion NumberConv {\n    double v;\n    struct {\n        uint32_t word0;\n        uint32_t word1;\n    };\n};\n\nstatic inline TValue doubleToInt(double x) {\n    NumberConv cnv;\n    cnv.v = x;\n\n    if (cnv.word1 == 0 && cnv.word0 == 0)\n        return TAG_NUMBER(0);\n\n    auto ex = (int)((cnv.word1 << 1) >> 21) - 1023;\n\n    // DMESG(\"v=%d/1000 %p %p %d\", (int)(x * 1000), cnv.word0, cnv.word1, ex);\n\n    if (ex < 0 || ex > 29) {\n        // the 'MININT' case\n        if (ex == 30 && cnv.word0 == 0 && cnv.word1 == 0xC1D00000)\n            return (TValue)(0x80000001);\n        return NULL;\n    }\n\n    int32_t r;\n\n    if (ex <= 20) {\n        if (cnv.word0)\n            return TAG_UNDEFINED;\n        if (cnv.word1 << (ex + 12))\n            return TAG_UNDEFINED;\n        r = ((cnv.word1 << 11) | 0x80000000) >> (20 - ex + 11);\n    } else {\n        if (cnv.word0 << (ex - 20))\n            return TAG_UNDEFINED;\n        r = ((cnv.word1 << 11) | 0x80000000) >> (20 - ex + 11);\n        r |= cnv.word0 >> (32 - (ex - 20));\n    }\n\n    if (cnv.word1 >> 31)\n        return TAG_NUMBER(-r);\n    else\n        return TAG_NUMBER(r);\n}\n#else\nstatic inline TValue doubleToInt(NUMBER r) {\n#ifdef PXT64\n    if ((int)r == r)\n        return TAG_NUMBER((int)r);\n#else\n    int ri = ((int)r) << 1;\n    if ((ri >> 1) == r)\n        return (TNumber)(uintptr_t)(ri | 1);\n#endif\n    return TAG_UNDEFINED;\n}\n#endif\n\nTNumber fromDouble(NUMBER r) {\n#ifndef PXT_BOX_DEBUG\n    auto i = doubleToInt(r);\n    if (i)\n        return i;\n#endif\n    if (isnan(r))\n        return TAG_NAN;\n#ifdef PXT64\n    return tvalueFromDouble(r);\n#else\n    BoxedNumber *p = NEW_GC(BoxedNumber);\n    p->num = r;\n    MEMDBG(\"mkNum: %d/1000 => %p\", (int)(r * 1000), p);\n    return (TNumber)p;\n#endif\n}\n\nTNumber fromFloat(float r) {\n    // TODO optimize\n    return fromDouble(r);\n}\n\nTNumber fromInt(int v) {\n    if (canBeTagged(v))\n        return TAG_NUMBER(v);\n    return fromDouble(v);\n}\n\nTNumber fromUInt(unsigned v) {\n#ifndef PXT_BOX_DEBUG\n    if (v <= 0x3fffffff)\n        return TAG_NUMBER(v);\n#endif\n    return fromDouble(v);\n}\n\nTValue fromBool(bool v) {\n    if (v)\n        return TAG_TRUE;\n    else\n        return TAG_FALSE;\n}\n\nTNumber eqFixup(TNumber v) {\n    if (v == TAG_NULL)\n        return TAG_UNDEFINED;\n    if (v == TAG_TRUE)\n        return TAG_NUMBER(1);\n    if (v == TAG_FALSE)\n        return TAG_NUMBER(0);\n    return v;\n}\n\nstatic inline bool eq_core(TValue a, TValue b, ValType ta) {\n#ifndef PXT_BOX_DEBUG\n    auto aa = (intptr_t)a;\n    auto bb = (intptr_t)b;\n\n    // if at least one of the values is tagged, they are not equal\n    if ((aa | bb) & 3)\n        return false;\n#endif\n\n    if (ta == ValType::String)\n        return String_::compare((String)a, (String)b) == 0;\n    else if (ta == ValType::Number)\n        return toDouble(a) == toDouble(b);\n    else\n        return a == b;\n}\n\nbool eqq_bool(TValue a, TValue b) {\n    if (a == TAG_NAN || b == TAG_NAN)\n        return false;\n\n    if (a == b)\n        return true;\n\n    if (bothNumbers(a, b))\n        return false;\n\n    ValType ta = valType(a);\n    ValType tb = valType(b);\n\n    if (ta != tb)\n        return false;\n\n    return eq_core(a, b, ta);\n}\n\nbool eq_bool(TValue a, TValue b) {\n    if (a == TAG_NAN || b == TAG_NAN)\n        return false;\n\n    if (eqFixup(a) == eqFixup(b))\n        return true;\n\n    if (bothNumbers(a, b))\n        return false;\n\n    ValType ta = valType(a);\n    ValType tb = valType(b);\n\n    if ((ta == ValType::String && tb == ValType::Number) ||\n        (tb == ValType::String && ta == ValType::Number))\n        return toDouble(a) == toDouble(b);\n\n    if (ta == ValType::Boolean) {\n        a = eqFixup(a);\n        ta = ValType::Number;\n    }\n    if (tb == ValType::Boolean) {\n        b = eqFixup(b);\n        tb = ValType::Number;\n    }\n\n    if (ta != tb)\n        return false;\n\n    return eq_core(a, b, ta);\n}\n\n// TODO move to assembly\n//%\nbool switch_eq(TValue a, TValue b) {\n    if (eq_bool(a, b)) {\n        return true;\n    }\n    return false;\n}\n\n} // namespace pxt\n\n#define NUMOP(op) return fromDouble(toDouble(a) op toDouble(b));\n#define BITOP(op) return fromInt(toInt(a) op toInt(b));\nnamespace numops {\n\nint toBool(TValue v) {\n    if (isTagged(v)) {\n        if (v == TAG_FALSE || v == TAG_UNDEFINED || v == TAG_NAN || v == TAG_NULL ||\n            v == TAG_NUMBER(0))\n            return 0;\n        else\n            return 1;\n    }\n\n    ValType t = valType(v);\n    if (t == ValType::String) {\n        String s = (String)v;\n        if (IS_EMPTY(s))\n            return 0;\n    } else if (t == ValType::Number) {\n        auto x = toDouble(v);\n        if (isnan(x) || x == 0.0 || x == -0.0)\n            return 0;\n        else\n            return 1;\n    }\n\n    return 1;\n}\n\nint toBoolDecr(TValue v) {\n    if (v == TAG_TRUE)\n        return 1;\n    if (v == TAG_FALSE)\n        return 0;\n    return toBool(v);\n}\n\n// The integer, non-overflow case for add/sub/bit opts is handled in assembly\n\n#ifdef PXT_VM\n#define NUMOP2(op)                                                                                 \\\n    if (bothNumbers(a, b)) {                                                                       \\\n        auto tmp = (int64_t)numValue(a) op(int64_t) numValue(b);                                   \\\n        if ((int)tmp == tmp)                                                                       \\\n            return TAG_NUMBER((int)tmp);                                                           \\\n    }                                                                                              \\\n    NUMOP(op)\n#else\n#define NUMOP2(op) NUMOP(op)\n#endif\n\n//%\nTNumber adds(TNumber a, TNumber b){NUMOP2(+)}\n\n//%\nTNumber subs(TNumber a, TNumber b){NUMOP2(-)}\n\n//%\nTNumber muls(TNumber a, TNumber b) {\n    if (bothNumbers(a, b)) {\n#ifdef PXT64\n        auto tmp = (int64_t)numValue(a) * (int64_t)numValue(b);\n        if ((int)tmp == tmp)\n            return TAG_NUMBER((int)tmp);\n#else\n        int aa = (int)a;\n        int bb = (int)b;\n        // if both operands fit 15 bits, the result will not overflow int\n        if ((aa >> 15 == 0 || aa >> 15 == -1) && (bb >> 15 == 0 || bb >> 15 == -1)) {\n            // it may overflow 31 bit int though - use fromInt to convert properly\n            return fromInt((aa >> 1) * (bb >> 1));\n        }\n#endif\n    }\n    NUMOP(*)\n}\n\n//%\nTNumber div(TNumber a, TNumber b) {\n    if (b == TAG_NUMBER(1))\n        return a;\n    NUMOP(/)\n}\n\n//%\nTNumber mod(TNumber a, TNumber b) {\n    if (isInt(a) && isInt(b) && numValue(b))\n        BITOP(%)\n    return fromDouble(fmod(toDouble(a), toDouble(b)));\n}\n\n//%\nTNumber lsls(TNumber a, TNumber b) {\n    return fromInt(toInt(a) << (toInt(b) & 0x1f));\n}\n\n//%\nTNumber lsrs(TNumber a, TNumber b) {\n    return fromUInt(toUInt(a) >> (toUInt(b) & 0x1f));\n}\n\n//%\nTNumber asrs(TNumber a, TNumber b) {\n    return fromInt(toInt(a) >> (toInt(b) & 0x1f));\n}\n\n//%\nTNumber eors(TNumber a, TNumber b){BITOP(^)}\n\n//%\nTNumber orrs(TNumber a, TNumber b){BITOP(|)}\n\n//%\nTNumber bnot(TNumber a) {\n    return fromInt(~toInt(a));\n}\n\n//%\nTNumber ands(TNumber a, TNumber b) {\n    BITOP(&)\n}\n\n#ifdef PXT64\n#define CMPOP_RAW(op, t, f)                                                                        \\\n    if (bothNumbers(a, b))                                                                         \\\n        return numValue(a) op numValue(b) ? t : f;                                                 \\\n    int cmp = valCompare(a, b);                                                                    \\\n    return cmp != -2 && cmp op 0 ? t : f;\n#else\n#define CMPOP_RAW(op, t, f)                                                                        \\\n    if (bothNumbers(a, b))                                                                         \\\n        return (intptr_t)a op((intptr_t)b) ? t : f;                                                \\\n    int cmp = valCompare(a, b);                                                                    \\\n    return cmp != -2 && cmp op 0 ? t : f;\n#endif\n\n#define CMPOP(op) CMPOP_RAW(op, TAG_TRUE, TAG_FALSE)\n\n// 7.2.13 Abstract Relational Comparison\nstatic int valCompare(TValue a, TValue b) {\n    if (a == TAG_NAN || b == TAG_NAN)\n        return -2;\n\n    ValType ta = valType(a);\n    ValType tb = valType(b);\n\n    if (ta == ValType::String && tb == ValType::String)\n        return String_::compare((String)a, (String)b);\n\n    if (a == b)\n        return 0;\n\n    auto da = toDouble(a);\n    auto db = toDouble(b);\n\n    if (isnan(da) || isnan(db))\n        return -2;\n\n    if (da < db)\n        return -1;\n    else if (da > db)\n        return 1;\n    else\n        return 0;\n}\n\n//%\nbool lt_bool(TNumber a, TNumber b){CMPOP_RAW(<, true, false)}\n\n//%\nTNumber le(TNumber a, TNumber b){CMPOP(<=)}\n\n//%\nTNumber lt(TNumber a, TNumber b){CMPOP(<)}\n\n//%\nTNumber ge(TNumber a, TNumber b){CMPOP(>=)}\n\n//%\nTNumber gt(TNumber a, TNumber b){CMPOP(>)}\n\n//%\nTNumber eq(TNumber a, TNumber b) {\n    return pxt::eq_bool(a, b) ? TAG_TRUE : TAG_FALSE;\n}\n\n//%\nTNumber neq(TNumber a, TNumber b) {\n    return !pxt::eq_bool(a, b) ? TAG_TRUE : TAG_FALSE;\n}\n\n//%\nTNumber eqq(TNumber a, TNumber b) {\n    return pxt::eqq_bool(a, b) ? TAG_TRUE : TAG_FALSE;\n}\n\n//%\nTNumber neqq(TNumber a, TNumber b) {\n    return !pxt::eqq_bool(a, b) ? TAG_TRUE : TAG_FALSE;\n}\n\n// How many significant digits mycvt() should output.\n// This cannot be more than 15, as this is the most that can be accurately represented\n// in 64 bit double. Otherwise this code may crash.\n#define DIGITS 15\n\nstatic const uint64_t pows[] = {\n    1LL,           10LL,           100LL,           1000LL,           10000LL,\n    100000LL,      1000000LL,      10000000LL,      100000000LL,      1000000000LL,\n    10000000000LL, 100000000000LL, 1000000000000LL, 10000000000000LL, 100000000000000LL,\n};\n\n// The basic idea is we convert d to a 64 bit integer with DIGITS\n// digits, and then print it out, putting dot in the right place.\n\nvoid mycvt(NUMBER d, char *buf) {\n    if (d < 0) {\n        *buf++ = '-';\n        d = -d;\n    }\n\n    if (!d) {\n        *buf++ = '0';\n        *buf++ = 0;\n        return;\n    }\n\n    int pw = (int)log10(d);\n    int e = 1;\n\n    // if outside 1e-6 -- 1e21 range, we use the e-notation\n    if (d < 1e-6 || d > 1e21) {\n        // normalize number to 1.XYZ, save e, and reset pw\n        if (pw < 0)\n            d *= p10(-pw);\n        else\n            d /= p10(pw);\n        e = pw;\n        pw = 0;\n    }\n\n    int trailingZ = 0;\n    int dotAfter = pw + 1; // at which position the dot should be in the number\n\n    uint64_t dd;\n\n    // normalize number to be integer with exactly DIGITS digits\n    if (pw >= DIGITS) {\n        // if the number is larger than DIGITS, we need trailing zeroes\n        trailingZ = pw - DIGITS + 1;\n        dd = (uint64_t)(d / p10(trailingZ) + 0.5);\n    } else {\n        dd = (uint64_t)(d * p10(DIGITS - pw - 1) + 0.5);\n    }\n\n    // if number is less than 1, we need 0.00...00 at the beginning\n    if (dotAfter < 1) {\n        *buf++ = '0';\n        *buf++ = '.';\n        int n = -dotAfter;\n        while (n--)\n            *buf++ = '0';\n    }\n\n    // now print out the actual number\n    for (int i = DIGITS - 1; i >= 0; i--) {\n        uint64_t q = pows[i];\n        // this may be faster than fp-division and fmod(); or maybe not\n        // anyways, it works\n        int k = '0';\n        while (dd >= q) {\n            dd -= q;\n            k++;\n        }\n        *buf++ = k;\n        // if we're after dot, and what's left is zeroes, stop\n        if (dd == 0 && (DIGITS - i) >= dotAfter)\n            break;\n        // print the dot, if we arrived at it\n        if ((DIGITS - i) == dotAfter)\n            *buf++ = '.';\n    }\n\n    // print out remaining trailing zeroes if any\n    while (trailingZ-- > 0)\n        *buf++ = '0';\n\n    // if we used e-notation, handle that\n    if (e != 1) {\n        *buf++ = 'e';\n        if (e > 0)\n            *buf++ = '+';\n        itoa(e, buf);\n    } else {\n        *buf = 0;\n    }\n}\n\n#if 0\n//%\nTValue floatAsInt(TValue x) {\n    return doubleToInt(toDouble(x));\n}\n\n//% shim=numops::floatAsInt\nfunction floatAsInt(v: number): number { return 0 }\n\nfunction testInt(i: number) {\n    if (floatAsInt(i) != i)\n        control.panic(101)\n    if (floatAsInt(i + 0.5) != null)\n        control.panic(102)\n    if (floatAsInt(i + 0.00001) != null)\n        control.panic(103)\n}\n\nfunction testFloat(i: number) {\n    if (floatAsInt(i) != null)\n        control.panic(104)\n}\n\nfunction testFloatAsInt() {\n    for (let i = 0; i < 0xffff; ++i) {\n        testInt(i)\n        testInt(-i)\n        testInt(i * 10000)\n        testInt(i << 12)\n        testInt(i + 0x3fff0001)\n        testInt(-i - 0x3fff0002)\n        testFloat(i + 0x3fffffff + 1)\n        testFloat((i + 10000) * 1000000)\n    }\n}\n#endif\n\nString toString(TValue v) {\n    ValType t = valType(v);\n\n    if (t == ValType::String) {\n        return (String)v;\n    } else if (t == ValType::Number) {\n        char buf[64];\n\n        if (isInt(v)) {\n            itoa(numValue(v), buf);\n            return mkStringCore(buf);\n        }\n\n        if (v == TAG_NAN)\n            return (String)(void *)sNaN;\n\n        auto x = toDouble(v);\n\n#ifdef PXT_BOX_DEBUG\n        if (x == (int)x) {\n            itoa((int)x, buf);\n            return mkStringCore(buf);\n        }\n#endif\n\n        if (isinf(x)) {\n            if (x < 0)\n                return (String)(void *)sMInf;\n            else\n                return (String)(void *)sInf;\n        } else if (isnan(x)) {\n            return (String)(void *)sNaN;\n        }\n        mycvt(x, buf);\n\n        return mkStringCore(buf);\n    } else if (t == ValType::Function) {\n        return (String)(void *)sFunction;\n    } else {\n        if (v == TAG_UNDEFINED)\n            return (String)(void *)sUndefined;\n        else if (v == TAG_FALSE)\n            return (String)(void *)sFalse;\n        else if (v == TAG_NAN)\n            return (String)(void *)sNaN;\n        else if (v == TAG_TRUE)\n            return (String)(void *)sTrue;\n        else if (v == TAG_NULL)\n            return (String)(void *)sNull;\n        return (String)(void *)sObject;\n    }\n}\n\n} // namespace numops\n\nnamespace Math_ {\n//%\nTNumber pow(TNumber x, TNumber y) {\n#ifdef PXT_POWI\n    // regular pow() from math.h is 4k of code, but it can\n    // also be expressed as exp(y * log(x)) which is less\n    // performant than pow() but doesn't increase code size\n    double dx = toDouble(x);\n    double dy = toDouble(y);\n\n    // shortcut to integer pow if y is an integer\n    if (::floor(dy) == dy) {\n        return fromDouble(__builtin_powi(dx, dy));\n    }\n    if (dx > 0) {\n        return fromDouble(::exp(dy * ::log(dx)));\n    }\n    if (dx == 0) {\n        if (dy < 0) {\n            // positive infinity\n            return fromDouble(HUGE_VAL);\n        }\n        return x;\n    }\n    return fromDouble(::log(dx));\n#else\n    return fromDouble(::pow(toDouble(x), toDouble(y)));\n#endif\n}\n\nNUMBER randomDouble() {\n    return getRandom(UINT_MAX) / ((NUMBER)UINT_MAX + 1) +\n           getRandom(0xffffff) / ((NUMBER)UINT_MAX * 0xffffff);\n}\n\n//%\nTNumber random() {\n    return fromDouble(randomDouble());\n}\n\n//%\nTNumber randomRange(TNumber min, TNumber max) {\n    if (isInt(min) && isInt(max)) {\n        int mini = numValue(min);\n        int maxi = numValue(max);\n        if (mini > maxi) {\n            int temp = mini;\n            mini = maxi;\n            maxi = temp;\n        }\n        if (maxi == mini)\n            return fromInt(mini);\n        else\n            return fromInt(mini + getRandom(maxi - mini));\n    } else {\n        auto mind = toDouble(min);\n        auto maxd = toDouble(max);\n        if (mind > maxd) {\n            auto temp = mind;\n            mind = maxd;\n            maxd = temp;\n        }\n        if (maxd == mind)\n            return fromDouble(mind);\n        else {\n            return fromDouble(mind + randomDouble() * (maxd - mind));\n        }\n    }\n}\n\n#define SINGLE(op) return fromDouble(::op(toDouble(x)));\n\n//%\nTNumber log(TNumber x){SINGLE(log)}\n\n//%\nTNumber log10(TNumber x){SINGLE(log10)}\n\n//%\nTNumber floor(TNumber x){SINGLE(floor)}\n\n//%\nTNumber ceil(TNumber x){SINGLE(ceil)}\n\n//%\nTNumber trunc(TNumber x){SINGLE(trunc)}\n\n//%\nTNumber round(TNumber x) {\n    // In C++, round(-1.5) == -2, while in JS, round(-1.5) == -1. Align to the JS convention for\n    // consistency between simulator and device. The following does rounding with ties (x.5) going\n    // towards positive infinity.\n    return fromDouble(::floor(toDouble(x) + 0.5));\n}\n\n//%\nint imul(int x, int y) {\n    return x * y;\n}\n\n//%\nint idiv(int x, int y) {\n    return x / y;\n}\n} // namespace Math_\n\nnamespace Array_ {\nRefCollection *mk() {\n    auto r = NEW_GC(RefCollection);\n    MEMDBG(\"mkColl: => %p\", r);\n    return r;\n}\nint length(RefCollection *c) {\n    return c->length();\n}\nvoid setLength(RefCollection *c, int newLength) {\n    c->setLength(newLength);\n}\nvoid push(RefCollection *c, TValue x) {\n    c->head.push(x);\n}\nTValue pop(RefCollection *c) {\n    return c->head.pop();\n}\nTValue getAt(RefCollection *c, int x) {\n    return c->head.get(x);\n}\nvoid setAt(RefCollection *c, int x, TValue y) {\n    c->head.set(x, y);\n}\nTValue removeAt(RefCollection *c, int x) {\n    return c->head.remove(x);\n}\nvoid insertAt(RefCollection *c, int x, TValue value) {\n    c->head.insert(x, value);\n}\nint indexOf(RefCollection *c, TValue x, int start) {\n    auto data = c->head.getData();\n    auto len = c->head.getLength();\n    for (unsigned i = 0; i < len; i++) {\n        if (pxt::eq_bool(data[i], x)) {\n            return (int)i;\n        }\n    }\n    return -1;\n}\nbool removeElement(RefCollection *c, TValue x) {\n    int idx = indexOf(c, x, 0);\n    if (idx >= 0) {\n        decr(removeAt(c, idx));\n        return 1;\n    }\n    return 0;\n}\n} // namespace Array_\n\nnamespace pxt {\nint debugFlags;\n\n//%\nvoid *ptrOfLiteral(int offset);\n\n#ifdef PXT_VM\nunsigned programSize() {\n    return 0;\n}\n#else\n//%\nunsigned programSize() {\n    return bytecode[17] * 8;\n}\n#endif\n\nvoid deepSleep() __attribute__((weak));\n//%\nvoid deepSleep() {}\n\nint *getBootloaderConfigData() __attribute__((weak));\nint *getBootloaderConfigData() {\n    return NULL;\n}\n\n//%\nint getConfig(int key, int defl) {\n#ifdef PXT_VM\n    if (!vmImg)\n        return defl;\n    int *cfgData = vmImg->configData;\n#else\n    int *cfgData = NULL;\n    if (bytecode) {\n        cfgData = *(int **)&bytecode[18];\n    } else {\n        // This happens when getConfig() is called before the TypeScript\n        // program starts (exec_binary()). One example is overriding heap size with:\n        // namespace userconfig { export const SYSTEM_HEAP_BYTES = 10000 }\n        unsigned *pc = (unsigned *)functionsAndBytecode;\n        if (*pc++ == 0x4210) {\n            uint16_t *bcode = *((uint16_t **)pc++);\n            cfgData = *(int **)&bcode[18];\n        }\n    }\n#endif\n\n    if (cfgData) {\n        for (int i = 0;; i += 2) {\n            if (cfgData[i] == key)\n                return cfgData[i + 1];\n            if (cfgData[i] == 0)\n                break;\n        }\n    }\n\n    cfgData = getBootloaderConfigData();\n\n    if (cfgData) {\n        for (int i = 0;; i += 2) {\n            if (cfgData[i] == key)\n                return cfgData[i + 1];\n            if (cfgData[i] == 0)\n                break;\n        }\n    }\n\n    return defl;\n}\n\n} // namespace pxt\n\nnamespace pxtrt {\n//%\nTValue ldlocRef(RefRefLocal *r) {\n    return r->v;\n}\n\n//%\nvoid stlocRef(RefRefLocal *r, TValue v) {\n    r->v = v;\n}\n\n//%\nRefRefLocal *mklocRef() {\n    auto r = NEW_GC(RefRefLocal);\n    MEMDBG(\"mklocRef: => %p\", r);\n    return r;\n}\n\n// Store a captured local in a closure. It returns the action, so it can be chained.\n//%\nRefAction *stclo(RefAction *a, int idx, TValue v) {\n    // DBG(\"STCLO \"); a->print(); DBG(\"@%d = %p\\n\", idx, (void*)v);\n    a->stCore(idx, v);\n    return a;\n}\n\n//%\nvoid panic(int code) {\n    soft_panic(code);\n}\n\n//%\nString emptyToNull(String s) {\n    if (!s || IS_EMPTY(s))\n        return NULL;\n    return s;\n}\n\n//%\nint ptrToBool(TValue p) {\n    if (p) {\n        decr(p);\n        return 1;\n    } else {\n        return 0;\n    }\n}\n\nRefMap *mkMap() {\n    auto r = NEW_GC(RefMap);\n    MEMDBG(\"mkMap: => %p\", r);\n    return r;\n}\n\nTValue mapGetByString(RefMap *map, String key) {\n    int i = map->findIdx(key);\n    if (i < 0) {\n        return 0;\n    }\n    return map->values.get(i);\n}\n\n#ifdef PXT_VM\n#define IFACE_MEMBER_NAMES vmImg->ifaceMemberNames\n#else\n#define IFACE_MEMBER_NAMES *(uintptr_t **)&bytecode[22]\n#endif\n\nint lookupMapKey(String key) {\n    auto arr = IFACE_MEMBER_NAMES;\n    auto len = *arr++;\n    int l = 1U; // skip index 0 - it's invalid\n    int r = (int)len - 1;\n    auto ikey = (uintptr_t)key;\n    if (arr[l] <= ikey && ikey <= arr[r]) {\n        while (l <= r) {\n            auto m = (l + r) >> 1;\n            if (arr[m] == ikey)\n                return m;\n            else if (arr[m] < ikey)\n                l = m + 1;\n            else\n                r = m - 1;\n        }\n    } else {\n        while (l <= r) {\n            int m = (l + r) >> 1;\n            auto cmp = String_::compare((String)arr[m], key);\n            if (cmp == 0)\n                return m;\n            else if (cmp < 0)\n                l = m + 1;\n            else\n                r = m - 1;\n        }\n    }\n    return 0;\n}\n\nTValue mapGet(RefMap *map, unsigned key) {\n    auto arr = (String *)IFACE_MEMBER_NAMES;\n    auto r = mapGetByString(map, arr[key + 1]);\n    map->unref();\n    return r;\n}\n\nvoid mapSetByString(RefMap *map, String key, TValue val) {\n    int i = map->findIdx(key);\n    if (i < 0) {\n        map->keys.push((TValue)key);\n        map->values.push(val);\n    } else {\n        map->values.set(i, val);\n    }\n}\n\nvoid mapSet(RefMap *map, unsigned key, TValue val) {\n    auto arr = (String *)IFACE_MEMBER_NAMES;\n    mapSetByString(map, arr[key + 1], val);\n    decr(val);\n    map->unref();\n}\n\n//\n// Debugger\n//\n\n// This is only to be called once at the beginning of lambda function\n//%\nvoid *getGlobalsPtr() {\n#ifdef DEVICE_GROUP_ID_USER\n    fiber_set_group(DEVICE_GROUP_ID_USER);\n#endif\n\n    return globals;\n}\n\n//%\nvoid runtimeWarning(String s) {\n    // noop for now\n}\n} // namespace pxtrt\n#endif\n\nnamespace pxt {\n\nvoid doNothing() {}\n\n//%\nValType valType(TValue v) {\n    if (isTagged(v)) {\n        if (!v)\n            return ValType::Undefined;\n\n        if (isInt(v) || v == TAG_NAN)\n            return ValType::Number;\n        if (v == TAG_TRUE || v == TAG_FALSE)\n            return ValType::Boolean;\n        else if (v == TAG_NULL)\n            return ValType::Object;\n        else {\n            oops(1);\n            return ValType::Object;\n        }\n#ifdef PXT64\n    } else if (isDouble(v)) {\n        return ValType::Number;\n#endif\n    } else {\n        auto vt = getVTable((RefObject *)v);\n        if (vt->magic == VTABLE_MAGIC)\n            return vt->objectType;\n        else\n            return ValType::Object;\n    }\n}\n\nPXT_DEF_STRING(sObjectTp, \"object\")\nPXT_DEF_STRING(sBooleanTp, \"boolean\")\nPXT_DEF_STRING(sStringTp, \"string\")\nPXT_DEF_STRING(sNumberTp, \"number\")\nPXT_DEF_STRING(sFunctionTp, \"function\")\nPXT_DEF_STRING(sUndefinedTp, \"undefined\")\n\n//% expose\nString typeOf(TValue v) {\n    switch (valType(v)) {\n    case ValType::Undefined:\n        return (String)sUndefinedTp;\n    case ValType::Boolean:\n        return (String)sBooleanTp;\n    case ValType::Number:\n        return (String)sNumberTp;\n    case ValType::String:\n        return (String)sStringTp;\n    case ValType::Object:\n        return (String)sObjectTp;\n    case ValType::Function:\n        return (String)sFunctionTp;\n    default:\n        oops(2);\n        return 0;\n    }\n}\n\n// Maybe in future we will want separate print methods; for now ignore\nvoid anyPrint(TValue v) {\n    if (valType(v) == ValType::Object) {\n        if (isRefCounted(v)) {\n            auto o = (RefObject *)v;\n            auto vt = getVTable(o);\n            auto meth = ((RefObjectMethod)vt->methods[1]);\n            if ((void *)meth == (void *)&anyPrint)\n                DMESG(\"[RefObject vt=%p cl=%d sz=%d]\", o->vtable, vt->classNo, vt->numbytes);\n            else\n                meth(o);\n        } else {\n            DMESG(\"[Native %p]\", v);\n        }\n    } else {\n#ifndef X86_64\n        String s = numops::toString(v);\n        DMESG(\"[%s %p = %s]\", pxt::typeOf(v)->getUTF8Data(), v, s->getUTF8Data());\n        decr((TValue)s);\n#endif\n    }\n}\n\nstatic void dtorDoNothing() {}\n\n#define PRIM_VTABLE(name, objectTp, tp, szexpr)                                                    \\\n    static uint32_t name##_size(tp *p) {                                                           \\\n        return TOWORDS(sizeof(tp) + szexpr);                                                       \\\n    }                                                                                              \\\n    DEF_VTABLE(name##_vt, tp, objectTp, (void *)&dtorDoNothing, (void *)&anyPrint, 0,              \\\n               (void *)&name##_size)\n\n#define NOOP ((void)0)\n\n#define STRING_VT(name, fix, scan, gcsize, data, utfsize, length, dataAt)                          \\\n    static uint32_t name##_gcsize(BoxedString *p) {                                                \\\n        return TOWORDS(sizeof(void *) + (gcsize));                                                 \\\n    }                                                                                              \\\n    static void name##_gcscan(BoxedString *p) {                                                    \\\n        scan;                                                                                      \\\n    }                                                                                              \\\n    static const char *name##_data(BoxedString *p) {                                               \\\n        fix;                                                                                       \\\n        return data;                                                                               \\\n    }                                                                                              \\\n    static uint32_t name##_utfsize(BoxedString *p) {                                               \\\n        fix;                                                                                       \\\n        return utfsize;                                                                            \\\n    }                                                                                              \\\n    static uint32_t name##_length(BoxedString *p) {                                                \\\n        fix;                                                                                       \\\n        return length;                                                                             \\\n    }                                                                                              \\\n    static const char *name##_dataAt(BoxedString *p, uint32_t idx) {                               \\\n        fix;                                                                                       \\\n        return dataAt;                                                                             \\\n    }                                                                                              \\\n    DEF_VTABLE(name##_vt, BoxedString, ValType::String, (void *)&dtorDoNothing, (void *)&anyPrint, \\\n               (void *)&name##_gcscan, (void *)&name##_gcsize, (void *)&name##_data,               \\\n               (void *)&name##_utfsize, (void *)&name##_length, (void *)&name##_dataAt)\n\nvoid gcMarkArray(void *data);\nvoid gcScan(TValue v);\n\n#if PXT_UTF8\nstatic const char *skipLookup(BoxedString *p, uint32_t idx, int packed) {\n    if (idx > p->skip.length)\n        return NULL;\n    auto ent = idx / PXT_STRING_SKIP_INCR;\n    auto data = packed ? PXT_SKIP_DATA_PACK(p) : PXT_SKIP_DATA_IND(p);\n    auto size = p->skip.size;\n    if (ent) {\n        auto off = packed ? p->skip_pack.list[ent - 1] : p->skip.list[ent - 1];\n        data += off;\n        size -= off;\n        idx &= PXT_STRING_SKIP_INCR - 1;\n    }\n    return utf8Skip(data, size, idx);\n}\n\nextern LLSegment workQueue;\n\nstatic uint32_t fixSize(BoxedString *p, uint32_t *len) {\n    uint32_t tlen = 0;\n    uint32_t sz = 0;\n    if (workQueue.getLength())\n        oops(81);\n    workQueue.push((TValue)p);\n    while (workQueue.getLength()) {\n        p = (BoxedString *)workQueue.pop();\n        if (IS_CONS(p)) {\n            workQueue.push((TValue)p->cons.right);\n            workQueue.push((TValue)p->cons.left);\n        } else {\n            tlen += p->getLength();\n            sz += p->getUTF8Size();\n        }\n    }\n    *len = tlen;\n    return sz;\n}\n\nstatic void fixCopy(BoxedString *p, char *dst) {\n    if (workQueue.getLength())\n        oops(81);\n\n    workQueue.push((TValue)p);\n    while (workQueue.getLength()) {\n        p = (BoxedString *)workQueue.pop();\n        if (IS_CONS(p)) {\n            workQueue.push((TValue)p->cons.right);\n            workQueue.push((TValue)p->cons.left);\n        } else {\n            auto sz = p->getUTF8Size();\n            memcpy(dst, p->getUTF8Data(), sz);\n            dst += sz;\n        }\n    }\n}\n\n// switches CONS representation into skip list representation\n// does not switch representation of CONS' children\nstatic void fixCons(BoxedString *r) {\n    uint32_t length = 0;\n    auto sz = fixSize(r, &length);\n    auto numSkips = length / PXT_STRING_SKIP_INCR;\n    // allocate first, while [r] still holds references to its children\n    // because allocation might trigger GC\n    auto data = (uint16_t *)gcAllocateArray(numSkips * 2 + sz + 1);\n    // copy, while [r] is still cons\n    fixCopy(r, (char *)(data + numSkips));\n    // now, set [r] up properly\n    r->vtable = &string_skiplist16_vt;\n    r->skip.size = sz;\n    r->skip.length = length;\n    r->skip.list = data;\n    setupSkipList(r, NULL, 0);\n}\n#endif\n\nSTRING_VT(string_inline_ascii, NOOP, NOOP, 2 + p->ascii.length + 1, p->ascii.data, p->ascii.length,\n          p->ascii.length, idx <= p->ascii.length ? p->ascii.data + idx : NULL)\n#if PXT_UTF8\nSTRING_VT(string_inline_utf8, NOOP, NOOP, 2 + p->utf8.size + 1, p->utf8.data, p->utf8.size,\n          utf8Len(p->utf8.data, p->utf8.size), utf8Skip(p->utf8.data, p->utf8.size, idx))\nSTRING_VT(string_skiplist16, NOOP, if (p->skip.list) gcMarkArray(p->skip.list), 2 * sizeof(void *),\n          PXT_SKIP_DATA_IND(p), p->skip.size, p->skip.length, skipLookup(p, idx, 0))\nSTRING_VT(string_skiplist16_packed, NOOP, NOOP,\n          2 + 2 + PXT_NUM_SKIP_ENTRIES(p) * 2 + p->skip.size + 1, PXT_SKIP_DATA_PACK(p),\n          p->skip.size, p->skip.length, skipLookup(p, idx, 1))\nSTRING_VT(string_cons, fixCons(p), (gcScan((TValue)p->cons.left), gcScan((TValue)p->cons.right)),\n          2 * sizeof(void *), PXT_SKIP_DATA_IND(p), p->skip.size, p->skip.length,\n          skipLookup(p, idx, 0))\n#endif\n\nPRIM_VTABLE(number, ValType::Number, BoxedNumber, 0)\nPRIM_VTABLE(buffer, ValType::Object, BoxedBuffer, p->length)\n// PRIM_VTABLE(action, ValType::Function, RefAction, )\n\nvoid failedCast(TValue v, void *addr) {\n    DMESG(\"failed type check for %p @%p\", v, addr);\n    auto vt = getAnyVTable(v);\n    if (vt) {\n        DMESG(\"VT %p - objtype %d classNo %d\", vt, vt->objectType, vt->classNo);\n    }\n\n    int code;\n    if (v == TAG_NULL)\n        code = PANIC_CAST_FROM_NULL;\n    else\n        code = PANIC_CAST_FIRST + (int)valType(v);\n    soft_panic(code);\n}\n\nvoid missingProperty(TValue v) {\n    DMESG(\"missing property on %p\", v);\n    soft_panic(PANIC_MISSING_PROPERTY);\n}\n\n#ifdef PXT_PROFILE\nstruct PerfCounter *perfCounters;\n\nstruct PerfCounterInfo {\n    uint32_t numPerfCounters;\n    char *perfCounterNames[0];\n};\n\n#define PERF_INFO ((PerfCounterInfo *)(((uintptr_t *)bytecode)[13]))\n\nvoid initPerfCounters() {\n    auto n = PERF_INFO->numPerfCounters;\n    perfCounters = new PerfCounter[n];\n    memset(perfCounters, 0, n * sizeof(PerfCounter));\n}\n\nvoid dumpPerfCounters() {\n    auto info = PERF_INFO;\n    DMESG(\"calls,us,name\");\n    for (uint32_t i = 0; i < info->numPerfCounters; ++i) {\n        auto c = &perfCounters[i];\n        DMESG(\"%d,%d,%s\", c->numstops, c->value, info->perfCounterNames[i]);\n        c->value = 0;\n        c->numstops = 0;\n    }\n}\n\nvoid startPerfCounter(PerfCounters n) {\n    if (!perfCounters)\n        return;\n    auto c = &perfCounters[(uint32_t)n];\n    if (c->start)\n        oops(50);\n    c->start = PERF_NOW();\n}\n\nvoid stopPerfCounter(PerfCounters n) {\n    if (!perfCounters)\n        return;\n    auto c = &perfCounters[(uint32_t)n];\n    if (!c->start)\n        oops(51);\n    c->value += ((PERF_NOW() - c->start) & PERF_NOW_MASK) / PERF_NOW_SCALE;\n    c->start = 0;\n    c->numstops++;\n}\n#endif\n\n// Exceptions\n\n#ifndef PXT_EXN_CTX\n#define PXT_EXN_CTX() getThreadContext()\n#endif\n\ntypedef void (*RestoreStateType)(TryFrame *, ThreadContext *);\n#ifndef pxt_restore_exception_state\n#define pxt_restore_exception_state ((RestoreStateType)(((uintptr_t *)bytecode)[14]))\n#endif\n\n//%\nTryFrame *beginTry() {\n    auto ctx = PXT_EXN_CTX();\n    auto frame = (TryFrame *)app_alloc(sizeof(TryFrame));\n    frame->parent = ctx->tryFrame;\n    ctx->tryFrame = frame;\n    return frame;\n}\n\n//% expose\nvoid endTry() {\n    auto ctx = PXT_EXN_CTX();\n    auto f = ctx->tryFrame;\n    if (!f)\n        oops(51);\n    ctx->tryFrame = f->parent;\n    app_free(f);\n}\n\n//% expose\nvoid throwValue(TValue v) {\n    auto ctx = PXT_EXN_CTX();\n    auto f = ctx->tryFrame;\n    if (!f) {\n        DMESG(\"unhandled exception, value:\");\n        anyPrint(v);\n        soft_panic(PANIC_UNHANDLED_EXCEPTION);\n    }\n    ctx->tryFrame = f->parent;\n    TryFrame copy = *f;\n    app_free(f);\n    ctx->thrownValue = v;\n    pxt_restore_exception_state(&copy, ctx);\n}\n\n//% expose\nTValue getThrownValue() {\n    auto ctx = PXT_EXN_CTX();\n    auto v = ctx->thrownValue;\n    ctx->thrownValue = TAG_NON_VALUE;\n    if (v == TAG_NON_VALUE)\n        oops(51);\n    return v;\n}\n\n//% expose\nvoid endFinally() {\n    auto ctx = PXT_EXN_CTX();\n    if (ctx->thrownValue == TAG_NON_VALUE)\n        return;\n    throwValue(getThrownValue());\n}\n\n// https://en.wikipedia.org/wiki/Fowler%E2%80%93Noll%E2%80%93Vo_hash_function\nuint32_t hash_fnv1(const void *data, unsigned len) {\n    const uint8_t *d = (const uint8_t *)data;\n    uint32_t h = 0x811c9dc5;\n    while (len--)\n        h = (h * 0x1000193) ^ *d++;\n    return h;\n}\n\n// redefined in melody.cpp\n__attribute__((weak)) int redirectSamples(int16_t *dst, int numsamples, int samplerate) {\n    return 0;\n}\n\n} // namespace pxt\n","dal.d.ts":"// Auto-generated. Do not edit.\ndeclare const enum DAL {\n    // /libraries/codal-core/inc/core/CodalComponent.h\n    DEVICE_ID_BUTTON_A = 1,\n    DEVICE_ID_BUTTON_B = 2,\n    DEVICE_ID_BUTTON_AB = 3,\n    DEVICE_ID_BUTTON_RESET = 4,\n    DEVICE_ID_ACCELEROMETER = 5,\n    DEVICE_ID_COMPASS = 6,\n    DEVICE_ID_DISPLAY = 7,\n    DEVICE_ID_THERMOMETER = 8,\n    DEVICE_ID_RADIO = 9,\n    DEVICE_ID_RADIO_DATA_READY = 10,\n    DEVICE_ID_MULTIBUTTON_ATTACH = 11,\n    DEVICE_ID_SERIAL = 12,\n    DEVICE_ID_GESTURE = 13,\n    DEVICE_ID_SYSTEM_TIMER = 14,\n    DEVICE_ID_SCHEDULER = 15,\n    DEVICE_ID_COMPONENT = 16,\n    DEVICE_ID_LIGHT_SENSOR = 17,\n    DEVICE_ID_TOUCH_SENSOR = 18,\n    DEVICE_ID_SYSTEM_DAC = 19,\n    DEVICE_ID_SYSTEM_MICROPHONE = 20,\n    DEVICE_ID_SYSTEM_LEVEL_DETECTOR = 21,\n    DEVICE_ID_SYSTEM_LEVEL_DETECTOR_SPL = 22,\n    DEVICE_ID_MSC = 23,\n    DEVICE_ID_SPI = 24,\n    DEVICE_ID_DISTANCE = 25,\n    DEVICE_ID_GYROSCOPE = 26,\n    DEVICE_ID_HUMIDITY = 27,\n    DEVICE_ID_PRESSURE = 28,\n    DEVICE_ID_SINGLE_WIRE_SERIAL = 29,\n    DEVICE_ID_JACDAC = 30,\n    DEVICE_ID_JACDAC_PHYS = 31,\n    DEVICE_ID_JACDAC_CONTROL_SERVICE = 32,\n    DEVICE_ID_JACDAC_CONFIGURATION_SERVICE = 33,\n    DEVICE_ID_SYSTEM_ADC = 34,\n    DEVICE_ID_PULSE_IN = 35,\n    DEVICE_ID_USB = 36,\n    DEVICE_ID_SPLITTER = 37,\n    DEVICE_ID_AUDIO_PROCESSOR = 38,\n    DEVICE_ID_TAP = 39,\n    DEVICE_ID_POWER_MANAGER = 40,\n    DEVICE_ID_PARTIAL_FLASHING = 41,\n    DEVICE_ID_USB_FLASH_MANAGER = 42,\n    DEVICE_ID_VIRTUAL_SPEAKER_PIN = 43,\n    DEVICE_ID_LOG = 44,\n    DEVICE_ID_IO_P0 = 100,\n    DEVICE_ID_MESSAGE_BUS_LISTENER = 1021,\n    DEVICE_ID_NOTIFY_ONE = 1022,\n    DEVICE_ID_NOTIFY = 1023,\n    DEVICE_ID_BUTTON_UP = 2000,\n    DEVICE_ID_BUTTON_DOWN = 2001,\n    DEVICE_ID_BUTTON_LEFT = 2002,\n    DEVICE_ID_BUTTON_RIGHT = 2003,\n    DEVICE_ID_JD_DYNAMIC_ID = 3000,\n    DEVICE_ID_DYNAMIC_MIN = 64000,\n    DEVICE_ID_DYNAMIC_MAX = 65000,\n    DEVICE_COMPONENT_RUNNING = 4096,\n    DEVICE_COMPONENT_STATUS_SYSTEM_TICK = 8192,\n    DEVICE_COMPONENT_STATUS_IDLE_TICK = 16384,\n    DEVICE_COMPONENT_LISTENERS_CONFIGURED = 1,\n    DEVICE_COMPONENT_EVT_SYSTEM_TICK = 1,\n    // /libraries/codal-core/inc/core/CodalFiber.h\n    DEVICE_SCHEDULER_RUNNING = 1,\n    DEVICE_SCHEDULER_IDLE = 2,\n    DEVICE_SCHEDULER_DEEPSLEEP = 4,\n    DEVICE_FIBER_FLAG_FOB = 1,\n    DEVICE_FIBER_FLAG_PARENT = 2,\n    DEVICE_FIBER_FLAG_CHILD = 4,\n    DEVICE_FIBER_FLAG_DO_NOT_PAGE = 8,\n    DEVICE_SCHEDULER_EVT_TICK = 1,\n    DEVICE_SCHEDULER_EVT_IDLE = 2,\n    DEVICE_GET_FIBER_LIST_AVAILABLE = 1,\n    MUTEX = 0,\n    SEMAPHORE = 1,\n    // /libraries/codal-core/inc/core/CodalListener.h\n    MESSAGE_BUS_LISTENER_PARAMETERISED = 1,\n    MESSAGE_BUS_LISTENER_METHOD = 2,\n    MESSAGE_BUS_LISTENER_BUSY = 4,\n    MESSAGE_BUS_LISTENER_REENTRANT = 8,\n    MESSAGE_BUS_LISTENER_QUEUE_IF_BUSY = 16,\n    MESSAGE_BUS_LISTENER_DROP_IF_BUSY = 32,\n    MESSAGE_BUS_LISTENER_NONBLOCKING = 64,\n    MESSAGE_BUS_LISTENER_URGENT = 128,\n    MESSAGE_BUS_LISTENER_DELETING = 32768,\n    MESSAGE_BUS_LISTENER_IMMEDIATE = 192,\n    // /libraries/codal-core/inc/core/ErrorNo.h\n    DEVICE_OK = 0,\n    DEVICE_INVALID_PARAMETER = -1001,\n    DEVICE_NOT_SUPPORTED = -1002,\n    DEVICE_CALIBRATION_IN_PROGRESS = -1003,\n    DEVICE_CALIBRATION_REQUIRED = -1004,\n    DEVICE_NO_RESOURCES = -1005,\n    DEVICE_BUSY = -1006,\n    DEVICE_CANCELLED = -1007,\n    DEVICE_I2C_ERROR = -1010,\n    DEVICE_SERIAL_IN_USE = -1011,\n    DEVICE_NO_DATA = -1012,\n    DEVICE_NOT_IMPLEMENTED = -1013,\n    DEVICE_SPI_ERROR = -1014,\n    DEVICE_INVALID_STATE = -1015,\n    DEVICE_OOM = 20,\n    DEVICE_RESORUCES_EXHAUSTED = 21,\n    DEVICE_HEAP_ERROR = 30,\n    DEVICE_NULL_DEREFERENCE = 40,\n    DEVICE_PERIPHERAL_ERROR = 50,\n    DEVICE_JACDAC_ERROR = 60,\n    DEVICE_CPU_SDK = 70,\n    DEVICE_HARDWARE_CONFIGURATION_ERROR = 90,\n    // /libraries/codal-core/inc/core/NotifyEvents.h\n    DISPLAY_EVT_FREE = 1,\n    CODAL_SERIAL_EVT_TX_EMPTY = 2,\n    BLE_EVT_SERIAL_TX_EMPTY = 3,\n    ARCADE_PLAYER_JOIN_RESULT = 4,\n    POWER_EVT_CANCEL_DEEPSLEEP = 5,\n    DEVICE_NOTIFY_USER_EVENT_BASE = 1024,\n    // /libraries/codal-core/inc/driver-models/AbstractButton.h\n    DEVICE_BUTTON_EVT_DOWN = 1,\n    DEVICE_BUTTON_EVT_UP = 2,\n    DEVICE_BUTTON_EVT_CLICK = 3,\n    DEVICE_BUTTON_EVT_LONG_CLICK = 4,\n    DEVICE_BUTTON_EVT_HOLD = 5,\n    DEVICE_BUTTON_EVT_DOUBLE_CLICK = 6,\n    DEVICE_BUTTON_LONG_CLICK_TIME = 1000,\n    DEVICE_BUTTON_HOLD_TIME = 1500,\n    DEVICE_BUTTON_STATE = 1,\n    DEVICE_BUTTON_STATE_HOLD_TRIGGERED = 2,\n    DEVICE_BUTTON_STATE_CLICK = 4,\n    DEVICE_BUTTON_STATE_LONG_CLICK = 8,\n    DEVICE_BUTTON_SIGMA_MIN = 0,\n    DEVICE_BUTTON_SIGMA_MAX = 12,\n    DEVICE_BUTTON_SIGMA_THRESH_HI = 8,\n    DEVICE_BUTTON_SIGMA_THRESH_LO = 2,\n    DEVICE_BUTTON_DOUBLE_CLICK_THRESH = 50,\n    DEVICE_BUTTON_SIMPLE_EVENTS = 0,\n    DEVICE_BUTTON_ALL_EVENTS = 1,\n    ACTIVE_LOW = 0,\n    ACTIVE_HIGH = 1,\n    // /libraries/codal-core/inc/driver-models/Accelerometer.h\n    ACCELEROMETER_IMU_DATA_VALID = 2,\n    ACCELEROMETER_EVT_DATA_UPDATE = 1,\n    ACCELEROMETER_EVT_NONE = 0,\n    ACCELEROMETER_EVT_TILT_UP = 1,\n    ACCELEROMETER_EVT_TILT_DOWN = 2,\n    ACCELEROMETER_EVT_TILT_LEFT = 3,\n    ACCELEROMETER_EVT_TILT_RIGHT = 4,\n    ACCELEROMETER_EVT_FACE_UP = 5,\n    ACCELEROMETER_EVT_FACE_DOWN = 6,\n    ACCELEROMETER_EVT_FREEFALL = 7,\n    ACCELEROMETER_EVT_3G = 8,\n    ACCELEROMETER_EVT_6G = 9,\n    ACCELEROMETER_EVT_8G = 10,\n    ACCELEROMETER_EVT_SHAKE = 11,\n    ACCELEROMETER_EVT_2G = 12,\n    ACCELEROMETER_REST_TOLERANCE = 200,\n    ACCELEROMETER_TILT_TOLERANCE = 200,\n    ACCELEROMETER_FREEFALL_TOLERANCE = 400,\n    ACCELEROMETER_SHAKE_TOLERANCE = 400,\n    ACCELEROMETER_2G_TOLERANCE = 2048,\n    ACCELEROMETER_3G_TOLERANCE = 3072,\n    ACCELEROMETER_6G_TOLERANCE = 6144,\n    ACCELEROMETER_8G_TOLERANCE = 8192,\n    ACCELEROMETER_GESTURE_DAMPING = 5,\n    ACCELEROMETER_SHAKE_DAMPING = 10,\n    ACCELEROMETER_SHAKE_RTX = 30,\n    ACCELEROMETER_SHAKE_COUNT_THRESHOLD = 4,\n    // /libraries/codal-core/inc/driver-models/Compass.h\n    COMPASS_STATUS_RUNNING = 1,\n    COMPASS_STATUS_CALIBRATED = 2,\n    COMPASS_STATUS_CALIBRATING = 4,\n    COMPASS_STATUS_ADDED_TO_IDLE = 8,\n    COMPASS_EVT_DATA_UPDATE = 1,\n    COMPASS_EVT_CONFIG_NEEDED = 2,\n    COMPASS_EVT_CALIBRATE = 3,\n    COMPASS_EVT_CALIBRATION_NEEDED = 4,\n    // /libraries/codal-core/inc/driver-models/Gyroscope.h\n    GYROSCOPE_IMU_DATA_VALID = 2,\n    GYROSCOPE_EVT_DATA_UPDATE = 1,\n    // /libraries/codal-core/inc/driver-models/LowLevelTimer.h\n    CODAL_LOWLEVELTIMER_STATUS_SLEEP_IRQENABLE = 1,\n    TimerModeTimer = 0,\n    TimerModeCounter = 1,\n    TimerModeAlternateFunction = 2,\n    BitMode8 = 0,\n    BitMode16 = 1,\n    BitMode24 = 2,\n    BitMode32 = 3,\n    // /libraries/codal-core/inc/driver-models/Pin.h\n    IO_STATUS_DIGITAL_IN = 1,\n    IO_STATUS_DIGITAL_OUT = 2,\n    IO_STATUS_ANALOG_IN = 4,\n    IO_STATUS_ANALOG_OUT = 8,\n    IO_STATUS_TOUCH_IN = 16,\n    IO_STATUS_EVENT_ON_EDGE = 32,\n    IO_STATUS_EVENT_PULSE_ON_EDGE = 64,\n    IO_STATUS_INTERRUPT_ON_EDGE = 128,\n    IO_STATUS_ACTIVE_HI = 256,\n    IO_STATUS_WAKE_ON_ACTIVE = 512,\n    IO_STATUS_DISCONNECTING = 1024,\n    DEVICE_PIN_MAX_OUTPUT = 1023,\n    DEVICE_PIN_MAX_SERVO_RANGE = 180,\n    DEVICE_PIN_DEFAULT_SERVO_RANGE = 2000,\n    DEVICE_PIN_DEFAULT_SERVO_CENTER = 1500,\n    DEVICE_PIN_EVENT_NONE = 0,\n    DEVICE_PIN_INTERRUPT_ON_EDGE = 1,\n    DEVICE_PIN_EVENT_ON_EDGE = 2,\n    DEVICE_PIN_EVENT_ON_PULSE = 3,\n    DEVICE_PIN_EVENT_ON_TOUCH = 4,\n    DEVICE_PIN_EVT_RISE = 2,\n    DEVICE_PIN_EVT_FALL = 3,\n    DEVICE_PIN_EVT_PULSE_HI = 4,\n    DEVICE_PIN_EVT_PULSE_LO = 5,\n    PIN_CAPABILITY_DIGITAL = 1,\n    PIN_CAPABILITY_ANALOG = 2,\n    PIN_CAPABILITY_AD = 3,\n    PIN_CAPABILITY_ALL = 3,\n    None = 0,\n    Down = 1,\n    Up = 2,\n    // /libraries/codal-core/inc/driver-models/Radio.h\n    RADIO_EVT_DATA_READY = 2,\n    // /libraries/codal-core/inc/driver-models/SPIFlash.h\n    SPIFLASH_PAGE_SIZE = 256,\n    SPIFLASH_SMALL_ROW_PAGES = 16,\n    SPIFLASH_BIG_ROW_PAGES = 256,\n    // /libraries/codal-core/inc/driver-models/Sensor.h\n    SENSOR_THRESHOLD_LOW = 1,\n    SENSOR_THRESHOLD_HIGH = 2,\n    SENSOR_UPDATE_NEEDED = 3,\n    SENSOR_INITIALISED = 1,\n    SENSOR_HIGH_THRESHOLD_PASSED = 2,\n    SENSOR_LOW_THRESHOLD_PASSED = 4,\n    SENSOR_LOW_THRESHOLD_ENABLED = 8,\n    SENSOR_HIGH_THRESHOLD_ENABLED = 16,\n    SENSOR_DEFAULT_SENSITIVITY = 868,\n    SENSOR_DEFAULT_SAMPLE_PERIOD = 500,\n    // /libraries/codal-core/inc/driver-models/Serial.h\n    CODAL_SERIAL_DEFAULT_BAUD_RATE = 115200,\n    CODAL_SERIAL_DEFAULT_BUFFER_SIZE = 20,\n    CODAL_SERIAL_EVT_DELIM_MATCH = 1,\n    CODAL_SERIAL_EVT_HEAD_MATCH = 2,\n    CODAL_SERIAL_EVT_RX_FULL = 3,\n    CODAL_SERIAL_EVT_DATA_RECEIVED = 4,\n    CODAL_SERIAL_STATUS_RX_IN_USE = 1,\n    CODAL_SERIAL_STATUS_TX_IN_USE = 2,\n    CODAL_SERIAL_STATUS_RX_BUFF_INIT = 4,\n    CODAL_SERIAL_STATUS_TX_BUFF_INIT = 8,\n    CODAL_SERIAL_STATUS_RXD = 16,\n    CODAL_SERIAL_STATUS_DEEPSLEEP = 32,\n    ASYNC = 0,\n    SYNC_SPINWAIT = 1,\n    SYNC_SLEEP = 2,\n    RxInterrupt = 0,\n    TxInterrupt = 1,\n    // /libraries/codal-core/inc/driver-models/SingleWireSerial.h\n    SWS_EVT_DATA_RECEIVED = 1,\n    SWS_EVT_DATA_SENT = 2,\n    SWS_EVT_ERROR = 3,\n    SWS_EVT_DATA_DROPPED = 4,\n    SingleWireRx = 0,\n    SingleWireTx = 1,\n    SingleWireDisconnected = 2,\n    // /libraries/codal-core/inc/driver-models/Timer.h\n    CODAL_TIMER_DEFAULT_EVENT_LIST_SIZE = 10,\n    CODAL_TIMER_EVENT_FLAGS_NONE = 0,\n    CODAL_TIMER_EVENT_FLAGS_WAKEUP = 1,\n    // /libraries/codal-core/inc/drivers/AnalogSensor.h\n    ANALOG_THRESHOLD_LOW = 1,\n    ANALOG_THRESHOLD_HIGH = 2,\n    ANALOG_SENSOR_UPDATE_NEEDED = 3,\n    ANALOG_SENSOR_INITIALISED = 1,\n    ANALOG_SENSOR_HIGH_THRESHOLD_PASSED = 2,\n    ANALOG_SENSOR_LOW_THRESHOLD_PASSED = 4,\n    ANALOG_SENSOR_LOW_THRESHOLD_ENABLED = 8,\n    ANALOG_SENSOR_HIGH_THRESHOLD_ENABLED = 16,\n    // /libraries/codal-core/inc/drivers/AnimatedDisplay.h\n    DISPLAY_EVT_ANIMATION_COMPLETE = 1,\n    DISPLAY_DEFAULT_AUTOCLEAR = 1,\n    DISPLAY_SPACING = 1,\n    DISPLAY_ANIMATE_DEFAULT_POS = -255,\n    DISPLAY_DEFAULT_SCROLL_SPEED = 120,\n    DISPLAY_DEFAULT_SCROLL_STRIDE = -1,\n    DISPLAY_DEFAULT_PRINT_SPEED = 400,\n    ANIMATION_MODE_NONE = 0,\n    ANIMATION_MODE_STOPPED = 1,\n    ANIMATION_MODE_SCROLL_TEXT = 2,\n    ANIMATION_MODE_PRINT_TEXT = 3,\n    ANIMATION_MODE_SCROLL_IMAGE = 4,\n    ANIMATION_MODE_ANIMATE_IMAGE = 5,\n    ANIMATION_MODE_ANIMATE_IMAGE_WITH_CLEAR = 6,\n    ANIMATION_MODE_PRINT_CHARACTER = 7,\n    // /libraries/codal-core/inc/drivers/FAT.h\n    FAT_RESERVED_SECTORS = 1,\n    FAT_ROOT_DIR_SECTORS = 4,\n    // /libraries/codal-core/inc/drivers/HID.h\n    HID_REQUEST_GET_REPORT = 1,\n    HID_REQUEST_GET_IDLE = 2,\n    HID_REQUEST_GET_PROTOCOL = 3,\n    HID_REQUEST_SET_REPORT = 9,\n    HID_REQUEST_SET_IDLE = 10,\n    HID_REQUEST_SET_PROTOCOL = 11,\n    // /libraries/codal-core/inc/drivers/HIDKeyboard.h\n    HID_KEYBOARD_NUM_REPORTS = 3,\n    HID_KEYBOARD_REPORT_GENERIC = 1,\n    HID_KEYBOARD_REPORT_CONSUMER = 2,\n    HID_KEYBOARD_KEYSTATE_SIZE_GENERIC = 8,\n    HID_KEYBOARD_KEYSTATE_SIZE_CONSUMER = 2,\n    HID_KEYBOARD_MODIFIER_OFFSET = 2,\n    HID_KEYBOARD_DELAY_DEFAULT = 10,\n    PressKey = 0,\n    ReleaseKey = 1,\n    // /libraries/codal-core/inc/drivers/KeyMap.h\n    KEYMAP_ALL_KEYS_UP_Val = 1,\n    KEYMAP_ALL_KEYS_UP_POS = 28,\n    KEYMAP_NORMAL_KEY_Val = 0,\n    KEYMAP_MODIFIER_KEY_Val = 1,\n    KEYMAP_MODIFIER_POS = 29,\n    KEYMAP_MEDIA_KEY_Val = 1,\n    KEYMAP_MEDIA_POS = 30,\n    KEYMAP_KEY_UP_Val = 0,\n    KEYMAP_KEY_DOWN_Val = 1,\n    KEYMAP_KEY_DOWN_POS = 31,\n    // /libraries/codal-core/inc/drivers/KeyValueStorage.h\n    DEVICE_KEY_VALUE_STORE_OFFSET = -4,\n    KEY_VALUE_STORAGE_MAGIC = 789921,\n    KEY_VALUE_STORAGE_BLOCK_SIZE = 48,\n    KEY_VALUE_STORAGE_KEY_SIZE = 16,\n    KEY_VALUE_STORAGE_SCRATCH_WORD_SIZE = 64,\n    KEY_VALUE_STORAGE_MAX_PAIRS = 5,\n    // /libraries/codal-core/inc/drivers/LEDMatrix.h\n    LED_MATRIX_GREYSCALE_BIT_DEPTH = 8,\n    LED_MATRIX_EVT_LIGHT_SENSE = 2,\n    LED_MATRIX_EVT_FRAME_TIMEOUT = 3,\n    LED_MATRIX_MINIMUM_BRIGHTNESS = 1,\n    LED_MATRIX_MAXIMUM_BRIGHTNESS = 255,\n    LED_MATRIX_DEFAULT_BRIGHTNESS = 255,\n    DISPLAY_MODE_BLACK_AND_WHITE = 0,\n    DISPLAY_MODE_GREYSCALE = 1,\n    DISPLAY_MODE_BLACK_AND_WHITE_LIGHT_SENSE = 2,\n    DISPLAY_MODE_GREYSCALE_LIGHT_SENSE = 3,\n    MATRIX_DISPLAY_ROTATION_0 = 0,\n    MATRIX_DISPLAY_ROTATION_90 = 1,\n    MATRIX_DISPLAY_ROTATION_180 = 2,\n    MATRIX_DISPLAY_ROTATION_270 = 3,\n    NO_CONN = 0,\n    // /libraries/codal-core/inc/drivers/MAG3110.h\n    MAG3110_DEFAULT_ADDR = 29,\n    MAG3110_SAMPLE_RATES = 11,\n    MAG3110_WHOAMI_VAL = 196,\n    // /libraries/codal-core/inc/drivers/MultiButton.h\n    MULTI_BUTTON_STATE_1 = 1,\n    MULTI_BUTTON_STATE_2 = 2,\n    MULTI_BUTTON_HOLD_TRIGGERED_1 = 4,\n    MULTI_BUTTON_HOLD_TRIGGERED_2 = 8,\n    MULTI_BUTTON_SUPRESSED_1 = 16,\n    MULTI_BUTTON_SUPRESSED_2 = 32,\n    MULTI_BUTTON_ATTACHED = 64,\n    // /libraries/codal-core/inc/drivers/PulseIn.h\n    DEVICE_EVT_PULSE_IN_TIMEOUT = 10000,\n    // /libraries/codal-core/inc/drivers/ST7735.h\n    MADCTL_MY = 128,\n    MADCTL_MX = 64,\n    MADCTL_MV = 32,\n    MADCTL_ML = 16,\n    MADCTL_RGB = 0,\n    MADCTL_BGR = 8,\n    MADCTL_MH = 4,\n    // /libraries/codal-core/inc/drivers/TouchButton.h\n    TOUCH_BUTTON_CALIBRATION_LINEAR_OFFSET = 2,\n    TOUCH_BUTTON_CALIBRATION_PERCENTAGE_OFFSET = 5,\n    TOUCH_BUTTON_SENSITIVITY = 10,\n    TOUCH_BUTTON_CALIBRATION_PERIOD = 10,\n    TOUCH_BUTTON_CALIBRATING = 16,\n    TOUCH_BUTTON_RUNNING = 32,\n    // /libraries/codal-core/inc/drivers/TouchSensor.h\n    TOUCH_SENSOR_MAX_BUTTONS = 10,\n    TOUCH_SENSOR_SAMPLE_PERIOD = 50,\n    TOUCH_SENSE_SAMPLE_MAX = 1000,\n    TOUCH_SENSOR_UPDATE_NEEDED = 1,\n    // /libraries/codal-core/inc/drivers/USB_HID_Keys.h\n    KEY_MOD_LCTRL = 1,\n    KEY_MOD_LSHIFT = 2,\n    KEY_MOD_LALT = 4,\n    KEY_MOD_LMETA = 8,\n    KEY_MOD_RCTRL = 16,\n    KEY_MOD_RSHIFT = 32,\n    KEY_MOD_RALT = 64,\n    KEY_MOD_RMETA = 128,\n    KEY_NONE = 0,\n    KEY_ERR_OVF = 1,\n    KEY_A = 4,\n    KEY_B = 5,\n    KEY_C = 6,\n    KEY_D = 7,\n    KEY_E = 8,\n    KEY_F = 9,\n    KEY_G = 10,\n    KEY_H = 11,\n    KEY_I = 12,\n    KEY_J = 13,\n    KEY_K = 14,\n    KEY_L = 15,\n    KEY_M = 16,\n    KEY_N = 17,\n    KEY_O = 18,\n    KEY_P = 19,\n    KEY_Q = 20,\n    KEY_R = 21,\n    KEY_S = 22,\n    KEY_T = 23,\n    KEY_U = 24,\n    KEY_V = 25,\n    KEY_W = 26,\n    KEY_X = 27,\n    KEY_Y = 28,\n    KEY_Z = 29,\n    KEY_1 = 30,\n    KEY_2 = 31,\n    KEY_3 = 32,\n    KEY_4 = 33,\n    KEY_5 = 34,\n    KEY_6 = 35,\n    KEY_7 = 36,\n    KEY_8 = 37,\n    KEY_9 = 38,\n    KEY_0 = 39,\n    KEY_ENTER = 40,\n    KEY_ESC = 41,\n    KEY_BACKSPACE = 42,\n    KEY_TAB = 43,\n    KEY_SPACE = 44,\n    KEY_MINUS = 45,\n    KEY_EQUAL = 46,\n    KEY_LEFTBRACE = 47,\n    KEY_RIGHTBRACE = 48,\n    KEY_BACKSLASH = 49,\n    KEY_HASHTILDE = 50,\n    KEY_SEMICOLON = 51,\n    KEY_APOSTROPHE = 52,\n    KEY_GRAVE = 53,\n    KEY_COMMA = 54,\n    KEY_DOT = 55,\n    KEY_SLASH = 56,\n    KEY_CAPSLOCK = 57,\n    KEY_F1 = 58,\n    KEY_F2 = 59,\n    KEY_F3 = 60,\n    KEY_F4 = 61,\n    KEY_F5 = 62,\n    KEY_F6 = 63,\n    KEY_F7 = 64,\n    KEY_F8 = 65,\n    KEY_F9 = 66,\n    KEY_F10 = 67,\n    KEY_F11 = 68,\n    KEY_F12 = 69,\n    KEY_SYSRQ = 70,\n    KEY_SCROLLLOCK = 71,\n    KEY_PAUSE = 72,\n    KEY_INSERT = 73,\n    KEY_HOME = 74,\n    KEY_PAGEUP = 75,\n    KEY_DELETE = 76,\n    KEY_END = 77,\n    KEY_PAGEDOWN = 78,\n    KEY_RIGHT = 79,\n    KEY_LEFT = 80,\n    KEY_DOWN = 81,\n    KEY_UP = 82,\n    KEY_NUMLOCK = 83,\n    KEY_KPSLASH = 84,\n    KEY_KPASTERISK = 85,\n    KEY_KPMINUS = 86,\n    KEY_KPPLUS = 87,\n    KEY_KPENTER = 88,\n    KEY_KP1 = 89,\n    KEY_KP2 = 90,\n    KEY_KP3 = 91,\n    KEY_KP4 = 92,\n    KEY_KP5 = 93,\n    KEY_KP6 = 94,\n    KEY_KP7 = 95,\n    KEY_KP8 = 96,\n    KEY_KP9 = 97,\n    KEY_KP0 = 98,\n    KEY_KPDOT = 99,\n    KEY_102ND = 100,\n    KEY_COMPOSE = 101,\n    KEY_POWER = 102,\n    KEY_KPEQUAL = 103,\n    KEY_F13 = 104,\n    KEY_F14 = 105,\n    KEY_F15 = 106,\n    KEY_F16 = 107,\n    KEY_F17 = 108,\n    KEY_F18 = 109,\n    KEY_F19 = 110,\n    KEY_F20 = 111,\n    KEY_F21 = 112,\n    KEY_F22 = 113,\n    KEY_F23 = 114,\n    KEY_F24 = 115,\n    KEY_OPEN = 116,\n    KEY_HELP = 117,\n    KEY_PROPS = 118,\n    KEY_FRONT = 119,\n    KEY_STOP = 120,\n    KEY_AGAIN = 121,\n    KEY_UNDO = 122,\n    KEY_CUT = 123,\n    KEY_COPY = 124,\n    KEY_PASTE = 125,\n    KEY_FIND = 126,\n    KEY_MUTE = 127,\n    KEY_VOLUMEUP = 128,\n    KEY_VOLUMEDOWN = 129,\n    KEY_KPCOMMA = 133,\n    KEY_RO = 135,\n    KEY_KATAKANAHIRAGANA = 136,\n    KEY_YEN = 137,\n    KEY_HENKAN = 138,\n    KEY_MUHENKAN = 139,\n    KEY_KPJPCOMMA = 140,\n    KEY_HANGEUL = 144,\n    KEY_HANJA = 145,\n    KEY_KATAKANA = 146,\n    KEY_HIRAGANA = 147,\n    KEY_ZENKAKUHANKAKU = 148,\n    KEY_KPLEFTPAREN = 182,\n    KEY_KPRIGHTPAREN = 183,\n    KEY_LEFTCTRL = 224,\n    KEY_LEFTSHIFT = 225,\n    KEY_LEFTALT = 226,\n    KEY_LEFTMETA = 227,\n    KEY_RIGHTCTRL = 228,\n    KEY_RIGHTSHIFT = 229,\n    KEY_RIGHTALT = 230,\n    KEY_RIGHTMETA = 231,\n    KEY_MEDIA_PLAYPAUSE = 232,\n    KEY_MEDIA_STOPCD = 233,\n    KEY_MEDIA_PREVIOUSSONG = 234,\n    KEY_MEDIA_NEXTSONG = 235,\n    KEY_MEDIA_EJECTCD = 236,\n    KEY_MEDIA_VOLUMEUP = 237,\n    KEY_MEDIA_VOLUMEDOWN = 238,\n    KEY_MEDIA_MUTE = 239,\n    KEY_MEDIA_WWW = 240,\n    KEY_MEDIA_BACK = 241,\n    KEY_MEDIA_FORWARD = 242,\n    KEY_MEDIA_STOP = 243,\n    KEY_MEDIA_FIND = 244,\n    KEY_MEDIA_SCROLLUP = 245,\n    KEY_MEDIA_SCROLLDOWN = 246,\n    KEY_MEDIA_EDIT = 247,\n    KEY_MEDIA_SLEEP = 248,\n    KEY_MEDIA_COFFEE = 249,\n    KEY_MEDIA_REFRESH = 250,\n    KEY_MEDIA_CALC = 251,\n    // /libraries/codal-core/inc/drivers/uf2format.h\n    UF2FORMAT_H = 1,\n    APP_START_ADDRESS = 8192,\n    UF2_FLAG_NOFLASH = 1,\n    // /libraries/codal-core/inc/streams/DataStream.h\n    DATASTREAM_MAXIMUM_BUFFERS = 1,\n    DATASTREAM_FORMAT_UNKNOWN = 0,\n    DATASTREAM_FORMAT_8BIT_UNSIGNED = 1,\n    DATASTREAM_FORMAT_8BIT_SIGNED = 2,\n    DATASTREAM_FORMAT_16BIT_UNSIGNED = 3,\n    DATASTREAM_FORMAT_16BIT_SIGNED = 4,\n    DATASTREAM_FORMAT_24BIT_UNSIGNED = 5,\n    DATASTREAM_FORMAT_24BIT_SIGNED = 6,\n    DATASTREAM_FORMAT_32BIT_UNSIGNED = 7,\n    DATASTREAM_FORMAT_32BIT_SIGNED = 8,\n    // /libraries/codal-core/inc/streams/FIFOStream.h\n    FIFO_MAXIMUM_BUFFERS = 256,\n    // /libraries/codal-core/inc/streams/LevelDetector.h\n    LEVEL_THRESHOLD_LOW = 1,\n    LEVEL_THRESHOLD_HIGH = 2,\n    LEVEL_DETECTOR_INITIALISED = 1,\n    LEVEL_DETECTOR_HIGH_THRESHOLD_PASSED = 2,\n    LEVEL_DETECTOR_LOW_THRESHOLD_PASSED = 4,\n    LEVEL_DETECTOR_DEFAULT_WINDOW_SIZE = 128,\n    // /libraries/codal-core/inc/streams/LevelDetectorSPL.h\n    LEVEL_DETECTOR_SPL_INITIALISED = 1,\n    LEVEL_DETECTOR_SPL_HIGH_THRESHOLD_PASSED = 2,\n    LEVEL_DETECTOR_SPL_LOW_THRESHOLD_PASSED = 4,\n    LEVEL_DETECTOR_SPL_CLAP = 8,\n    LEVEL_DETECTOR_SPL_DEFAULT_WINDOW_SIZE = 128,\n    LEVEL_DETECTOR_SPL_NORMALIZE = 1,\n    LEVEL_DETECTOR_SPL_MIN_BUFFERS = 2,\n    LEVEL_DETECTOR_SPL_DB = 1,\n    LEVEL_DETECTOR_SPL_8BIT = 2,\n    LEVEL_DETECTOR_SPL_BEGIN_POSS_CLAP_RMS = 200,\n    LEVEL_DETECTOR_SPL_MIN_IN_CLAP_RMS = 300,\n    LEVEL_DETECTOR_SPL_CLAP_OVER_RMS = 100,\n    LEVEL_DETECTOR_SPL_CLAP_MAX_LOUD_BLOCKS = 13,\n    LEVEL_DETECTOR_SPL_CLAP_MIN_LOUD_BLOCKS = 2,\n    LEVEL_DETECTOR_SPL_CLAP_MIN_QUIET_BLOCKS = 20,\n    // /libraries/codal-core/inc/streams/MemorySource.h\n    MEMORY_SOURCE_DEFAULT_MAX_BUFFER = 256,\n    // /libraries/codal-core/inc/streams/StreamFlowTrigger.h\n    TRIGGER_PULL = 1,\n    TRIGGER_REQUEST = 2,\n    // /libraries/codal-core/inc/streams/StreamRecording.h\n    CODAL_DEFAULT_STREAM_RECORDING_MAX_LENGTH = 50000,\n    REC_STATE_STOPPED = 0,\n    REC_STATE_PLAYING = 1,\n    REC_STATE_RECORDING = 2,\n    // /libraries/codal-core/inc/streams/StreamSplitter.h\n    CONFIG_MAX_CHANNELS = 10,\n    CONFIG_SPLITTER_OVERSAMPLE_STEP = 16,\n    SPLITTER_CHANNEL_CONNECT = 1,\n    SPLITTER_CHANNEL_DISCONNECT = 2,\n    SPLITTER_ACTIVATE = 3,\n    SPLITTER_DEACTIVATE = 4,\n    SPLITTER_TICK = 10,\n    // /libraries/codal-core/inc/streams/Synthesizer.h\n    SYNTHESIZER_SAMPLE_RATE = 44100,\n    TONE_WIDTH = 1024,\n    // /libraries/codal-core/inc/types/BitmapFont.h\n    BITMAP_FONT_WIDTH = 5,\n    BITMAP_FONT_HEIGHT = 5,\n    BITMAP_FONT_ASCII_START = 32,\n    BITMAP_FONT_ASCII_END = 126,\n    // /libraries/codal-core/inc/types/CoordinateSystem.h\n    COORDINATE_SPACE_ROTATED_0 = 0,\n    COORDINATE_SPACE_ROTATED_90 = 1,\n    COORDINATE_SPACE_ROTATED_180 = 2,\n    COORDINATE_SPACE_ROTATED_270 = 3,\n    RAW = 0,\n    SIMPLE_CARTESIAN = 1,\n    NORTH_EAST_DOWN = 2,\n    EAST_NORTH_UP = 3,\n    NORTH_EAST_UP = 3,\n    // /libraries/codal-core/inc/types/Event.h\n    DEVICE_ID_ANY = 0,\n    DEVICE_EVT_ANY = 0,\n    CREATE_ONLY = 0,\n    CREATE_AND_FIRE = 1,\n    DEVICE_EVENT_DEFAULT_LAUNCH_MODE = 1,\n    // /libraries/codal-core/inc/types/ManagedBuffer.h\n    Zero = 1,\n    // /libraries/codal-microbit-v2/inc/FSCache.h\n    FSCACHE_FLAG_PINNED = 1,\n    CODAL_FS_CACHE_VALIDATE = 1,\n    CODAL_FS_DEFAULT_CACHE_SZE = 4,\n    // /libraries/codal-microbit-v2/inc/MicroBitAudio.h\n    MICROBIT_AUDIO_STATUS_DEEPSLEEP = 1,\n    // /libraries/codal-microbit-v2/inc/MicroBitBLEServices.h\n    MICROBIT_BLE_SERVICES_MAX = 20,\n    MICROBIT_BLE_SERVICES_OBSERVER_PRIO = 2,\n    // /libraries/codal-microbit-v2/inc/MicroBitDevice.h\n    MICROBIT_NAME_LENGTH = 5,\n    MICROBIT_NAME_CODE_LETTERS = 5,\n    // /libraries/codal-microbit-v2/inc/MicroBitFile.h\n    READ = 1,\n    WRITE = 2,\n    READ_AND_WRITE = 3,\n    CREATE = 4,\n    // /libraries/codal-microbit-v2/inc/MicroBitFileSystem.h\n    MBFS_FILENAME_LENGTH = 16,\n    MB_READ = 1,\n    MB_WRITE = 2,\n    MB_CREAT = 4,\n    MB_APPEND = 8,\n    MB_SEEK_SET = 1,\n    MB_SEEK_END = 2,\n    MB_SEEK_CUR = 4,\n    MBFS_STATUS_INITIALISED = 1,\n    MBFS_UNUSED = 65535,\n    MBFS_EOF = 61439,\n    MBFS_DELETED = 0,\n    MBFS_DIRECTORY_ENTRY_FREE = 32768,\n    MBFS_DIRECTORY_ENTRY_VALID = 16384,\n    MBFS_DIRECTORY_ENTRY_DIRECTORY = 8192,\n    MBFS_DIRECTORY_ENTRY_NEW = 65535,\n    MBFS_DIRECTORY_ENTRY_DELETED = 0,\n    MBFS_BLOCK_TYPE_FILE = 1,\n    MBFS_BLOCK_TYPE_DIRECTORY = 2,\n    MBFS_BLOCK_TYPE_FILETABLE = 3,\n    // /libraries/codal-microbit-v2/inc/MicroBitLog.h\n    CONFIG_MICROBIT_LOG_METADATA_SIZE = 2048,\n    CONFIG_MICROBIT_LOG_JOURNAL_SIZE = 4096,\n    CONFIG_MICROBIT_LOG_CACHE_BLOCK_SIZE = 256,\n    MICROBIT_LOG_JOURNAL_ENTRY_SIZE = 8,\n    MICROBIT_LOG_STATUS_INITIALIZED = 1,\n    MICROBIT_LOG_STATUS_ROW_STARTED = 2,\n    MICROBIT_LOG_STATUS_FULL = 4,\n    MICROBIT_LOG_STATUS_SERIAL_MIRROR = 8,\n    MICROBIT_LOG_EVT_LOG_FULL = 1,\n    Milliseconds = 1,\n    Seconds = 10,\n    Minutes = 600,\n    Hours = 36000,\n    Days = 864000,\n    HTMLHeader = 0,\n    HTML = 1,\n    CSV = 2,\n    // /libraries/codal-microbit-v2/inc/MicroBitMemoryMap.h\n    NUMBER_OF_REGIONS = 3,\n    REGION_SD = 0,\n    REGION_CODAL = 1,\n    REGION_MAKECODE = 2,\n    REGION_PYTHON = 3,\n    // /libraries/codal-microbit-v2/inc/MicroBitPowerManager.h\n    MICROBIT_UIPM_MAX_BUFFER_SIZE = 12,\n    MICROBIT_UIPM_MAX_RETRIES = 20,\n    MICROBIT_USB_INTERFACE_IRQ_THRESHOLD = 30,\n    MICROBIT_UIPM_COMMAND_READ_REQUEST = 16,\n    MICROBIT_UIPM_COMMAND_READ_RESPONSE = 17,\n    MICROBIT_UIPM_COMMAND_WRITE_REQUEST = 18,\n    MICROBIT_UIPM_COMMAND_WRITE_RESPONSE = 19,\n    MICROBIT_UIPM_COMMAND_ERROR_RESPONSE = 32,\n    MICROBIT_UIPM_PROPERTY_BOARD_REVISION = 1,\n    MICROBIT_UIPM_PROPERTY_I2C_VERSION = 2,\n    MICROBIT_UIPM_PROPERTY_DAPLINK_VERSION = 3,\n    MICROBIT_UIPM_PROPERTY_POWER_SOURCE = 4,\n    MICROBIT_UIPM_PROPERTY_POWER_CONSUMPTION = 5,\n    MICROBIT_UIPM_PROPERTY_USB_STATE = 6,\n    MICROBIT_UIPM_PROPERTY_KL27_POWER_MODE = 7,\n    MICROBIT_UIPM_PROPERTY_KL27_POWER_LED_STATE = 8,\n    MICROBIT_UIPM_PROPERTY_KL27_USER_EVENT = 9,\n    MICROBIT_UIPM_EVENT_WAKE_RESET = 1,\n    MICROBIT_UIPM_EVENT_WAKE_USB_INSERTION = 2,\n    MICROBIT_UIPM_EVENT_RESET_LONG_PRESS = 3,\n    MICROBIT_UIPM_SUCCESS = 48,\n    MICROBIT_UIPM_INCOMPLETE_CMD = 49,\n    MICROBIT_UIPM_UNKNOWN_CMD = 50,\n    MICROBIT_UIPM_FORBIDDEN = 51,\n    MICROBIT_UIPM_NOT_RECOGNISED = 52,\n    MICROBIT_UIPM_BAD_LENGTH = 53,\n    MICROBIT_UIPM_READ_FORBIDDEN = 54,\n    MICROBIT_UIPM_WRITE_FORBIDDEN = 55,\n    MICROBIT_UIPM_WRITE_FAIL = 56,\n    MICROBIT_UIPM_BUSY = 57,\n    MICROBIT_USB_INTERFACE_POWER_MODE_VLPS = 6,\n    MICROBIT_USB_INTERFACE_POWER_MODE_VLLS0 = 8,\n    MICROBIT_USB_INTERFACE_AWAITING_RESPONSE = 1,\n    MICROBIT_USB_INTERFACE_VERSION_LOADED = 2,\n    MICROBIT_USB_INTERFACE_ALWAYS_NOP = 4,\n    MICROBIT_USB_INTERFACE_BUSY_FLAG_SUPPORTED = 32,\n    CONFIG_MINIMUM_DEEP_SLEEP_TIME = 100,\n    CONFIG_MINIMUM_POWER_ON_TIME = 500,\n    // /libraries/codal-microbit-v2/inc/MicroBitRadio.h\n    MICROBIT_RADIO_STATUS_INITIALISED = 1,\n    MICROBIT_RADIO_STATUS_DEEPSLEEP_IRQ = 2,\n    MICROBIT_RADIO_STATUS_DEEPSLEEP_INIT = 4,\n    MICROBIT_RADIO_BASE_ADDRESS = 1969383796,\n    MICROBIT_RADIO_DEFAULT_GROUP = 0,\n    MICROBIT_RADIO_DEFAULT_TX_POWER = 6,\n    MICROBIT_RADIO_DEFAULT_FREQUENCY = 7,\n    MICROBIT_RADIO_HEADER_SIZE = 4,\n    MICROBIT_RADIO_MAXIMUM_RX_BUFFERS = 4,\n    MICROBIT_RADIO_POWER_LEVELS = 8,\n    MICROBIT_RADIO_PROTOCOL_DATAGRAM = 1,\n    MICROBIT_RADIO_PROTOCOL_EVENTBUS = 2,\n    MICROBIT_RADIO_EVT_DATAGRAM = 1,\n    // /libraries/codal-microbit-v2/inc/MicroBitThermometer.h\n    MICROBIT_THERMOMETER_PERIOD = 1000,\n    MICROBIT_THERMOMETER_EVT_UPDATE = 1,\n    // /libraries/codal-microbit-v2/inc/MicroBitUSBFlashManager.h\n    MICROBIT_USB_FLASH_MAX_TX_RETRIES = 20,\n    MICROBIT_USB_FLASH_MAX_RX_RETRIES = 20,\n    MICROBIT_USB_FLASH_MAX_FLASH_STORAGE = 126976,\n    MICROBIT_USB_FLASH_FILENAME_CMD = 1,\n    MICROBIT_USB_FLASH_FILESIZE_CMD = 2,\n    MICROBIT_USB_FLASH_VISIBILITY_CMD = 3,\n    MICROBIT_USB_FLASH_WRITE_CONFIG_CMD = 4,\n    MICROBIT_USB_FLASH_ERASE_CONFIG_CMD = 5,\n    MICROBIT_USB_FLASH_DISK_SIZE_CMD = 6,\n    MICROBIT_USB_FLASH_SECTOR_SIZE_CMD = 7,\n    MICROBIT_USB_FLASH_REMOUNT_CMD = 8,\n    MICROBIT_USB_FLASH_STATUS_CMD = 9,\n    MICROBIT_USB_FLASH_READ_CMD = 10,\n    MICROBIT_USB_FLASH_WRITE_CMD = 11,\n    MICROBIT_USB_FLASH_ERASE_CMD = 12,\n    MICROBIT_USB_FLASH_AWAITING_RESPONSE = 1,\n    MICROBIT_USB_FLASH_GEOMETRY_LOADED = 2,\n    MICROBIT_USB_FLASH_CONFIG_LOADED = 4,\n    MICROBIT_USB_FLASH_SINGLE_PAGE_ERASE_ONLY = 8,\n    MICROBIT_USB_FLASH_USE_NULL_TRANSACTION = 16,\n    MICROBIT_USB_FLASH_BUSY_FLAG_SUPPORTED = 32,\n    MICROBIT_USB_FLASH_100MS_AFTER_ERASE = 64,\n    // /libraries/codal-microbit-v2/inc/MicroSynth.h\n    Saw = 0,\n    Pulse = 1,\n    Triangle = 2,\n    LPF = 0,\n    HPF = 1,\n    BPF = 2,\n    // /libraries/codal-microbit-v2/inc/Mixer2.h\n    CONFIG_MIXER_BUFFER_SIZE = 512,\n    CONFIG_MIXER_INTERNAL_RANGE = 1023,\n    CONFIG_MIXER_DEFAULT_SAMPLERATE = 44100,\n    CONFIG_MIXER_DEFAULT_CHANNEL_SAMPLERATE = 44100,\n    DEVICE_ID_MIXER = 3030,\n    DEVICE_MIXER_EVT_SILENCE = 1,\n    DEVICE_MIXER_EVT_SOUND = 2,\n    // /libraries/codal-microbit-v2/inc/NRF52LedMatrix.h\n    NRF52_LED_MATRIX_CLOCK_FREQUENCY = 16000000,\n    NRF52_LED_MATRIX_FREQUENCY = 60,\n    NRF52_LED_MATRIX_MAXIMUM_COLUMNS = 5,\n    NRF52_LED_MATRIX_LIGHTSENSE_STROBES = 4,\n    NRF52_LEDMATRIX_GPIOTE_CHANNEL_BASE = 1,\n    NRF52_LEDMATRIX_PPI_CHANNEL_BASE = 3,\n    NRF52_LEDMATRIX_STATUS_RESET = 1,\n    NRF52_LEDMATRIX_STATUS_LIGHTREADY = 2,\n    // /libraries/codal-microbit-v2/inc/SoundEmojiSynthesizer.h\n    CONFIG_EMOJI_SYNTHESIZER_OUTPUT_BUFFER_DEPTH = 3,\n    EMOJI_SYNTHESIZER_SAMPLE_RATE = 44100,\n    EMOJI_SYNTHESIZER_TONE_WIDTH = 1024,\n    EMOJI_SYNTHESIZER_BUFFER_SIZE = 512,\n    EMOJI_SYNTHESIZER_TONE_EFFECT_PARAMETERS = 2,\n    EMOJI_SYNTHESIZER_TONE_EFFECTS = 3,\n    EMOJI_SYNTHESIZER_STATUS_ACTIVE = 1,\n    EMOJI_SYNTHESIZER_STATUS_OUTPUT_SILENCE_AS_EMPTY = 2,\n    EMOJI_SYNTHESIZER_STATUS_STOPPING = 4,\n    DEVICE_ID_SOUND_EMOJI_SYNTHESIZER_0 = 3010,\n    DEVICE_ID_SOUND_EMOJI_SYNTHESIZER_1 = 3011,\n    DEVICE_ID_SOUND_EMOJI_SYNTHESIZER_2 = 3012,\n    DEVICE_ID_SOUND_EMOJI_SYNTHESIZER_3 = 3013,\n    DEVICE_ID_SOUND_EMOJI_SYNTHESIZER_4 = 3014,\n    DEVICE_ID_SOUND_EMOJI_SYNTHESIZER_5 = 3015,\n    DEVICE_ID_SOUND_EMOJI_SYNTHESIZER_6 = 3016,\n    DEVICE_ID_SOUND_EMOJI_SYNTHESIZER_7 = 3017,\n    DEVICE_ID_SOUND_EMOJI_SYNTHESIZER_8 = 3018,\n    DEVICE_ID_SOUND_EMOJI_SYNTHESIZER_9 = 3019,\n    DEVICE_SOUND_EMOJI_SYNTHESIZER_EVT_DONE = 1,\n    DEVICE_SOUND_EMOJI_SYNTHESIZER_EVT_PLAYBACK_COMPLETE = 2,\n    SFX_DEFAULT_VIBRATO_STEPS = 512,\n    SFX_DEFAULT_VIBRATO_PARAM = 2,\n    SFX_DEFAULT_TREMOLO_STEPS = 900,\n    SFX_DEFAULT_TREMOLO_PARAM = 3,\n    SFX_DEFAULT_WARBLE_STEPS = 700,\n    SFX_DEFAULT_WARBLE_PARAM = 2,\n    // /libraries/codal-microbit-v2/inc/SoundOutputPin.h\n    CONFIG_SOUND_OUTPUT_PIN_PERIOD = 5,\n    CONFIG_SOUND_OUTPUT_PIN_SILENCE_GATE = 100,\n    SOUND_OUTPUT_PIN_SAMPLE_RATE = 44100,\n    SOUND_OUTPUT_PIN_BUFFER_SIZE = 512,\n    CONFIG_SOUND_OUTPUT_PIN_DISCRETE_OUTPUT = 1,\n    SOUND_OUTPUT_PIN_STATUS_ENABLED = 1,\n    SOUND_OUTPUT_PIN_STATUS_ACTIVE = 2,\n    CONFIG_SOUND_OUTPUT_PIN_TONEPRINT = 0,\n    // /libraries/codal-microbit-v2/inc/bluetooth/ExternalEvents.h\n    MICROBIT_ID_BLE = 1000,\n    MICROBIT_ID_BLE_UART = 1200,\n    MICROBIT_BLE_EVT_CONNECTED = 1,\n    MICROBIT_BLE_EVT_DISCONNECTED = 2,\n    // /libraries/codal-microbit-v2/inc/bluetooth/MESEvents.h\n    MES_REMOTE_CONTROL_ID = 1001,\n    MES_REMOTE_CONTROL_EVT_PLAY = 1,\n    MES_REMOTE_CONTROL_EVT_PAUSE = 2,\n    MES_REMOTE_CONTROL_EVT_STOP = 3,\n    MES_REMOTE_CONTROL_EVT_NEXTTRACK = 4,\n    MES_REMOTE_CONTROL_EVT_PREVTRACK = 5,\n    MES_REMOTE_CONTROL_EVT_FORWARD = 6,\n    MES_REMOTE_CONTROL_EVT_REWIND = 7,\n    MES_REMOTE_CONTROL_EVT_VOLUMEUP = 8,\n    MES_REMOTE_CONTROL_EVT_VOLUMEDOWN = 9,\n    MES_CAMERA_ID = 1002,\n    MES_CAMERA_EVT_LAUNCH_PHOTO_MODE = 1,\n    MES_CAMERA_EVT_LAUNCH_VIDEO_MODE = 2,\n    MES_CAMERA_EVT_TAKE_PHOTO = 3,\n    MES_CAMERA_EVT_START_VIDEO_CAPTURE = 4,\n    MES_CAMERA_EVT_STOP_VIDEO_CAPTURE = 5,\n    MES_CAMERA_EVT_STOP_PHOTO_MODE = 6,\n    MES_CAMERA_EVT_STOP_VIDEO_MODE = 7,\n    MES_CAMERA_EVT_TOGGLE_FRONT_REAR = 8,\n    MES_ALERTS_ID = 1004,\n    MES_ALERT_EVT_DISPLAY_TOAST = 1,\n    MES_ALERT_EVT_VIBRATE = 2,\n    MES_ALERT_EVT_PLAY_SOUND = 3,\n    MES_ALERT_EVT_PLAY_RINGTONE = 4,\n    MES_ALERT_EVT_FIND_MY_PHONE = 5,\n    MES_ALERT_EVT_ALARM1 = 6,\n    MES_ALERT_EVT_ALARM2 = 7,\n    MES_ALERT_EVT_ALARM3 = 8,\n    MES_ALERT_EVT_ALARM4 = 9,\n    MES_ALERT_EVT_ALARM5 = 10,\n    MES_ALERT_EVT_ALARM6 = 11,\n    MES_SIGNAL_STRENGTH_ID = 1101,\n    MES_SIGNAL_STRENGTH_EVT_NO_BAR = 1,\n    MES_SIGNAL_STRENGTH_EVT_ONE_BAR = 2,\n    MES_SIGNAL_STRENGTH_EVT_TWO_BAR = 3,\n    MES_SIGNAL_STRENGTH_EVT_THREE_BAR = 4,\n    MES_SIGNAL_STRENGTH_EVT_FOUR_BAR = 5,\n    MES_DEVICE_INFO_ID = 1103,\n    MES_DEVICE_ORIENTATION_LANDSCAPE = 1,\n    MES_DEVICE_ORIENTATION_PORTRAIT = 2,\n    MES_DEVICE_GESTURE_NONE = 3,\n    MES_DEVICE_GESTURE_DEVICE_SHAKEN = 4,\n    MES_DEVICE_DISPLAY_OFF = 5,\n    MES_DEVICE_DISPLAY_ON = 6,\n    MES_DEVICE_INCOMING_CALL = 7,\n    MES_DEVICE_INCOMING_MESSAGE = 8,\n    MES_DPAD_CONTROLLER_ID = 1104,\n    MES_DPAD_BUTTON_A_DOWN = 1,\n    MES_DPAD_BUTTON_A_UP = 2,\n    MES_DPAD_BUTTON_B_DOWN = 3,\n    MES_DPAD_BUTTON_B_UP = 4,\n    MES_DPAD_BUTTON_C_DOWN = 5,\n    MES_DPAD_BUTTON_C_UP = 6,\n    MES_DPAD_BUTTON_D_DOWN = 7,\n    MES_DPAD_BUTTON_D_UP = 8,\n    MES_DPAD_BUTTON_1_DOWN = 9,\n    MES_DPAD_BUTTON_1_UP = 10,\n    MES_DPAD_BUTTON_2_DOWN = 11,\n    MES_DPAD_BUTTON_2_UP = 12,\n    MES_DPAD_BUTTON_3_DOWN = 13,\n    MES_DPAD_BUTTON_3_UP = 14,\n    MES_DPAD_BUTTON_4_DOWN = 15,\n    MES_DPAD_BUTTON_4_UP = 16,\n    MES_BROADCAST_GENERAL_ID = 2000,\n    // /libraries/codal-microbit-v2/inc/bluetooth/MicroBitBLEManager.h\n    MICROBIT_BLE_PAIR_REQUEST = 1,\n    MICROBIT_BLE_PAIR_COMPLETE = 2,\n    MICROBIT_BLE_PAIR_PASSCODE = 4,\n    MICROBIT_BLE_PAIR_SUCCESSFUL = 8,\n    MICROBIT_BLE_PAIRING_TIMEOUT = 90,\n    MICROBIT_BLE_POWER_LEVELS = 8,\n    MICROBIT_BLE_EDDYSTONE_ADV_INTERVAL = 400,\n    MICROBIT_BLE_EDDYSTONE_DEFAULT_POWER = 240,\n    MICROBIT_BLE_STATUS_DISCONNECT = 4,\n    MICROBIT_BLE_STATUS_SHUTDOWN = 8,\n    MICROBIT_MODE_PAIRING = 0,\n    MICROBIT_MODE_APPLICATION = 1,\n    // /libraries/codal-microbit-v2/inc/bluetooth/MicroBitBLETypes.h\n    MICROBIT_DMESG_LEVEL_OFF = 0,\n    MICROBIT_DMESG_LEVEL_ERROR = 1,\n    MICROBIT_DMESG_LEVEL_WARNING = 2,\n    MICROBIT_DMESG_LEVEL_INFO = 3,\n    MICROBIT_DMESG_LEVEL_DEBUG = 4,\n    MICROBIT_DMESG_LEVEL = 0,\n    // /libraries/codal-microbit-v2/inc/bluetooth/MicroBitIOPinService.h\n    MICROBIT_IO_PIN_SERVICE_PINCOUNT = 19,\n    MICROBIT_IO_PIN_SERVICE_DATA_SIZE = 10,\n    MICROBIT_PWM_PIN_SERVICE_DATA_SIZE = 2,\n    // /libraries/codal-microbit-v2/inc/bluetooth/MicroBitLEDService.h\n    MICROBIT_BLE_MAXIMUM_SCROLLTEXT = 20,\n    // /libraries/codal-microbit-v2/inc/bluetooth/MicroBitMagnetometerService.h\n    COMPASS_CALIBRATION_STATUS_UNKNOWN = 0,\n    COMPASS_CALIBRATION_REQUESTED = 1,\n    COMPASS_CALIBRATION_COMPLETED_OK = 2,\n    COMPASS_CALIBRATION_COMPLETED_ERR = 3,\n    // /libraries/codal-microbit-v2/inc/bluetooth/MicroBitPartialFlashingService.h\n    PARTIAL_FLASHING_VERSION = 1,\n    REGION_INFO = 0,\n    FLASH_DATA = 1,\n    END_OF_TRANSMISSION = 2,\n    MICROBIT_STATUS = 238,\n    MICROBIT_RESET = 255,\n    // /libraries/codal-microbit-v2/inc/bluetooth/MicroBitUARTService.h\n    MICROBIT_UART_S_DEFAULT_BUF_SIZE = 20,\n    MICROBIT_UART_S_EVT_DELIM_MATCH = 1,\n    MICROBIT_UART_S_EVT_HEAD_MATCH = 2,\n    MICROBIT_UART_S_EVT_RX_FULL = 3,\n    // /libraries/codal-microbit-v2/inc/compat/MicroBitCompat.h\n    MICROBIT_BUSY = -1006,\n    MICROBIT_CANCELLED = -1007,\n    MICROBIT_CALIBRATION_IN_PROGRESS = -1003,\n    MICROBIT_CALIBRATION_REQUIRED = -1004,\n    MICROBIT_HEAP_ERROR = 30,\n    MICROBIT_I2C_ERROR = -1010,\n    MICROBIT_INVALID_PARAMETER = -1001,\n    MICROBIT_NO_DATA = -1012,\n    MICROBIT_NO_RESOURCES = -1005,\n    MICROBIT_NOT_SUPPORTED = -1002,\n    MICROBIT_NULL_DEREFERENCE = 40,\n    MICROBIT_OK = 0,\n    MICROBIT_OOM = 20,\n    MICROBIT_SERIAL_IN_USE = -1011,\n    MICROBIT_ACCELEROMETER_3G_TOLERANCE = 3072,\n    MICROBIT_ACCELEROMETER_6G_TOLERANCE = 6144,\n    MICROBIT_ACCELEROMETER_8G_TOLERANCE = 8192,\n    MICROBIT_ACCELEROMETER_FREEFALL_TOLERANCE = 400,\n    MICROBIT_ACCELEROMETER_GESTURE_DAMPING = 5,\n    MICROBIT_ACCELEROMETER_REST_TOLERANCE = 200,\n    MICROBIT_ACCELEROMETER_SHAKE_COUNT_THRESHOLD = 4,\n    MICROBIT_ACCELEROMETER_SHAKE_DAMPING = 10,\n    MICROBIT_ACCELEROMETER_SHAKE_RTX = 30,\n    MICROBIT_ACCELEROMETER_SHAKE_TOLERANCE = 400,\n    MICROBIT_ACCELEROMETER_TILT_TOLERANCE = 200,\n    MICROBIT_COMPONENT_RUNNING = 4096,\n    MICROBIT_DEFAULT_PRINT_SPEED = 400,\n    MICROBIT_DEFAULT_SCROLL_SPEED = 120,\n    MICROBIT_DEFAULT_SCROLL_STRIDE = -1,\n    MICROBIT_DISPLAY_DEFAULT_AUTOCLEAR = 1,\n    MICROBIT_DISPLAY_DEFAULT_BRIGHTNESS = 255,\n    MICROBIT_DISPLAY_GREYSCALE_BIT_DEPTH = 8,\n    MICROBIT_DISPLAY_MAXIMUM_BRIGHTNESS = 255,\n    MICROBIT_DISPLAY_MINIMUM_BRIGHTNESS = 1,\n    MICROBIT_DISPLAY_ROTATION_0 = 0,\n    MICROBIT_DISPLAY_ROTATION_180 = 2,\n    MICROBIT_DISPLAY_ROTATION_270 = 3,\n    MICROBIT_DISPLAY_ROTATION_90 = 1,\n    MICROBIT_EVENT_DEFAULT_LAUNCH_MODE = 1,\n    MICROBIT_DISPLAY_ANIMATE_DEFAULT_POS = -255,\n    MICROBIT_FONT_ASCII_END = 126,\n    MICROBIT_FONT_ASCII_START = 32,\n    MICROBIT_FONT_HEIGHT = 5,\n    MICROBIT_FONT_WIDTH = 5,\n    MICROBIT_I2C_MAX_RETRIES = 1,\n    MICROBIT_PIN_DEFAULT_SERVO_CENTER = 1500,\n    MICROBIT_PIN_DEFAULT_SERVO_RANGE = 2000,\n    MICROBIT_PIN_EVENT_NONE = 0,\n    MICROBIT_PIN_EVENT_ON_EDGE = 2,\n    MICROBIT_PIN_EVENT_ON_PULSE = 3,\n    MICROBIT_PIN_EVENT_ON_TOUCH = 4,\n    MICROBIT_PIN_EVT_FALL = 3,\n    MICROBIT_PIN_EVT_PULSE_HI = 4,\n    MICROBIT_PIN_EVT_PULSE_LO = 5,\n    MICROBIT_PIN_EVT_RISE = 2,\n    MICROBIT_PIN_MAX_OUTPUT = 1023,\n    MICROBIT_PIN_MAX_SERVO_RANGE = 180,\n    MICROBIT_UART_S_EVT_TX_EMPTY = 3,\n    MICROBIT_ACCELEROMETER_EVT_3G = 8,\n    MICROBIT_ACCELEROMETER_EVT_6G = 9,\n    MICROBIT_ACCELEROMETER_EVT_8G = 10,\n    MICROBIT_ACCELEROMETER_EVT_DATA_UPDATE = 1,\n    MICROBIT_ACCELEROMETER_EVT_FACE_DOWN = 6,\n    MICROBIT_ACCELEROMETER_EVT_FACE_UP = 5,\n    MICROBIT_ACCELEROMETER_EVT_FREEFALL = 7,\n    MICROBIT_ACCELEROMETER_EVT_NONE = 0,\n    MICROBIT_ACCELEROMETER_EVT_SHAKE = 11,\n    MICROBIT_ACCELEROMETER_EVT_TILT_DOWN = 2,\n    MICROBIT_ACCELEROMETER_EVT_TILT_LEFT = 3,\n    MICROBIT_ACCELEROMETER_EVT_TILT_RIGHT = 4,\n    MICROBIT_ACCELEROMETER_EVT_TILT_UP = 1,\n    MICROBIT_BUTTON_ALL_EVENTS = 1,\n    MICROBIT_BUTTON_SIMPLE_EVENTS = 0,\n    MICROBIT_BUTTON_EVT_CLICK = 3,\n    MICROBIT_BUTTON_EVT_DOUBLE_CLICK = 6,\n    MICROBIT_BUTTON_EVT_DOWN = 1,\n    MICROBIT_BUTTON_EVT_HOLD = 5,\n    MICROBIT_BUTTON_EVT_LONG_CLICK = 4,\n    MICROBIT_BUTTON_EVT_UP = 2,\n    MICROBIT_COMPASS_EVT_CALIBRATE = 3,\n    MICROBIT_COMPASS_EVT_CONFIG_NEEDED = 2,\n    MICROBIT_COMPASS_EVT_DATA_UPDATE = 1,\n    MICROBIT_COMPASS_EVT_CALIBRATION_NEEDED = 4,\n    MICROBIT_DISPLAY_EVT_ANIMATION_COMPLETE = 1,\n    MICROBIT_DISPLAY_EVT_FREE = 1,\n    MICROBIT_SERIAL_EVT_DELIM_MATCH = 1,\n    MICROBIT_SERIAL_EVT_HEAD_MATCH = 2,\n    MICROBIT_SERIAL_EVT_RX_FULL = 3,\n    MICROBIT_SERIAL_EVT_TX_EMPTY = 2,\n    MICROBIT_ID_ANY = 0,\n    MICROBIT_EVT_ANY = 0,\n    MICROBIT_ID_ACCELEROMETER = 5,\n    MICROBIT_ID_BUTTON_A = 1,\n    MICROBIT_ID_BUTTON_B = 2,\n    MICROBIT_ID_BUTTON_AB = 3,\n    MICROBIT_ID_BUTTON_RESET = 4,\n    MICROBIT_ID_COMPASS = 6,\n    MICROBIT_ID_DISPLAY = 7,\n    MICROBIT_ID_GESTURE = 13,\n    MICROBIT_ID_IO_P0 = 100,\n    MICROBIT_ID_IO_P1 = 101,\n    MICROBIT_ID_IO_P2 = 102,\n    MICROBIT_ID_IO_P3 = 103,\n    MICROBIT_ID_IO_P4 = 104,\n    MICROBIT_ID_IO_P5 = 105,\n    MICROBIT_ID_IO_P6 = 106,\n    MICROBIT_ID_IO_P7 = 107,\n    MICROBIT_ID_IO_P8 = 108,\n    MICROBIT_ID_IO_P9 = 109,\n    MICROBIT_ID_IO_P10 = 110,\n    MICROBIT_ID_IO_P11 = 111,\n    MICROBIT_ID_IO_P12 = 112,\n    MICROBIT_ID_IO_P13 = 113,\n    MICROBIT_ID_IO_P14 = 114,\n    MICROBIT_ID_IO_P15 = 115,\n    MICROBIT_ID_IO_P16 = 116,\n    MICROBIT_ID_IO_P19 = 119,\n    MICROBIT_ID_IO_P20 = 120,\n    MICROBIT_ID_LOGO = 121,\n    MICROBIT_ID_MESSAGE_BUS_LISTENER = 1021,\n    MICROBIT_ID_MULTIBUTTON_ATTACH = 11,\n    MICROBIT_ID_NOTIFY = 1023,\n    MICROBIT_ID_NOTIFY_ONE = 1022,\n    MICROBIT_ID_RADIO = 9,\n    MICROBIT_ID_RADIO_DATA_READY = 10,\n    MICROBIT_ID_SERIAL = 12,\n    MICROBIT_ID_THERMOMETER = 8,\n    MICROBIT_ID_POWER_MANAGER = 40,\n    MICROBIT_ID_PARTIAL_FLASHING = 41,\n    MICROBIT_ID_USB_FLASH_MANAGER = 42,\n    MICROBIT_ID_VIRTUAL_SPEAKER_PIN = 43,\n    MICROBIT_ID_LOG = 44,\n    MICROBIT_ID_UTILITY = 45,\n    MICROBIT_NESTED_HEAP_SIZE = 0,\n    MICROBIT_SCHEDULER_RUNNING = 1,\n    MICROBIT_SERIAL_DEFAULT_BAUD_RATE = 115200,\n    MICROBIT_SERIAL_DEFAULT_BUFFER_SIZE = 20,\n    MICROBIT_ACCEL_ADDED_TO_IDLE = 8,\n    MICROBIT_COMPASS_STATUS_ADDED_TO_IDLE = 8,\n    // /libraries/codal-microbit-v2/model/MicroBit.h\n    DEVICE_INITIALIZED = 1,\n    KL27_POWER_ON_DELAY = 1000,\n    DEVICE_ID_MICROPHONE = 3001,\n    // /libraries/codal-microbit-v2/model/MicroBitIO.h\n    MICROBIT_PIN_BUTTON_RESET = -1,\n    ID_PIN_P0 = 100,\n    ID_PIN_P1 = 101,\n    ID_PIN_P2 = 102,\n    ID_PIN_P3 = 103,\n    ID_PIN_P4 = 104,\n    ID_PIN_P5 = 105,\n    ID_PIN_P6 = 106,\n    ID_PIN_P7 = 107,\n    ID_PIN_P8 = 108,\n    ID_PIN_P9 = 109,\n    ID_PIN_P10 = 110,\n    ID_PIN_P11 = 111,\n    ID_PIN_P12 = 112,\n    ID_PIN_P13 = 113,\n    ID_PIN_P14 = 114,\n    ID_PIN_P15 = 115,\n    ID_PIN_P16 = 116,\n    ID_PIN_P17 = 117,\n    ID_PIN_P18 = 118,\n    ID_PIN_P19 = 119,\n    ID_PIN_P20 = 120,\n    ID_PIN_LOGO = 121,\n    ID_PIN_SPEAKER = 122,\n    ID_PIN_RUNMIC = 123,\n    ID_PIN_SDA = 124,\n    ID_PIN_SCL = 125,\n    ID_PIN_ROW1 = 126,\n    ID_PIN_ROW2 = 127,\n    ID_PIN_ROW3 = 128,\n    ID_PIN_ROW4 = 129,\n    ID_PIN_ROW5 = 130,\n    ID_PIN_USBTX = 131,\n    ID_PIN_USBRX = 132,\n    ID_PIN_IRQ1 = 133,\n    ID_PIN_MIC = 134,\n    ID_PIN_P35 = 135,\n    ID_PIN_P36 = 136,\n    ID_PIN_P37 = 137,\n    ID_PIN_P38 = 138,\n    ID_PIN_P39 = 139,\n    ID_PIN_P40 = 140,\n    ID_PIN_P41 = 141,\n    ID_PIN_P42 = 142,\n    ID_PIN_P43 = 143,\n    ID_PIN_P44 = 144,\n    ID_PIN_P45 = 145,\n    ID_PIN_P46 = 146,\n    ID_PIN_P47 = 147,\n    IO_SAVED_STATUS_OUTPUT_NA = 0,\n    IO_SAVED_STATUS_OUTPUT_LO = 1,\n    IO_SAVED_STATUS_OUTPUT_HI = 2,\n    IO_SAVED_STATUS_DETECT_LOW_ENABLED = 4,\n    IO_SAVED_STATUS_DETECT_HIGH_ENABLED = 8,\n    IO_SAVED_STATUS_SAVED = 1,\n    // /pxtapp/configkeys.h\n    CFG_PIN_NAME_MSK = 65535,\n    CFG_PIN_CONFIG_MSK = 4294901760,\n    CFG_PIN_CONFIG_ACTIVE_LO = 65536,\n    CFG_MAGIC0 = 513675505,\n    CFG_MAGIC1 = 539130489,\n    CFG_PIN_ACCELEROMETER_INT = 1,\n    CFG_PIN_ACCELEROMETER_SCL = 2,\n    CFG_PIN_ACCELEROMETER_SDA = 3,\n    CFG_PIN_BTN_A = 4,\n    CFG_PIN_BTN_B = 5,\n    CFG_PIN_BTN_SLIDE = 6,\n    CFG_PIN_DOTSTAR_CLOCK = 7,\n    CFG_PIN_DOTSTAR_DATA = 8,\n    CFG_PIN_FLASH_CS = 9,\n    CFG_PIN_FLASH_MISO = 10,\n    CFG_PIN_FLASH_MOSI = 11,\n    CFG_PIN_FLASH_SCK = 12,\n    CFG_PIN_LED = 13,\n    CFG_PIN_LIGHT = 14,\n    CFG_PIN_MICROPHONE = 15,\n    CFG_PIN_MIC_CLOCK = 16,\n    CFG_PIN_MIC_DATA = 17,\n    CFG_PIN_MISO = 18,\n    CFG_PIN_MOSI = 19,\n    CFG_PIN_NEOPIXEL = 20,\n    CFG_PIN_RX = 21,\n    CFG_PIN_RXLED = 22,\n    CFG_PIN_SCK = 23,\n    CFG_PIN_SCL = 24,\n    CFG_PIN_SDA = 25,\n    CFG_PIN_SPEAKER_AMP = 26,\n    CFG_PIN_TEMPERATURE = 27,\n    CFG_PIN_TX = 28,\n    CFG_PIN_TXLED = 29,\n    CFG_PIN_IR_OUT = 30,\n    CFG_PIN_IR_IN = 31,\n    CFG_PIN_DISPLAY_SCK = 32,\n    CFG_PIN_DISPLAY_MISO = 33,\n    CFG_PIN_DISPLAY_MOSI = 34,\n    CFG_PIN_DISPLAY_CS = 35,\n    CFG_PIN_DISPLAY_DC = 36,\n    CFG_DISPLAY_WIDTH = 37,\n    CFG_DISPLAY_HEIGHT = 38,\n    CFG_DISPLAY_CFG0 = 39,\n    CFG_DISPLAY_CFG1 = 40,\n    CFG_DISPLAY_CFG2 = 41,\n    CFG_DISPLAY_CFG3 = 42,\n    CFG_PIN_DISPLAY_RST = 43,\n    CFG_PIN_DISPLAY_BL = 44,\n    CFG_PIN_SERVO_1 = 45,\n    CFG_PIN_SERVO_2 = 46,\n    CFG_PIN_BTN_LEFT = 47,\n    CFG_PIN_BTN_RIGHT = 48,\n    CFG_PIN_BTN_UP = 49,\n    CFG_PIN_BTN_DOWN = 50,\n    CFG_PIN_BTN_MENU = 51,\n    CFG_PIN_LED_R = 52,\n    CFG_PIN_LED_G = 53,\n    CFG_PIN_LED_B = 54,\n    CFG_PIN_LED1 = 55,\n    CFG_PIN_LED2 = 56,\n    CFG_PIN_LED3 = 57,\n    CFG_PIN_LED4 = 58,\n    CFG_SPEAKER_VOLUME = 59,\n    CFG_PIN_JACK_TX = 60,\n    CFG_PIN_JACK_SENSE = 61,\n    CFG_PIN_JACK_HPEN = 62,\n    CFG_PIN_JACK_BZEN = 63,\n    CFG_PIN_JACK_PWREN = 64,\n    CFG_PIN_JACK_SND = 65,\n    CFG_PIN_JACK_BUSLED = 66,\n    CFG_PIN_JACK_COMMLED = 67,\n    CFG_PIN_BTN_SOFT_RESET = 69,\n    CFG_ACCELEROMETER_TYPE = 70,\n    CFG_PIN_BTNMX_LATCH = 71,\n    CFG_PIN_BTNMX_CLOCK = 72,\n    CFG_PIN_BTNMX_DATA = 73,\n    CFG_PIN_BTN_MENU2 = 74,\n    CFG_PIN_BATTSENSE = 75,\n    CFG_PIN_VIBRATION = 76,\n    CFG_PIN_PWREN = 77,\n    CFG_DISPLAY_TYPE = 78,\n    CFG_PIN_ROTARY_ENCODER_A = 79,\n    CFG_PIN_ROTARY_ENCODER_B = 80,\n    CFG_ACCELEROMETER_SPACE = 81,\n    CFG_PIN_WIFI_MOSI = 82,\n    CFG_PIN_WIFI_MISO = 83,\n    CFG_PIN_WIFI_SCK = 84,\n    CFG_PIN_WIFI_TX = 85,\n    CFG_PIN_WIFI_RX = 86,\n    CFG_PIN_WIFI_CS = 87,\n    CFG_PIN_WIFI_BUSY = 88,\n    CFG_PIN_WIFI_RESET = 89,\n    CFG_PIN_WIFI_GPIO0 = 90,\n    CFG_PIN_WIFI_AT_TX = 91,\n    CFG_PIN_WIFI_AT_RX = 92,\n    CFG_PIN_USB_POWER = 93,\n    CFG_DISPLAY_DELAY = 94,\n    CFG_SETTINGS_SIZE_DEFL = 95,\n    CFG_SETTINGS_SIZE = 96,\n    ACCELEROMETER_TYPE_LIS3DH = 50,\n    ACCELEROMETER_TYPE_LIS3DH_ALT = 48,\n    ACCELEROMETER_TYPE_MMA8453 = 56,\n    ACCELEROMETER_TYPE_FXOS8700 = 60,\n    ACCELEROMETER_TYPE_MMA8653 = 58,\n    ACCELEROMETER_TYPE_MSA300 = 76,\n    ACCELEROMETER_TYPE_MPU6050 = 104,\n    DISPLAY_TYPE_ST7735 = 7735,\n    DISPLAY_TYPE_ILI9341 = 9341,\n    DISPLAY_TYPE_SMART = 4242,\n    CFG_PIN_A0 = 100,\n    CFG_PIN_A1 = 101,\n    CFG_PIN_A2 = 102,\n    CFG_PIN_A3 = 103,\n    CFG_PIN_A4 = 104,\n    CFG_PIN_A5 = 105,\n    CFG_PIN_A6 = 106,\n    CFG_PIN_A7 = 107,\n    CFG_PIN_A8 = 108,\n    CFG_PIN_A9 = 109,\n    CFG_PIN_A10 = 110,\n    CFG_PIN_A11 = 111,\n    CFG_PIN_A12 = 112,\n    CFG_PIN_A13 = 113,\n    CFG_PIN_A14 = 114,\n    CFG_PIN_A15 = 115,\n    CFG_PIN_A16 = 116,\n    CFG_PIN_A17 = 117,\n    CFG_PIN_A18 = 118,\n    CFG_PIN_A19 = 119,\n    CFG_PIN_A20 = 120,\n    CFG_PIN_A21 = 121,\n    CFG_PIN_A22 = 122,\n    CFG_PIN_A23 = 123,\n    CFG_PIN_A24 = 124,\n    CFG_PIN_A25 = 125,\n    CFG_PIN_A26 = 126,\n    CFG_PIN_A27 = 127,\n    CFG_PIN_A28 = 128,\n    CFG_PIN_A29 = 129,\n    CFG_PIN_A30 = 130,\n    CFG_PIN_A31 = 131,\n    CFG_PIN_D0 = 150,\n    CFG_PIN_D1 = 151,\n    CFG_PIN_D2 = 152,\n    CFG_PIN_D3 = 153,\n    CFG_PIN_D4 = 154,\n    CFG_PIN_D5 = 155,\n    CFG_PIN_D6 = 156,\n    CFG_PIN_D7 = 157,\n    CFG_PIN_D8 = 158,\n    CFG_PIN_D9 = 159,\n    CFG_PIN_D10 = 160,\n    CFG_PIN_D11 = 161,\n    CFG_PIN_D12 = 162,\n    CFG_PIN_D13 = 163,\n    CFG_PIN_D14 = 164,\n    CFG_PIN_D15 = 165,\n    CFG_PIN_D16 = 166,\n    CFG_PIN_D17 = 167,\n    CFG_PIN_D18 = 168,\n    CFG_PIN_D19 = 169,\n    CFG_PIN_D20 = 170,\n    CFG_PIN_D21 = 171,\n    CFG_PIN_D22 = 172,\n    CFG_PIN_D23 = 173,\n    CFG_PIN_D24 = 174,\n    CFG_PIN_D25 = 175,\n    CFG_PIN_D26 = 176,\n    CFG_PIN_D27 = 177,\n    CFG_PIN_D28 = 178,\n    CFG_PIN_D29 = 179,\n    CFG_PIN_D30 = 180,\n    CFG_PIN_D31 = 181,\n    CFG_NUM_NEOPIXELS = 200,\n    CFG_NUM_DOTSTARS = 201,\n    CFG_DEFAULT_BUTTON_MODE = 202,\n    CFG_SWD_ENABLED = 203,\n    CFG_FLASH_BYTES = 204,\n    CFG_RAM_BYTES = 205,\n    CFG_SYSTEM_HEAP_BYTES = 206,\n    CFG_LOW_MEM_SIMULATION_KB = 207,\n    CFG_BOOTLOADER_BOARD_ID = 208,\n    CFG_UF2_FAMILY = 209,\n    CFG_PINS_PORT_SIZE = 210,\n    CFG_BOOTLOADER_PROTECTION = 211,\n    CFG_POWER_DEEPSLEEP_TIMEOUT = 212,\n    CFG_ANALOG_BUTTON_THRESHOLD = 213,\n    CFG_CPU_MHZ = 214,\n    CFG_CONTROLLER_LIGHT_MAX_BRIGHTNESS = 215,\n    CFG_ANALOG_JOYSTICK_MIN = 216,\n    CFG_ANALOG_JOYSTICK_MAX = 217,\n    CFG_TIMERS_TO_USE = 218,\n    CFG_PIN_ONBOARD_DOTSTAR_CLOCK = 219,\n    CFG_PIN_ONBOARD_DOTSTAR_DATA = 220,\n    CFG_NUM_ONBOARD_DOTSTARS = 221,\n    CFG_PIN_ONBOARD_NEOPIXEL = 222,\n    CFG_NUM_ONBOARD_NEOPIXELS = 223,\n    CFG_MATRIX_KEYPAD_MESSAGE_ID = 239,\n    CFG_NUM_MATRIX_KEYPAD_ROWS = 240,\n    CFG_PIN_MATRIX_KEYPAD_ROW0 = 241,\n    CFG_PIN_MATRIX_KEYPAD_ROW1 = 242,\n    CFG_PIN_MATRIX_KEYPAD_ROW2 = 243,\n    CFG_PIN_MATRIX_KEYPAD_ROW3 = 244,\n    CFG_PIN_MATRIX_KEYPAD_ROW4 = 245,\n    CFG_PIN_MATRIX_KEYPAD_ROW5 = 246,\n    CFG_PIN_MATRIX_KEYPAD_ROW6 = 247,\n    CFG_PIN_MATRIX_KEYPAD_ROW7 = 248,\n    CFG_NUM_MATRIX_KEYPAD_COLS = 250,\n    CFG_PIN_MATRIX_KEYPAD_COL0 = 251,\n    CFG_PIN_MATRIX_KEYPAD_COL1 = 252,\n    CFG_PIN_MATRIX_KEYPAD_COL2 = 253,\n    CFG_PIN_MATRIX_KEYPAD_COL3 = 254,\n    CFG_PIN_MATRIX_KEYPAD_COL4 = 255,\n    CFG_PIN_MATRIX_KEYPAD_COL5 = 256,\n    CFG_PIN_MATRIX_KEYPAD_COL6 = 257,\n    CFG_PIN_MATRIX_KEYPAD_COL7 = 258,\n    CFG_PIN_B0 = 300,\n    CFG_PIN_B1 = 301,\n    CFG_PIN_B2 = 302,\n    CFG_PIN_B3 = 303,\n    CFG_PIN_B4 = 304,\n    CFG_PIN_B5 = 305,\n    CFG_PIN_B6 = 306,\n    CFG_PIN_B7 = 307,\n    CFG_PIN_B8 = 308,\n    CFG_PIN_B9 = 309,\n    CFG_PIN_B10 = 310,\n    CFG_PIN_B11 = 311,\n    CFG_PIN_B12 = 312,\n    CFG_PIN_B13 = 313,\n    CFG_PIN_B14 = 314,\n    CFG_PIN_B15 = 315,\n    CFG_PIN_B16 = 316,\n    CFG_PIN_B17 = 317,\n    CFG_PIN_B18 = 318,\n    CFG_PIN_B19 = 319,\n    CFG_PIN_B20 = 320,\n    CFG_PIN_B21 = 321,\n    CFG_PIN_B22 = 322,\n    CFG_PIN_B23 = 323,\n    CFG_PIN_B24 = 324,\n    CFG_PIN_B25 = 325,\n    CFG_PIN_B26 = 326,\n    CFG_PIN_B27 = 327,\n    CFG_PIN_B28 = 328,\n    CFG_PIN_B29 = 329,\n    CFG_PIN_B30 = 330,\n    CFG_PIN_B31 = 331,\n    CFG_PIN_C0 = 350,\n    CFG_PIN_C1 = 351,\n    CFG_PIN_C2 = 352,\n    CFG_PIN_C3 = 353,\n    CFG_PIN_C4 = 354,\n    CFG_PIN_C5 = 355,\n    CFG_PIN_C6 = 356,\n    CFG_PIN_C7 = 357,\n    CFG_PIN_C8 = 358,\n    CFG_PIN_C9 = 359,\n    CFG_PIN_C10 = 360,\n    CFG_PIN_C11 = 361,\n    CFG_PIN_C12 = 362,\n    CFG_PIN_C13 = 363,\n    CFG_PIN_C14 = 364,\n    CFG_PIN_C15 = 365,\n    CFG_PIN_C16 = 366,\n    CFG_PIN_C17 = 367,\n    CFG_PIN_C18 = 368,\n    CFG_PIN_C19 = 369,\n    CFG_PIN_C20 = 370,\n    CFG_PIN_C21 = 371,\n    CFG_PIN_C22 = 372,\n    CFG_PIN_C23 = 373,\n    CFG_PIN_C24 = 374,\n    CFG_PIN_C25 = 375,\n    CFG_PIN_C26 = 376,\n    CFG_PIN_C27 = 377,\n    CFG_PIN_C28 = 378,\n    CFG_PIN_C29 = 379,\n    CFG_PIN_C30 = 380,\n    CFG_PIN_C31 = 381,\n    CFG_PIN_P0 = 400,\n    CFG_PIN_P1 = 401,\n    CFG_PIN_P2 = 402,\n    CFG_PIN_P3 = 403,\n    CFG_PIN_P4 = 404,\n    CFG_PIN_P5 = 405,\n    CFG_PIN_P6 = 406,\n    CFG_PIN_P7 = 407,\n    CFG_PIN_P8 = 408,\n    CFG_PIN_P9 = 409,\n    CFG_PIN_P10 = 410,\n    CFG_PIN_P11 = 411,\n    CFG_PIN_P12 = 412,\n    CFG_PIN_P13 = 413,\n    CFG_PIN_P14 = 414,\n    CFG_PIN_P15 = 415,\n    CFG_PIN_P16 = 416,\n    CFG_PIN_P17 = 417,\n    CFG_PIN_P18 = 418,\n    CFG_PIN_P19 = 419,\n    CFG_PIN_P20 = 420,\n    CFG_PIN_P21 = 421,\n    CFG_PIN_P22 = 422,\n    CFG_PIN_P23 = 423,\n    CFG_PIN_P24 = 424,\n    CFG_PIN_P25 = 425,\n    CFG_PIN_P26 = 426,\n    CFG_PIN_P27 = 427,\n    CFG_PIN_P28 = 428,\n    CFG_PIN_P29 = 429,\n    CFG_PIN_P30 = 430,\n    CFG_PIN_P31 = 431,\n    CFG_PIN_P32 = 432,\n    CFG_PIN_P33 = 433,\n    CFG_PIN_P34 = 434,\n    CFG_PIN_P35 = 435,\n    CFG_PIN_P36 = 436,\n    CFG_PIN_P37 = 437,\n    CFG_PIN_P38 = 438,\n    CFG_PIN_P39 = 439,\n    CFG_PIN_P40 = 440,\n    CFG_PIN_P41 = 441,\n    CFG_PIN_P42 = 442,\n    CFG_PIN_P43 = 443,\n    CFG_PIN_P44 = 444,\n    CFG_PIN_P45 = 445,\n    CFG_PIN_P46 = 446,\n    CFG_PIN_P47 = 447,\n    CFG_PIN_P48 = 448,\n    CFG_PIN_P49 = 449,\n    CFG_PIN_P50 = 450,\n    CFG_PIN_P51 = 451,\n    CFG_PIN_P52 = 452,\n    CFG_PIN_P53 = 453,\n    CFG_PIN_P54 = 454,\n    CFG_PIN_P55 = 455,\n    CFG_PIN_P56 = 456,\n    CFG_PIN_P57 = 457,\n    CFG_PIN_P58 = 458,\n    CFG_PIN_P59 = 459,\n    CFG_PIN_P60 = 460,\n    CFG_PIN_P61 = 461,\n    CFG_PIN_P62 = 462,\n    CFG_PIN_P63 = 463,\n    CFG_PIN_LORA_MISO = 1001,\n    CFG_PIN_LORA_MOSI = 1002,\n    CFG_PIN_LORA_SCK = 1003,\n    CFG_PIN_LORA_CS = 1004,\n    CFG_PIN_LORA_BOOT = 1005,\n    CFG_PIN_LORA_RESET = 1006,\n    CFG_PIN_IRRXLED = 1007,\n    CFG_PIN_IRTXLED = 1008,\n    CFG_PIN_LCD_RESET = 1009,\n    CFG_PIN_LCD_ENABLE = 1010,\n    CFG_PIN_LCD_DATALINE4 = 1011,\n    CFG_PIN_LCD_DATALINE5 = 1012,\n    CFG_PIN_LCD_DATALINE6 = 1013,\n    CFG_PIN_LCD_DATALINE7 = 1014,\n    CFG_NUM_LCD_COLUMNS = 1015,\n    CFG_NUM_LCD_ROWS = 1016,\n    CFG_PIN_RCC0 = 1017,\n    CFG_PIN_RCC1 = 1018,\n    CFG_PIN_RCC2 = 1019,\n    CFG_PIN_RCC3 = 1020,\n    CFG_PIN_RCC4 = 1021,\n    CFG_PIN_RCC5 = 1022,\n    CFG_PIN_RCC6 = 1023,\n    CFG_PIN_RCC7 = 1024,\n    CFG_PIN_SERVO0 = 1025,\n    CFG_PIN_SERVO1 = 1026,\n    CFG_PIN_SERVO2 = 1027,\n    CFG_PIN_SERVO3 = 1028,\n    CFG_PIN_SERVO4 = 1029,\n    CFG_PIN_SERVO5 = 1030,\n    CFG_PIN_SERVO6 = 1031,\n    CFG_PIN_SERVO7 = 1032,\n    CFG_PIN_SERVO8 = 1033,\n    CFG_PIN_PI_TX = 1034,\n    CFG_PIN_PI_RX = 1035,\n    CFG_PIN_GPS_SDA = 1036,\n    CFG_PIN_GPS_SCL = 1037,\n    CFG_PIN_GPS_TX = 1038,\n    CFG_PIN_GPS_RX = 1039,\n    CFG_PIN_GROVE0 = 1040,\n    CFG_PIN_GROVE1 = 1041,\n    CFG_PIN_SS = 1042,\n    CFG_PIN_D33 = 183,\n    CFG_PIN_D34 = 184,\n    CFG_PIN_D35 = 185,\n    CFG_PIN_D36 = 186,\n    CFG_PIN_D37 = 187,\n    CFG_PIN_D38 = 188,\n    CFG_PIN_D39 = 189,\n    CFG_PIN_D40 = 190,\n    CFG_PIN_D41 = 191,\n    CFG_PIN_D42 = 192,\n    CFG_PIN_D43 = 193,\n    CFG_PIN_D44 = 194,\n    CFG_PIN_D45 = 195,\n    CFG_PIN_D46 = 196,\n    CFG_PIN_D47 = 197,\n    CFG_PIN_D48 = 198,\n    CFG_PIN_D49 = 199,\n    CFG_PIN_D50 = 259,\n    CFG_PIN_D51 = 260,\n    CFG_PIN_D52 = 261,\n    CFG_PIN_D53 = 262,\n    CFG_PIN_TX1 = 263,\n    CFG_PIN_TX2 = 264,\n    CFG_PIN_TX3 = 265,\n    CFG_PIN_RX1 = 266,\n    CFG_PIN_RX2 = 267,\n    CFG_PIN_RX3 = 268,\n    CFG_PIN_SCL1 = 269,\n    CFG_PIN_SDA1 = 270,\n    CFG_PIN_PCC_D0 = 271,\n    CFG_PIN_PCC_D1 = 272,\n    CFG_PIN_PCC_D2 = 273,\n    CFG_PIN_PCC_D3 = 274,\n    CFG_PIN_PCC_D4 = 275,\n    CFG_PIN_PCC_D5 = 276,\n    CFG_PIN_PCC_D6 = 277,\n    CFG_PIN_PCC_D7 = 278,\n    CFG_PIN_PCC_D8 = 279,\n    CFG_PIN_PCC_D9 = 280,\n    CFG_PIN_PCC_D10 = 281,\n    CFG_PIN_PCC_D11 = 282,\n    CFG_PIN_PCC_D12 = 283,\n    CFG_PIN_PCC_D13 = 284,\n    CFG_PIN_CC_DEN1 = 285,\n    CFG_PIN_CC_DEN2 = 286,\n    CFG_PIN_CC_CLK = 287,\n    CFG_PIN_XCC_CLK = 288,\n    CFG_PIN_JDPWR_PRE_SENSE = 1100,\n    CFG_PIN_JDPWR_GND_SENSE = 1101,\n    CFG_PIN_JDPWR_PULSE = 1102,\n    CFG_PIN_JDPWR_OVERLOAD_LED = 1103,\n    CFG_PIN_JDPWR_ENABLE = 1104,\n    CFG_PIN_JDPWR_FAULT = 1105,\n    CFG_USER_CFG_0 = 2000,\n    CFG_USER_CFG_1 = 2001,\n    CFG_USER_CFG_2 = 2002,\n    CFG_USER_CFG_3 = 2003,\n    CFG_USER_CFG_4 = 2004,\n    CFG_USER_CFG_5 = 2005,\n    CFG_USER_CFG_6 = 2006,\n    CFG_USER_CFG_7 = 2007,\n    CFG_USER_CFG_8 = 2008,\n    CFG_USER_CFG_9 = 2009,\n    CFG_ARCADE_CFG_0 = 2100,\n    CFG_ARCADE_CFG_1 = 2101,\n    CFG_ARCADE_SCREEN_WIDTH = 2102,\n    CFG_ARCADE_SCREEN_HEIGHT = 2103,\n    // /pxtapp/platform.h\n    PXT_MICROBIT_TAGGED_INT = 1,\n    PXT_POWI = 1,\n    // /pxtapp/pxtbase.h\n    PXT_UTF8 = 0,\n    PXT32 = 1,\n    PXT64 = 1,\n    PXT_REFCNT_FLASH = 65534,\n    VTABLE_MAGIC = 249,\n    VTABLE_MAGIC2 = 248,\n    Undefined = 0,\n    Boolean = 1,\n    Number = 2,\n    String = 3,\n    Object = 4,\n    Function = 5,\n    BoxedString = 1,\n    BoxedNumber = 2,\n    BoxedBuffer = 3,\n    RefAction = 4,\n    RefImage = 5,\n    RefCollection = 6,\n    RefRefLocal = 7,\n    RefMap = 8,\n    RefMImage = 9,\n    MMap = 10,\n    BoxedString_SkipList = 11,\n    BoxedString_ASCII = 12,\n    ZPin = 13,\n    User0 = 16,\n    IMAGE_HEADER_MAGIC = 135,\n    Int8LE = 1,\n    UInt8LE = 2,\n    Int16LE = 3,\n    UInt16LE = 4,\n    Int32LE = 5,\n    Int8BE = 6,\n    UInt8BE = 7,\n    Int16BE = 8,\n    UInt16BE = 9,\n    Int32BE = 10,\n    UInt32LE = 11,\n    UInt32BE = 12,\n    Float32LE = 13,\n    Float64LE = 14,\n    Float32BE = 15,\n    Float64BE = 16,\n    NUM_TRY_FRAME_REGS = 3,\n    GC = 0,\n    PERF_NOW_MASK = 4294967295,\n    PERF_NOW_SCALE = 1,\n    PXT_STRING_SKIP_INCR = 16,\n    // /pxtapp/pxtcore.h\n    NON_GC_HEAP_RESERVATION = 1024,\n    GC_BLOCK_SIZE = 256,\n}\n","enums.d.ts":"// Auto-generated. Do not edit.\n\n\n    declare const enum NumberFormat {\n    Int8LE = 1,\n    UInt8LE = 2,\n    Int16LE = 3,\n    UInt16LE = 4,\n    Int32LE = 5,\n    Int8BE = 6,\n    UInt8BE = 7,\n    Int16BE = 8,\n    UInt16BE = 9,\n    Int32BE = 10,\n\n    UInt32LE = 11,\n    UInt32BE = 12,\n    Float32LE = 13,\n    Float64LE = 14,\n    Float32BE = 15,\n    Float64BE = 16,\n    }\n\n\n    declare const enum PerfCounters {\n    GC = 0,\n    }\ndeclare namespace images {\n}\ndeclare namespace basic {\n}\n\n\n    declare const enum Button {\n    A = 1,  // MICROBIT_ID_BUTTON_A\n    B = 2,  // MICROBIT_ID_BUTTON_B\n    //% block=\"A+B\"\n    AB = 3,  // MICROBIT_ID_BUTTON_AB\n    }\n\n\n    declare const enum Dimension {\n    //% block=x\n    X = 0,\n    //% block=y\n    Y = 1,\n    //% block=z\n    Z = 2,\n    //% block=strength\n    Strength = 3,\n    }\n\n\n    declare const enum Rotation {\n    //% block=pitch\n    Pitch = 0,\n    //% block=roll\n    Roll = 1,\n    }\n\n\n    declare const enum TouchPin {\n    P0 = 100,  // MICROBIT_ID_IO_P0\n    P1 = 101,  // MICROBIT_ID_IO_P1\n    P2 = 102,  // MICROBIT_ID_IO_P2\n    }\n\n\n    declare const enum AcceleratorRange {\n    /**\n     * The accelerator measures forces up to 1 gravity\n     */\n    //%  block=\"1g\"\n    OneG = 1,\n    /**\n     * The accelerator measures forces up to 2 gravity\n     */\n    //%  block=\"2g\"\n    TwoG = 2,\n    /**\n     * The accelerator measures forces up to 4 gravity\n     */\n    //% block=\"4g\"\n    FourG = 4,\n    /**\n     * The accelerator measures forces up to 8 gravity\n     */\n    //% block=\"8g\"\n    EightG = 8,\n    }\n\n\n    declare const enum Gesture {\n    /**\n     * Raised when shaken\n     */\n    //% block=shake\n    //% jres=gestures.shake\n    Shake = 11,  // MICROBIT_ACCELEROMETER_EVT_SHAKE\n    /**\n     * Raised when the logo is upward and the screen is vertical\n     */\n    //% block=\"logo up\"\n    //% jres=gestures.tiltforward\n    LogoUp = 1,  // MICROBIT_ACCELEROMETER_EVT_TILT_UP\n    /**\n     * Raised when the logo is downward and the screen is vertical\n     */\n    //% block=\"logo down\"\n    //% jres=gestures.tiltbackwards\n    LogoDown = 2,  // MICROBIT_ACCELEROMETER_EVT_TILT_DOWN\n    /**\n     * Raised when the screen is pointing up and the board is horizontal\n     */\n    //% block=\"screen up\"\n    //% jres=gestures.frontsideup\n    ScreenUp = 5,  // MICROBIT_ACCELEROMETER_EVT_FACE_UP\n    /**\n     * Raised when the screen is pointing down and the board is horizontal\n     */\n    //% block=\"screen down\"\n    //% jres=gestures.backsideup\n    ScreenDown = 6,  // MICROBIT_ACCELEROMETER_EVT_FACE_DOWN\n    /**\n     * Raised when the screen is pointing left\n     */\n    //% block=\"tilt left\"\n    //% jres=gestures.tiltleft\n    TiltLeft = 3,  // MICROBIT_ACCELEROMETER_EVT_TILT_LEFT\n    /**\n     * Raised when the screen is pointing right\n     */\n    //% block=\"tilt right\"\n    //% jres=gestures.tiltright\n    TiltRight = 4,  // MICROBIT_ACCELEROMETER_EVT_TILT_RIGHT\n    /**\n     * Raised when the board is falling!\n     */\n    //% block=\"free fall\"\n    //% jres=gestures.freefall\n    FreeFall = 7,  // MICROBIT_ACCELEROMETER_EVT_FREEFALL\n    /**\n     * Raised when a 3G shock is detected\n     */\n    //% block=\"3g\"\n    //% jres=gestures.impact3g\n    ThreeG = 8,  // MICROBIT_ACCELEROMETER_EVT_3G\n    /**\n     * Raised when a 6G shock is detected\n     */\n    //% block=\"6g\"\n    //% jres=gestures.impact6g\n    SixG = 9,  // MICROBIT_ACCELEROMETER_EVT_6G\n    /**\n     * Raised when a 8G shock is detected\n     */\n    //% block=\"8g\"\n    //% jres=gestures.impact8g\n    EightG = 10,  // MICROBIT_ACCELEROMETER_EVT_8G\n    }\n\n\n    declare const enum MesDpadButtonInfo {\n    //% block=\"A down\"\n    ADown = 1,  // MES_DPAD_BUTTON_A_DOWN\n    //% block=\"A up\"\n    AUp = 2,  // MES_DPAD_BUTTON_A_UP\n    //% block=\"B down\"\n    BDown = 3,  // MES_DPAD_BUTTON_B_DOWN\n    //% block=\"B up\"\n    BUp = 4,  // MES_DPAD_BUTTON_B_UP\n    //% block=\"C down\"\n    CDown = 5,  // MES_DPAD_BUTTON_C_DOWN\n    //% block=\"C up\"\n    CUp = 6,  // MES_DPAD_BUTTON_C_UP\n    //% block=\"D down\"\n    DDown = 7,  // MES_DPAD_BUTTON_D_DOWN\n    //% block=\"D up\"\n    DUp = 8,  // MES_DPAD_BUTTON_D_UP\n    //% block=\"1 down\"\n    _1Down = 9,  // MES_DPAD_BUTTON_1_DOWN\n    //% block=\"1 up\"\n    _1Up = 10,  // MES_DPAD_BUTTON_1_UP\n    //% block=\"2 down\"\n    _2Down = 11,  // MES_DPAD_BUTTON_2_DOWN\n    //% block=\"2 up\"\n    _2Up = 12,  // MES_DPAD_BUTTON_2_UP\n    //% block=\"3 down\"\n    _3Down = 13,  // MES_DPAD_BUTTON_3_DOWN\n    //% block=\"3 up\"\n    _3Up = 14,  // MES_DPAD_BUTTON_3_UP\n    //% block=\"4 down\"\n    _4Down = 15,  // MES_DPAD_BUTTON_4_DOWN\n    //% block=\"4 up\"\n    _4Up = 16,  // MES_DPAD_BUTTON_4_UP\n    }\ndeclare namespace input {\n}\n\n\n    /**\n     * How to create the event.\n     */\n\n    declare const enum EventCreationMode {\n    /**\n     * MicroBitEvent is initialised, and no further processing takes place.\n     */\n    CreateOnly = 0,  // CREATE_ONLY\n    /**\n     * MicroBitEvent is initialised, and its event handlers are immediately fired (not suitable for use in interrupts!).\n     */\n    CreateAndFire = 1,  // CREATE_AND_FIRE\n    }\n\n\n    declare const enum EventBusSource {\n    //% blockIdentity=\"control.eventSourceId\"\n    MICROBIT_ID_BUTTON_A = 1,  // MICROBIT_ID_BUTTON_A\n    //% blockIdentity=\"control.eventSourceId\"\n    MICROBIT_ID_BUTTON_B = 2,  // MICROBIT_ID_BUTTON_B\n    //% blockIdentity=\"control.eventSourceId\"\n    MICROBIT_ID_BUTTON_AB = 3,  // MICROBIT_ID_BUTTON_AB\n    //% blockIdentity=\"control.eventSourceId\"\n    MICROBIT_ID_RADIO = 9,  // MICROBIT_ID_RADIO\n    //% blockIdentity=\"control.eventSourceId\"\n    MICROBIT_ID_GESTURE = 13,  // MICROBIT_ID_GESTURE\n    //% blockIdentity=\"control.eventSourceId\"\n    MICROBIT_ID_ACCELEROMETER = 5,  // MICROBIT_ID_ACCELEROMETER\n    //% blockIdentity=\"control.eventSourceId\"\n    MICROBIT_ID_IO_P0 = 100,  // MICROBIT_ID_IO_P0\n    //% blockIdentity=\"control.eventSourceId\"\n    MICROBIT_ID_IO_P1 = 101,  // MICROBIT_ID_IO_P1\n    //% blockIdentity=\"control.eventSourceId\"\n    MICROBIT_ID_IO_P2 = 102,  // MICROBIT_ID_IO_P2\n    //% blockIdentity=\"control.eventSourceId\"\n    MICROBIT_ID_IO_P3 = 103,  // MICROBIT_ID_IO_P3\n    //% blockIdentity=\"control.eventSourceId\"\n    MICROBIT_ID_IO_P4 = 104,  // MICROBIT_ID_IO_P4\n    //% blockIdentity=\"control.eventSourceId\"\n    MICROBIT_ID_IO_P5 = 105,  // MICROBIT_ID_IO_P5\n    //% blockIdentity=\"control.eventSourceId\"\n    MICROBIT_ID_IO_P6 = 106,  // MICROBIT_ID_IO_P6\n    //% blockIdentity=\"control.eventSourceId\"\n    MICROBIT_ID_IO_P7 = 107,  // MICROBIT_ID_IO_P7\n    //% blockIdentity=\"control.eventSourceId\"\n    MICROBIT_ID_IO_P8 = 108,  // MICROBIT_ID_IO_P8\n    //% blockIdentity=\"control.eventSourceId\"\n    MICROBIT_ID_IO_P9 = 109,  // MICROBIT_ID_IO_P9\n    //% blockIdentity=\"control.eventSourceId\"\n    MICROBIT_ID_IO_P10 = 110,  // MICROBIT_ID_IO_P10\n    //% blockIdentity=\"control.eventSourceId\"\n    MICROBIT_ID_IO_P11 = 111,  // MICROBIT_ID_IO_P11\n    //% blockIdentity=\"control.eventSourceId\"\n    MICROBIT_ID_IO_P12 = 112,  // MICROBIT_ID_IO_P12\n    //% blockIdentity=\"control.eventSourceId\"\n    MICROBIT_ID_IO_P13 = 113,  // MICROBIT_ID_IO_P13\n    //% blockIdentity=\"control.eventSourceId\"\n    MICROBIT_ID_IO_P14 = 114,  // MICROBIT_ID_IO_P14\n    //% blockIdentity=\"control.eventSourceId\"\n    MICROBIT_ID_IO_P15 = 115,  // MICROBIT_ID_IO_P15\n    //% blockIdentity=\"control.eventSourceId\"\n    MICROBIT_ID_IO_P16 = 116,  // MICROBIT_ID_IO_P16\n    //% blockIdentity=\"control.eventSourceId\"\n    MICROBIT_ID_IO_P19 = 119,  // MICROBIT_ID_IO_P19\n    //% blockIdentity=\"control.eventSourceId\"\n    MICROBIT_ID_IO_P20 = 120,  // MICROBIT_ID_IO_P20\n    //% blockIdentity=\"control.eventSourceId\"\n    MES_DEVICE_INFO_ID = 1103,  // MES_DEVICE_INFO_ID\n    //% blockIdentity=\"control.eventSourceId\"\n    MES_SIGNAL_STRENGTH_ID = 1101,  // MES_SIGNAL_STRENGTH_ID\n    //% blockIdentity=\"control.eventSourceId\"\n    MES_DPAD_CONTROLLER_ID = 1104,  // MES_DPAD_CONTROLLER_ID\n    //% blockIdentity=\"control.eventSourceId\"\n    MES_BROADCAST_GENERAL_ID = 2000,  // MES_BROADCAST_GENERAL_ID\n    }\n\n\n    declare const enum EventBusValue {\n    //% blockIdentity=\"control.eventValueId\"\n    MICROBIT_EVT_ANY = 0,  // MICROBIT_EVT_ANY\n    //% blockIdentity=\"control.eventValueId\"\n    MICROBIT_BUTTON_EVT_DOWN = 1,  // MICROBIT_BUTTON_EVT_DOWN\n    //% blockIdentity=\"control.eventValueId\"\n    MICROBIT_BUTTON_EVT_UP = 2,  // MICROBIT_BUTTON_EVT_UP\n    //% blockIdentity=\"control.eventValueId\"\n    MICROBIT_BUTTON_EVT_CLICK = 3,  // MICROBIT_BUTTON_EVT_CLICK\n    //% blockIdentity=\"control.eventValueId\"\n    MICROBIT_RADIO_EVT_DATAGRAM = 1,  // MICROBIT_RADIO_EVT_DATAGRAM\n    //% blockIdentity=\"control.eventValueId\"\n    MICROBIT_ACCELEROMETER_EVT_DATA_UPDATE = 1,  // MICROBIT_ACCELEROMETER_EVT_DATA_UPDATE\n    //% blockIdentity=\"control.eventValueId\"\n    MICROBIT_PIN_EVT_RISE = 2,  // MICROBIT_PIN_EVT_RISE\n    //% blockIdentity=\"control.eventValueId\"\n    MICROBIT_PIN_EVT_FALL = 3,  // MICROBIT_PIN_EVT_FALL\n    //% blockIdentity=\"control.eventValueId\"\n    MICROBIT_PIN_EVT_PULSE_HI = 4,  // MICROBIT_PIN_EVT_PULSE_HI\n    //% blockIdentity=\"control.eventValueId\"\n    MICROBIT_PIN_EVT_PULSE_LO = 5,  // MICROBIT_PIN_EVT_PULSE_LO\n    //% blockIdentity=\"control.eventValueId\"\n    MES_ALERT_EVT_ALARM1 = 6,  // MES_ALERT_EVT_ALARM1\n    //% blockIdentity=\"control.eventValueId\"\n    MES_ALERT_EVT_ALARM2 = 7,  // MES_ALERT_EVT_ALARM2\n    //% blockIdentity=\"control.eventValueId\"\n    MES_ALERT_EVT_ALARM3 = 8,  // MES_ALERT_EVT_ALARM3\n    //% blockIdentity=\"control.eventValueId\"\n    MES_ALERT_EVT_ALARM4 = 9,  // MES_ALERT_EVT_ALARM4\n    //% blockIdentity=\"control.eventValueId\"\n    MES_ALERT_EVT_ALARM5 = 10,  // MES_ALERT_EVT_ALARM5\n    //% blockIdentity=\"control.eventValueId\"\n    MES_ALERT_EVT_ALARM6 = 11,  // MES_ALERT_EVT_ALARM6\n    //% blockIdentity=\"control.eventValueId\"\n    MES_ALERT_EVT_DISPLAY_TOAST = 1,  // MES_ALERT_EVT_DISPLAY_TOAST\n    //% blockIdentity=\"control.eventValueId\"\n    MES_ALERT_EVT_FIND_MY_PHONE = 5,  // MES_ALERT_EVT_FIND_MY_PHONE\n    //% blockIdentity=\"control.eventValueId\"\n    MES_ALERT_EVT_PLAY_RINGTONE = 4,  // MES_ALERT_EVT_PLAY_RINGTONE\n    //% blockIdentity=\"control.eventValueId\"\n    MES_ALERT_EVT_PLAY_SOUND = 3,  // MES_ALERT_EVT_PLAY_SOUND\n    //% blockIdentity=\"control.eventValueId\"\n    MES_ALERT_EVT_VIBRATE = 2,  // MES_ALERT_EVT_VIBRATE\n    //% blockIdentity=\"control.eventValueId\"\n    MES_CAMERA_EVT_LAUNCH_PHOTO_MODE = 1,  // MES_CAMERA_EVT_LAUNCH_PHOTO_MODE\n    //% blockIdentity=\"control.eventValueId\"\n    MES_CAMERA_EVT_LAUNCH_VIDEO_MODE = 2,  // MES_CAMERA_EVT_LAUNCH_VIDEO_MODE\n    //% blockIdentity=\"control.eventValueId\"\n    MES_CAMERA_EVT_START_VIDEO_CAPTURE = 4,  // MES_CAMERA_EVT_START_VIDEO_CAPTURE\n    //% blockIdentity=\"control.eventValueId\"\n    MES_CAMERA_EVT_STOP_PHOTO_MODE = 6,  // MES_CAMERA_EVT_STOP_PHOTO_MODE\n    //% blockIdentity=\"control.eventValueId\"\n    MES_CAMERA_EVT_STOP_VIDEO_CAPTURE = 5,  // MES_CAMERA_EVT_STOP_VIDEO_CAPTURE\n    //% blockIdentity=\"control.eventValueId\"\n    MES_CAMERA_EVT_STOP_VIDEO_MODE = 7,  // MES_CAMERA_EVT_STOP_VIDEO_MODE\n    //% blockIdentity=\"control.eventValueId\"\n    MES_CAMERA_EVT_TAKE_PHOTO = 3,  // MES_CAMERA_EVT_TAKE_PHOTO\n    //% blockIdentity=\"control.eventValueId\"\n    MES_CAMERA_EVT_TOGGLE_FRONT_REAR = 8,  // MES_CAMERA_EVT_TOGGLE_FRONT_REAR\n    //% blockIdentity=\"control.eventValueId\"\n    MES_DEVICE_DISPLAY_OFF = 5,  // MES_DEVICE_DISPLAY_OFF\n    //% blockIdentity=\"control.eventValueId\"\n    MES_DEVICE_DISPLAY_ON = 6,  // MES_DEVICE_DISPLAY_ON\n    //% blockIdentity=\"control.eventValueId\"\n    MES_DEVICE_GESTURE_DEVICE_SHAKEN = 4,  // MES_DEVICE_GESTURE_DEVICE_SHAKEN\n    //% blockIdentity=\"control.eventValueId\"\n    MES_DEVICE_INCOMING_CALL = 7,  // MES_DEVICE_INCOMING_CALL\n    //% blockIdentity=\"control.eventValueId\"\n    MES_DEVICE_INCOMING_MESSAGE = 8,  // MES_DEVICE_INCOMING_MESSAGE\n    //% blockIdentity=\"control.eventValueId\"\n    MES_DEVICE_ORIENTATION_LANDSCAPE = 1,  // MES_DEVICE_ORIENTATION_LANDSCAPE\n    //% blockIdentity=\"control.eventValueId\"\n    MES_DEVICE_ORIENTATION_PORTRAIT = 2,  // MES_DEVICE_ORIENTATION_PORTRAIT\n    //% blockIdentity=\"control.eventValueId\"\n    MES_DPAD_BUTTON_1_DOWN = 9,  // MES_DPAD_BUTTON_1_DOWN\n    //% blockIdentity=\"control.eventValueId\"\n    MES_DPAD_BUTTON_1_UP = 10,  // MES_DPAD_BUTTON_1_UP\n    //% blockIdentity=\"control.eventValueId\"\n    MES_DPAD_BUTTON_2_DOWN = 11,  // MES_DPAD_BUTTON_2_DOWN\n    //% blockIdentity=\"control.eventValueId\"\n    MES_DPAD_BUTTON_2_UP = 12,  // MES_DPAD_BUTTON_2_UP\n    //% blockIdentity=\"control.eventValueId\"\n    MES_DPAD_BUTTON_3_DOWN = 13,  // MES_DPAD_BUTTON_3_DOWN\n    //% blockIdentity=\"control.eventValueId\"\n    MES_DPAD_BUTTON_3_UP = 14,  // MES_DPAD_BUTTON_3_UP\n    //% blockIdentity=\"control.eventValueId\"\n    MES_DPAD_BUTTON_4_DOWN = 15,  // MES_DPAD_BUTTON_4_DOWN\n    //% blockIdentity=\"control.eventValueId\"\n    MES_DPAD_BUTTON_4_UP = 16,  // MES_DPAD_BUTTON_4_UP\n    //% blockIdentity=\"control.eventValueId\"\n    MES_DPAD_BUTTON_A_DOWN = 1,  // MES_DPAD_BUTTON_A_DOWN\n    //% blockIdentity=\"control.eventValueId\"\n    MES_DPAD_BUTTON_A_UP = 2,  // MES_DPAD_BUTTON_A_UP\n    //% blockIdentity=\"control.eventValueId\"\n    MES_DPAD_BUTTON_B_DOWN = 3,  // MES_DPAD_BUTTON_B_DOWN\n    //% blockIdentity=\"control.eventValueId\"\n    MES_DPAD_BUTTON_B_UP = 4,  // MES_DPAD_BUTTON_B_UP\n    //% blockIdentity=\"control.eventValueId\"\n    MES_DPAD_BUTTON_C_DOWN = 5,  // MES_DPAD_BUTTON_C_DOWN\n    //% blockIdentity=\"control.eventValueId\"\n    MES_DPAD_BUTTON_C_UP = 6,  // MES_DPAD_BUTTON_C_UP\n    //% blockIdentity=\"control.eventValueId\"\n    MES_DPAD_BUTTON_D_DOWN = 7,  // MES_DPAD_BUTTON_D_DOWN\n    //% blockIdentity=\"control.eventValueId\"\n    MES_DPAD_BUTTON_D_UP = 8,  // MES_DPAD_BUTTON_D_UP\n    //% blockIdentity=\"control.eventValueId\"\n    MES_REMOTE_CONTROL_EVT_FORWARD = 6,  // MES_REMOTE_CONTROL_EVT_FORWARD\n    //% blockIdentity=\"control.eventValueId\"\n    MES_REMOTE_CONTROL_EVT_NEXTTRACK = 4,  // MES_REMOTE_CONTROL_EVT_NEXTTRACK\n    //% blockIdentity=\"control.eventValueId\"\n    MES_REMOTE_CONTROL_EVT_PAUSE = 2,  // MES_REMOTE_CONTROL_EVT_PAUSE\n    //% blockIdentity=\"control.eventValueId\"\n    MES_REMOTE_CONTROL_EVT_PLAY = 1,  // MES_REMOTE_CONTROL_EVT_PLAY\n    //% blockIdentity=\"control.eventValueId\"\n    MES_REMOTE_CONTROL_EVT_PREVTRACK = 5,  // MES_REMOTE_CONTROL_EVT_PREVTRACK\n    //% blockIdentity=\"control.eventValueId\"\n    MES_REMOTE_CONTROL_EVT_REWIND = 7,  // MES_REMOTE_CONTROL_EVT_REWIND\n    //% blockIdentity=\"control.eventValueId\"\n    MES_REMOTE_CONTROL_EVT_STOP = 3,  // MES_REMOTE_CONTROL_EVT_STOP\n    //% blockIdentity=\"control.eventValueId\"\n    MES_REMOTE_CONTROL_EVT_VOLUMEDOWN = 9,  // MES_REMOTE_CONTROL_EVT_VOLUMEDOWN\n    //% blockIdentity=\"control.eventValueId\"\n    MES_REMOTE_CONTROL_EVT_VOLUMEUP = 8,  // MES_REMOTE_CONTROL_EVT_VOLUMEUP\n    }\n\n\n    declare const enum EventFlags {\n    //%\n    QueueIfBusy = 16,  // MESSAGE_BUS_LISTENER_QUEUE_IF_BUSY\n    //%\n    DropIfBusy = 32,  // MESSAGE_BUS_LISTENER_DROP_IF_BUSY\n    //%\n    Reentrant = 8,  // MESSAGE_BUS_LISTENER_REENTRANT\n    }\ndeclare namespace control {\n}\n\n\n    declare const enum DisplayMode {\n    //% block=\"black and white\"\n    BlackAndWhite = 0,  // DISPLAY_MODE_BLACK_AND_WHITE\n    //% blockHidden=true\n    BackAndWhite = 0,  // DISPLAY_MODE_BLACK_AND_WHITE\n    //% block=\"greyscale\"\n    Greyscale = 1,  // DISPLAY_MODE_GREYSCALE\n    // TODO DISPLAY_MODE_BLACK_AND_WHITE_LIGHT_SENSE\n    }\ndeclare namespace led {\n}\n\n\n    declare const enum DigitalPin {\n    //% blockIdentity=\"pins._digitalPin\"\n    P0 = 100,  // MICROBIT_ID_IO_P0\n    //% blockIdentity=\"pins._digitalPin\"\n    P1 = 101,  // MICROBIT_ID_IO_P1\n    //% blockIdentity=\"pins._digitalPin\"\n    P2 = 102,  // MICROBIT_ID_IO_P2\n    //% blockIdentity=\"pins._digitalPin\"\n    P3 = 103,  // MICROBIT_ID_IO_P3\n    //% blockIdentity=\"pins._digitalPin\"\n    P4 = 104,  // MICROBIT_ID_IO_P4\n    //% blockIdentity=\"pins._digitalPin\"\n    P5 = 105,  // MICROBIT_ID_IO_P5\n    //% blockIdentity=\"pins._digitalPin\"\n    P6 = 106,  // MICROBIT_ID_IO_P6\n    //% blockIdentity=\"pins._digitalPin\"\n    P7 = 107,  // MICROBIT_ID_IO_P7\n    //% blockIdentity=\"pins._digitalPin\"\n    P8 = 108,  // MICROBIT_ID_IO_P8\n    //% blockIdentity=\"pins._digitalPin\"\n    P9 = 109,  // MICROBIT_ID_IO_P9\n    //% blockIdentity=\"pins._digitalPin\"\n    P10 = 110,  // MICROBIT_ID_IO_P10\n    //% blockIdentity=\"pins._digitalPin\"\n    P11 = 111,  // MICROBIT_ID_IO_P11\n    //% blockIdentity=\"pins._digitalPin\"\n    P12 = 112,  // MICROBIT_ID_IO_P12\n    //% blockIdentity=\"pins._digitalPin\"\n    P13 = 113,  // MICROBIT_ID_IO_P13\n    //% blockIdentity=\"pins._digitalPin\"\n    P14 = 114,  // MICROBIT_ID_IO_P14\n    //% blockIdentity=\"pins._digitalPin\"\n    P15 = 115,  // MICROBIT_ID_IO_P15\n    //% blockIdentity=\"pins._digitalPin\"\n    P16 = 116,  // MICROBIT_ID_IO_P16\n    //% blockIdentity=\"pins._digitalPin\"\n    //% blockHidden=1\n    P19 = 119,  // MICROBIT_ID_IO_P19\n    //% blockIdentity=\"pins._digitalPin\"\n    //% blockHidden=1\n    P20 = 120,  // MICROBIT_ID_IO_P20\n    }\n\n\n    declare const enum AnalogPin {\n    //% blockIdentity=\"pins._analogPin\"\n    P0 = 100,  // MICROBIT_ID_IO_P0\n    //% blockIdentity=\"pins._analogPin\"\n    P1 = 101,  // MICROBIT_ID_IO_P1\n    //% blockIdentity=\"pins._analogPin\"\n    P2 = 102,  // MICROBIT_ID_IO_P2\n    //% blockIdentity=\"pins._analogPin\"\n    P3 = 103,  // MICROBIT_ID_IO_P3\n    //% blockIdentity=\"pins._analogPin\"\n    P4 = 104,  // MICROBIT_ID_IO_P4\n    //% blockIdentity=\"pins._analogPin\"\n    P5 = 105,  // MICROBIT_ID_IO_P5\n    //% blockIdentity=\"pins._analogPin\"\n    P6 = 106,  // MICROBIT_ID_IO_P6\n    //% blockIdentity=\"pins._analogPin\"\n    P7 = 107,  // MICROBIT_ID_IO_P7\n    //% blockIdentity=\"pins._analogPin\"\n    P8 = 108,  // MICROBIT_ID_IO_P8\n    //% blockIdentity=\"pins._analogPin\"\n    P9 = 109,  // MICROBIT_ID_IO_P9\n    //% blockIdentity=\"pins._analogPin\"\n    P10 = 110,  // MICROBIT_ID_IO_P10\n    //% blockIdentity=\"pins._analogPin\"\n    P11 = 111,  // MICROBIT_ID_IO_P11\n    //% blockIdentity=\"pins._analogPin\"\n    P12 = 112,  // MICROBIT_ID_IO_P12\n    //% blockIdentity=\"pins._analogPin\"\n    P13 = 113,  // MICROBIT_ID_IO_P13\n    //% blockIdentity=\"pins._analogPin\"\n    P14 = 114,  // MICROBIT_ID_IO_P14\n    //% blockIdentity=\"pins._analogPin\"\n    P15 = 115,  // MICROBIT_ID_IO_P15\n    //% blockIdentity=\"pins._analogPin\"\n    P16 = 116,  // MICROBIT_ID_IO_P16\n    //% blockIdentity=\"pins._analogPin\"\n    //% blockHidden=1\n    P19 = 119,  // MICROBIT_ID_IO_P19\n    //% blockIdentity=\"pins._analogPin\"\n    //% blockHidden=1\n    P20 = 120,  // MICROBIT_ID_IO_P20\n    }\n\n\n    declare const enum PulseValue {\n    //% block=high\n    High = 4,  // MICROBIT_PIN_EVT_PULSE_HI\n    //% block=low\n    Low = 5,  // MICROBIT_PIN_EVT_PULSE_LO\n    }\n\n\n    declare const enum PinPullMode {\n    //% block=\"down\"\n    PullDown = 0,\n    //% block=\"up\"\n    PullUp = 1,\n    //% block=\"none\"\n    PullNone = 2,\n    }\n\n\n    declare const enum PinEventType {\n    //% block=\"edge\"\n    Edge = 2,  // MICROBIT_PIN_EVENT_ON_EDGE\n    //% block=\"pulse\"\n    Pulse = 3,  // MICROBIT_PIN_EVENT_ON_PULSE\n    //% block=\"touch\"\n    Touch = 4,  // MICROBIT_PIN_EVENT_ON_TOUCH\n    //% block=\"none\"\n    None = 0,  // MICROBIT_PIN_EVENT_NONE\n    }\n\n\n    declare const enum SerialPin {\n    P0 = 100,  // MICROBIT_ID_IO_P0\n    P1 = 101,  // MICROBIT_ID_IO_P1\n    P2 = 102,  // MICROBIT_ID_IO_P2\n    P8 = 108,  // MICROBIT_ID_IO_P8\n    P12 = 112,  // MICROBIT_ID_IO_P12\n    P13 = 113,  // MICROBIT_ID_IO_P13\n    P14 = 114,  // MICROBIT_ID_IO_P14\n    P15 = 115,  // MICROBIT_ID_IO_P15\n    P16 = 116,  // MICROBIT_ID_IO_P16\n    USB_TX = 1001,\n    USB_RX = 1002,\n    }\n\n\n    declare const enum BaudRate {\n    //% block=115200\n    BaudRate115200 = 115200,\n    //% block=57600\n    BaudRate57600 = 57600,\n    //% block=38400\n    BaudRate38400 = 38400,\n    //% block=31250\n    BaudRate31250 = 31250,\n    //% block=28800\n    BaudRate28800 = 28800,\n    //% block=19200\n    BaudRate19200 = 19200,\n    //% block=14400\n    BaudRate14400 = 14400,\n    //% block=9600\n    BaudRate9600 = 9600,\n    //% block=4800\n    BaudRate4800 = 4800,\n    //% block=2400\n    BaudRate2400 = 2400,\n    //% block=1200\n    BaudRate1200 = 1200,\n    }\ndeclare namespace serial {\n}\n\n\n    /**\n     * An action on a touch button\n     */\n\n    declare const enum TouchButtonEvent {\n    //% block=pressed\n    Pressed = 3,  // MICROBIT_BUTTON_EVT_CLICK\n    //% block=touched\n    Touched = 1,  // MICROBIT_BUTTON_EVT_DOWN\n    //% block=released\n    Released = 2,  // MICROBIT_BUTTON_EVT_UP\n    //% block=\"long pressed\"\n    LongPressed = 4,  // MICROBIT_BUTTON_EVT_LONG_CLICK\n    }\n\n\n    declare const enum TouchTargetMode {\n    //% block=\"capacitive\"\n    Capacitive = 1,\n    //% block=\"resistive\"\n    Resistive = 0,\n    }\n\n\n    declare const enum TouchTarget {\n    //% block=\"P0\"\n    P0 = 100,  // MICROBIT_ID_IO_P0\n    //% block=\"P1\"\n    P1 = 101,  // MICROBIT_ID_IO_P1\n    //% block=\"P2\"\n    P2 = 102,  // MICROBIT_ID_IO_P2\n    //% block=\"logo\"\n    LOGO = 121,  // MICROBIT_ID_LOGO\n    }\n\n// Auto-generated. Do not edit. Really.\n","fixed.ts":"interface Fx8 {\n    _dummyFx8: string;\n}\n\nfunction Fx8(v: number) {\n    return ((v * 256) | 0) as any as Fx8\n}\n\nnamespace Fx {\n    export const zeroFx8 = 0 as any as Fx8\n    export const oneHalfFx8 = 128 as any as Fx8\n    export const oneFx8 = 256 as any as Fx8\n    export const twoFx8 = 512 as any as Fx8\n\n    export function neg(a: Fx8) {\n        return (-(a as any as number)) as any as Fx8\n    }\n    export function toIntShifted(a: Fx8, n: number) {\n        return (a as any as number) >> (n + 8)\n    }\n    export function add(a: Fx8, b: Fx8) {\n        return ((a as any as number) + (b as any as number)) as any as Fx8\n    }\n    export function iadd(a: number, b: Fx8) {\n        return ((a << 8) + (b as any as number)) as any as Fx8\n    }\n    export function sub(a: Fx8, b: Fx8) {\n        return ((a as any as number) - (b as any as number)) as any as Fx8\n    }\n    export function mul(a: Fx8, b: Fx8) {\n        return (Math.imul((a as any as number), (b as any as number)) >> 8) as any as Fx8\n    }\n    export function imul(a: Fx8, b: number) {\n        return Math.imul((a as any as number), (b as any as number)) as any as Fx8\n    }\n    export function div(a: Fx8, b: Fx8) {\n        return Math.idiv((a as any as number) << 8, b as any as number) as any as Fx8\n    }\n    export function idiv(a: Fx8, b: number) {\n        return Math.idiv((a as any as number), b) as any as Fx8\n    }\n    export function compare(a: Fx8, b: Fx8) {\n        return (a as any as number) - (b as any as number)\n    }\n    export function abs(a: Fx8) {\n        if ((a as any as number) < 0)\n            return (-(a as any as number)) as any as Fx8\n        else\n            return a\n    }\n    export function min(a: Fx8, b: Fx8) {\n        if (a < b)\n            return a\n        else\n            return b\n    }\n    export function max(a: Fx8, b: Fx8) {\n        if (a > b)\n            return a\n        else\n            return b\n    }\n    export function floor(v: Fx8): Fx8 {\n        return ((v as any as number) & ~0xff) as any as Fx8;\n    }\n    export function ceil(v: Fx8): Fx8 {\n        return (v as any as number) & 0xff ? Fx.floor(Fx.add(v, Fx.oneFx8)) : v;\n    }\n    export function leftShift(a: Fx8, n: number) {\n        return (a as any as number << n) as any as Fx8\n    }\n    export function rightShift(a: Fx8, n: number) {\n        return (a as any as number >> n) as any as Fx8\n    }\n    export function toInt(v: Fx8) {\n        return ((v as any as number) + 128) >> 8\n    }\n    export function toFloat(v: Fx8) {\n        return (v as any as number) / 256\n    }\n}","game.ts":"enum Direction {\n    //% block=right\n    Right,\n    //% block=left\n    Left\n}\n\nenum LedSpriteProperty {\n    //% block=x\n    X,\n    //% block=y\n    Y,\n    //% block=direction\n    Direction,\n    //% block=brightness\n    Brightness,\n    //% block=blink\n    Blink\n}\n\n/**\n * A single-LED sprite game engine\n */\n//% color=#007A4B weight=32 icon=\"\\uf11b\"\n//% advanced=true\nnamespace game {\n    let _score: number = 0;\n    let _life: number = 3;\n    let _startTime: number = 0;\n    let _endTime: number = 0;\n    let _isGameOver: boolean = false;\n    let _countdownPause: number = 0;\n    let _level: number = 1;\n    let _gameId: number = 0;\n    let _img: Image;\n    let _sprites: LedSprite[];\n    let _paused: boolean = false;\n    let _backgroundAnimation = false; // indicates if an auxiliary animation (and fiber) is already running\n\n    /**\n     * Creates a new LED sprite pointing to the right.\n     * @param x sprite horizontal coordinate, eg: 2\n     * @param y sprite vertical coordinate, eg: 2\n     */\n    //% weight=60 blockGap=8 help=game/create-sprite\n    //% blockId=game_create_sprite block=\"create sprite at|x: %x|y: %y\"\n    //% parts=\"ledmatrix\"\n    export function createSprite(x: number, y: number): LedSprite {\n        init();\n        let p = new LedSprite(x, y);\n        return p;\n    }\n\n    /**\n     * Gets the current score\n     */\n    //% weight=9 help=game/score\n    //% blockId=game_score block=\"score\" blockGap=8\n    export function score(): number {\n        return _score;\n    }\n\n    /**\n     * Adds points to the current score and shows an animation\n     * @param points amount of points to change, eg: 1\n     */\n    //% weight=10 help=game/add-score\n    //% blockId=game_add_score block=\"change score by|%points\" blockGap=8\n    //% parts=\"ledmatrix\"\n    export function addScore(points: number): void {\n        setScore(_score + points);\n        if (!_paused && !_backgroundAnimation) {\n            _backgroundAnimation = true;\n            control.inBackground(() => {\n                led.stopAnimation();\n                basic.showAnimation(`0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 1 1 1 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 1 1 1 0 0 0 1 0 0 0 0 0\n    0 0 0 0 0 0 0 1 0 0 0 1 1 1 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 1 1 1 0 0 0 1 0 0 0 0 0 0 0 0 0 0\n    0 0 1 0 0 0 1 1 1 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 1 1 1 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0\n    0 0 0 0 0 0 0 1 0 0 0 1 1 1 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 1 1 1 0 0 0 1 0 0 0 0 0 0 0 0 0 0\n    0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 1 1 1 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 1 1 1 0 0 0 1 0 0 0 0 0`, 20);\n                _backgroundAnimation = false;\n            });\n        }\n    }\n\n    /**\n     * Shows an animation, then starts a game countdown timer, which causes Game Over when it reaches 0\n     * @param ms countdown duration in milliseconds, eg: 10000\n     */\n    //% weight=9 help=game/start-countdown\n    //% blockId=game_start_countdown block=\"start countdown|(ms) %duration\" blockGap=8\n    //% parts=\"ledmatrix\"\n    export function startCountdown(ms: number): void {\n        if (checkStart()) {\n            basic.showAnimation(`1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0\n0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0\n1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0\n0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0\n1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0`, 400);\n            _countdownPause = Math.max(500, ms);\n            _startTime = -1;\n            _endTime = input.runningTime() + _countdownPause;\n            _paused = false;\n            control.inBackground(() => {\n                basic.pause(_countdownPause);\n                gameOver();\n            });\n        }\n    }\n\n    /**\n     * Displays a game over animation and the score.\n     */\n    //% weight=8 help=game/game-over\n    //% blockId=game_game_over block=\"game over\"\n    //% parts=\"ledmatrix\"\n    export function gameOver(): void {\n        if (!_isGameOver) {\n            _isGameOver = true;\n            unplugEvents();\n            led.stopAnimation();\n            led.setBrightness(255);\n            while (true) {\n                for (let i = 0; i < 8; i++) {\n                    basic.clearScreen();\n                    basic.pause(100);\n                    basic.showLeds(`1 1 1 1 1\n1 1 1 1 1\n1 1 1 1 1\n1 1 1 1 1\n1 1 1 1 1`, 300);\n                }\n                basic.showAnimation(`1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 1 1 1 0 0 1 1 0 0 0 1 0 0 0 0 0 0 0 0 0\n1 1 1 1 1 1 1 1 1 1 1 1 1 0 1 1 1 0 0 1 1 0 0 0 1 0 0 0 0 1 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0\n1 1 0 1 1 1 0 0 0 1 1 0 0 0 1 1 0 0 0 1 1 0 0 0 1 1 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0\n1 1 1 1 1 1 1 1 1 1 1 0 1 1 1 1 0 0 1 1 1 0 0 0 1 1 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0\n1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 1 1 1 1 0 0 1 1 1 0 0 0 1 1 0 0 0 0 1 0 0 0 0 0`, 100);\n                for (let j = 0; j < 3; j++) {\n                    basic.showString(\" GAMEOVER \", 100);\n                    showScore();\n                }\n            }\n        } else {\n            // already in game over mode in another fiber\n            while (true) {\n                basic.pause(10000);\n            }\n        }\n    }\n\n    /**\n     * Sets the current score value\n     * @param value new score value.\n     */\n    //% blockId=game_set_score block=\"set score %points\" blockGap=8\n    //% weight=10 help=game/set-score\n    export function setScore(value: number): void {\n        _score = Math.max(0, value);\n    }\n\n    /**\n     * Gets the current life\n     */\n    //% weight=10\n    export function life(): number {\n        return _life;\n    }\n\n    /**\n     * Sets the current life value\n     * @param value current life value\n     */\n    //% weight=10 help=game/set-life\n    //% blockId=game_set_life block=\"set life %value\" blockGap=8\n    export function setLife(value: number): void {\n        _life = Math.max(0, value);\n        if (_life <= 0) {\n            gameOver();\n        }\n    }\n\n    /**\n     * Add life points to the current life amount\n     * @param lives amount of lives to add\n     */\n    //% weight=10 help=game/add-life\n    //% blockId=game_add_life block=\"add life %lives\" blockGap=8\n    export function addLife(lives: number): void {\n        setLife(_life + lives);\n    }\n\n    /**\n     * Gets the remaining time (since `start countdown`) or current time (since the device started or `start stopwatch`) in milliseconds.\n     */\n    //% weight=10\n    export function currentTime(): number {\n        if (_endTime > 0) {\n            return Math.max(0, _endTime - input.runningTime());\n        } else {\n            return input.runningTime() - _startTime;\n        }\n    }\n\n    /**\n     * Remove some life\n     * @param life amount of life to remove\n     */\n    //% weight=10 help=game/remove-life\n    //% parts=\"ledmatrix\"\n    //% blockId=game_remove_life block=\"remove life %life\" blockGap=8\n    export function removeLife(life: number): void {\n        setLife(_life - life);\n        if (!_paused && !_backgroundAnimation) {\n            _backgroundAnimation = true;\n            control.inBackground(() => {\n                led.stopAnimation();\n                basic.showAnimation(`1 0 0 0 1 0 0 0 0 0 1 0 0 0 1 0 0 0 0 0\n0 1 0 1 0 0 0 0 0 0 0 1 0 1 0 0 0 0 0 0\n0 0 1 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0\n0 1 0 1 0 0 0 0 0 0 0 1 0 1 0 0 0 0 0 0\n1 0 0 0 1 0 0 0 0 0 1 0 0 0 1 0 0 0 0 0`, 40);\n                _backgroundAnimation = false;\n            });\n        }\n    }\n\n    /**\n     * Increments the level and display a message.\n     */\n    //% weight=10\n    //% parts=\"ledmatrix\"\n    export function levelUp(): void {\n        _level = _level + 1;\n        basic.showString(\"LEVEL:\", 150);\n        basic.showNumber(_level, 150);\n    }\n\n    /**\n     * Gets the current level\n     */\n    //% weight=10\n    export function level(): number {\n        return _level;\n    }\n\n    /**\n     * Starts a stopwatch timer. `current time` will return the elapsed time.\n     */\n    //% weight=10\n    export function startStopwatch(): void {\n        _startTime = input.runningTime();\n        _endTime = -1;\n    }\n\n    /**\n     * Indicates if the game is still running. Returns `false` if the game is over or paused.\n     */\n    //% weight=5 help=game/is-running\n    //% blockId=game_isrunning block=\"is running\" blockGap=8\n    export function isRunning(): boolean {\n        return !_isGameOver && !_paused && !!_img;\n    }\n\n    /**\n     * Displays the score on the screen.\n     */\n    //%  weight=60\n    //% parts=\"ledmatrix\"\n    export function showScore(): void {\n        basic.showString(\" SCORE \", 100);\n        basic.showNumber(_score, 150);\n        basic.showString(\" \", 150);\n    }\n\n    /**\n     * Indicates if the game is over and displaying the game over sequence.\n     */\n    //% weight=7 help=game/is-game-over\n    //% blockId=game_isgameover block=\"is game over\" blockGap=8\n    export function isGameOver(): boolean {\n        return _isGameOver;\n    }\n\n    /**\n     * Indicates if the game rendering is paused to allow other animations\n     */\n    //% weight=6 help=game/is-paused\n    //% blockId=game_ispaused block=\"is paused\" blockGap=8\n    export function isPaused(): boolean {\n        return _paused;\n    }\n\n    /**\n     * Pauses the game rendering engine to allow other animations\n     */\n    //% blockId=game_pause block=\"pause\"\n    //% advanced=true blockGap=8 help=game/pause\n    export function pause(): void {\n        plot()\n        _paused = true;\n    }\n\n\n    /**\n     * Resumes the game rendering engine\n     */\n    //% blockId=game_resume block=\"resume\"\n    //% advanced=true blockGap=8 help=game/resume\n    export function resume(): void {\n        _paused = false;\n        plot();\n    }\n\n    /**\n     * returns false if game can't start\n     */\n    function checkStart(): boolean {\n        if (_countdownPause > 0 || _startTime > 0) {\n            return false;\n        } else {\n            return true;\n        }\n    }\n\n    function unplugEvents(): void {\n        input.onButtonPressed(Button.A, () => { });\n        input.onButtonPressed(Button.B, () => { });\n        input.onButtonPressed(Button.AB, () => {\n            control.reset();\n        });\n    }\n\n    /**\n     * A game sprite rendered as a single LED\n     */\n    //%\n    export class LedSprite {\n        private _x: number;\n        private _y: number;\n        private _dir: number;\n        private _brightness: number;\n        private _blink: number;\n        private _enabled: boolean;\n\n        constructor(x: number, y: number) {\n            this._x = Math.clamp(0, 4, x);\n            this._y = Math.clamp(0, 4, y);\n            this._dir = 90;\n            this._brightness = 255;\n            this._enabled = true;\n            init();\n            _sprites.push(this);\n            plot();\n        }\n\n        /**\n         * Move a certain number of LEDs in the current direction\n         * @param this the sprite to move\n         * @param leds number of leds to move, eg: 1, -1\n         */\n        //% weight=50 help=game/move\n        //% blockId=game_move_sprite block=\"%sprite|move by %leds\" blockGap=8\n        //% parts=\"ledmatrix\"\n        public move(leds: number): void {\n            if (this._dir == 0) {\n                this._y = this._y - leds;\n            } else if (this._dir == 45) {\n                this._x = this._x + leds;\n                this._y = this._y - leds;\n            } else if (this._dir == 90) {\n                this._x = this._x + leds;\n            } else if (this._dir == 135) {\n                this._x = this._x + leds;\n                this._y = this._y + leds;\n            } else if (this._dir == 180) {\n                this._y = this._y + leds;\n            } else if (this._dir == -45) {\n                this._x = this._x - leds;\n                this._y = this._y - leds;\n            } else if (this._dir == -90) {\n                this._x = this._x - leds;\n            } else {\n                this._x = this._x - leds;\n                this._y = this._y + leds;\n            }\n            this._x = Math.clamp(0, 4, this._x);\n            this._y = Math.clamp(0, 4, this._y);\n            plot();\n        }\n\n        /**\n         * Go to this position on the screen\n         * @param this TODO\n         * @param x TODO\n         * @param y TODO\n         */\n        //% parts=\"ledmatrix\"\n        public goTo(x: number, y: number): void {\n            this._x = x;\n            this._y = y;\n            this._x = Math.clamp(0, 4, this._x);\n            this._y = Math.clamp(0, 4, this._y);\n            plot();\n        }\n\n        /**\n         * If touching the edge of the stage and facing towards it, then turn away.\n         * @param this the sprite to check for bounce\n         */\n        //% weight=18 help=game/if-on-edge-bounce\n        //% blockId=game_sprite_bounce block=\"%sprite|if on edge, bounce\"\n        //% parts=\"ledmatrix\"\n        public ifOnEdgeBounce(): void {\n            if (this._dir == 0 && this._y == 0) {\n                this._dir = 180;\n            } else if (this._dir == 45 && (this._x == 4 || this._y == 0)) {\n                if (this._x == 0 && this._y == 0) {\n                    this._dir = -135;\n                } else if (this._y == 0) {\n                    this._dir = 135;\n                } else {\n                    this._dir = -45;\n                }\n            } else if (this._dir == 90 && this._x == 4) {\n                this._dir = -90;\n            } else if (this._dir == 135 && (this._x == 4 || this._y == 4)) {\n                if (this.x() == 4 && this.y() == 4) {\n                    this._dir = -45;\n                } else if (this._y == 4) {\n                    this._dir = 45;\n                } else {\n                    this._dir = -135;\n                }\n            } else if (this._dir == 180 && this._y == 4) {\n                this._dir = 0;\n            } else if (this._dir == -45 && (this._x == 0 || this._y == 0)) {\n                if (this.x() == 0 && this.y() == 0) {\n                    this._dir = 135;\n                } else if (this._y == 0) {\n                    this._dir = -135;\n                } else {\n                    this._dir = 45;\n                }\n            } else if (this._dir == -90 && this._x == 0) {\n                this._dir = 90;\n            } else if (this._dir == -135 && (this._x == 0 || this._y == 4)) {\n                if (this._x == 0 && this._y == 4) {\n                    this._dir = 45;\n                } else if (this._y == 4) {\n                    this._dir = -45;\n                } else {\n                    this._dir = 135;\n                }\n            }\n            plot();\n        }\n\n        /**\n         * Turn the sprite\n         * @param this the sprite to trun\n         * @param direction left or right\n         * @param degrees angle in degrees to turn, eg: 45, 90, 180, 135\n         */\n        //% weight=49 help=game/turn\n        //% blockId=game_turn_sprite block=\"%sprite|turn %direction|by (°) %degrees\"\n        public turn(direction: Direction, degrees: number) {\n            if (direction == Direction.Right)\n                this.setDirection(this._dir + degrees);\n            else\n                this.setDirection(this._dir - degrees);\n        }\n\n        /**\n         * Turn to the right (clockwise)\n         * @param this the sprite to turn\n         * @param degrees TODO\n         */\n        public turnRight(degrees: number): void {\n            this.turn(Direction.Right, degrees);\n        }\n\n        /**\n         * Turn to the left (counter-clockwise)\n         * @param this the sprite to turn\n         * @param degrees TODO\n         */\n        public turnLeft(degrees: number): void {\n            this.turn(Direction.Left, degrees);\n        }\n\n        /**\n         * Sets a property of the sprite\n         * @param property the name of the property to change\n         * @param the updated value\n         */\n        //% weight=29 help=game/set\n        //% blockId=game_sprite_set_property block=\"%sprite|set %property|to %value\" blockGap=8\n        public set(property: LedSpriteProperty, value: number) {\n            switch (property) {\n                case LedSpriteProperty.X: this.setX(value); break;\n                case LedSpriteProperty.Y: this.setY(value); break;\n                case LedSpriteProperty.Direction: this.setDirection(value); break;\n                case LedSpriteProperty.Brightness: this.setBrightness(value); break;\n                case LedSpriteProperty.Blink: this.setBlink(value); break;\n            }\n        }\n\n        /**\n         * Changes a property of the sprite\n         * @param property the name of the property to change\n         * @param value amount of change, eg: 1\n         */\n        //% weight=30 help=game/change\n        //% blockId=game_sprite_change_xy block=\"%sprite|change %property|by %value\" blockGap=8\n        public change(property: LedSpriteProperty, value: number) {\n            switch (property) {\n                case LedSpriteProperty.X: this.changeXBy(value); break;\n                case LedSpriteProperty.Y: this.changeYBy(value); break;\n                case LedSpriteProperty.Direction: this.changeDirectionBy(value); break;\n                case LedSpriteProperty.Brightness: this.changeBrightnessBy(value); break;\n                case LedSpriteProperty.Blink: this.changeBlinkBy(value); break;\n            }\n        }\n\n        /**\n         * Gets a property of the sprite\n         * @param property the name of the property to change\n         */\n        //% weight=28 help=game/get\n        //% blockId=game_sprite_property block=\"%sprite|%property\"\n        public get(property: LedSpriteProperty) {\n            switch (property) {\n                case LedSpriteProperty.X: return this.x();\n                case LedSpriteProperty.Y: return this.y();\n                case LedSpriteProperty.Direction: return this.direction()\n                case LedSpriteProperty.Brightness: return this.brightness();\n                case LedSpriteProperty.Blink: return this.blink();\n                default: return 0;\n            }\n        }\n\n        /**\n         * Set the direction of the current sprite, rounded to the nearest multiple of 45\n         * @param this the sprite to set direction for\n         * @param degrees new direction in degrees\n         */\n        //% parts=\"ledmatrix\"\n        public setDirection(degrees: number): void {\n            this._dir = (Math.floor(degrees / 45) % 8) * 45;\n            if (this._dir <= -180) {\n                this._dir = this._dir + 360;\n            } else if (this._dir > 180) {\n                this._dir = this._dir - 360;\n            }\n            plot();\n        }\n\n        /**\n         * Reports the ``x`` position of a sprite on the LED screen\n         * @param this TODO\n         */\n        public x(): number {\n            return this._x;\n        }\n\n        /**\n         * Reports the ``y`` position of a sprite on the LED screen\n         * @param this TODO\n         */\n        public y(): number {\n            return this._y;\n        }\n\n        /**\n         * Reports the current direction of a sprite\n         * @param this TODO\n         */\n        public direction(): number {\n            return this._dir;\n        }\n\n        /**\n         * Set the ``x`` position of a sprite\n         * @param this TODO\n         * @param x TODO\n         */\n        public setX(x: number): void {\n            this.goTo(x, this._y);\n        }\n\n        /**\n         * Set the ``y`` position of a sprite\n         * @param this TODO\n         * @param y TODO\n         */\n        public setY(y: number): void {\n            this.goTo(this._x, y);\n        }\n\n        /**\n         * Changes the ``y`` position by the given amount\n         * @param this TODO\n         * @param y TODO\n         */\n        public changeYBy(y: number): void {\n            this.goTo(this._x, this._y + y);\n        }\n\n        /**\n         * Changes the ``x`` position by the given amount\n         * @param this TODO\n         * @param x TODO\n         */\n        public changeXBy(x: number): void {\n            this.goTo(this._x + x, this._y);\n        }\n\n        /**\n         * Reports true if sprite has the same position as specified sprite\n         * @param this the sprite to check overlap or touch\n         * @param other the other sprite to check overlap or touch\n         */\n        //% weight=20 help=game/is-touching\n        //% blockId=game_sprite_touching_sprite block=\"is %sprite|touching %other\" blockGap=8\n        public isTouching(other: LedSprite): boolean {\n            return this._enabled && other._enabled && this._x == other._x && this._y == other._y;\n        }\n\n        /**\n         * Reports true if sprite is touching an edge\n         * @param this the sprite to check for an edge contact\n         */\n        //% weight=19 help=game/is-touching-edge\n        //% blockId=game_sprite_touching_edge block=\"is %sprite|touching edge\" blockGap=8\n        public isTouchingEdge(): boolean {\n            return this._enabled && (this._x == 0 || this._x == 4 || this._y == 0 || this._y == 4);\n        }\n\n        /**\n         * Turns on the sprite (on by default)\n         * @param this the sprite\n         */\n        public on(): void {\n            this.setBrightness(255);\n        }\n\n        /**\n         * Turns off the sprite (on by default)\n         * @param this the sprite\n         */\n        public off(): void {\n            this.setBrightness(0);\n        }\n\n        /**\n         * Set the ``brightness`` of a sprite\n         * @param this the sprite\n         * @param brightness the brightness from 0 (off) to 255 (on), eg: 255.\n         */\n        //% parts=\"ledmatrix\"\n        public setBrightness(brightness: number): void {\n            this._brightness = Math.clamp(0, 255, brightness);\n            plot();\n        }\n\n        /**\n         * Reports the ``brightness` of a sprite on the LED screen\n         * @param this the sprite\n         */\n        //% parts=\"ledmatrix\"\n        public brightness(): number {\n            let r: number;\n            return this._brightness;\n        }\n\n        /**\n         * Changes the ``y`` position by the given amount\n         * @param this the sprite\n         * @param value the value to change brightness\n         */\n        public changeBrightnessBy(value: number): void {\n            this.setBrightness(this._brightness + value);\n        }\n\n        /**\n         * Changes the ``direction`` position by the given amount by turning right\n         * @param this TODO\n         * @param angle TODO\n         */\n        public changeDirectionBy(angle: number): void {\n            this.turnRight(angle);\n        }\n\n        /**\n         * Deletes the sprite from the game engine. The sprite will no longer appear on the screen or interact with other sprites.\n         * @param this sprite to delete\n         */\n        //% weight=59 blockGap=8 help=game/delete\n        //% blockId=\"game_delete_sprite\" block=\"delete %this(sprite)\"\n        public delete(): void {\n            this._enabled = false;\n            if (_sprites.removeElement(this))\n                plot();\n        }\n\n        /**\n         * Reports whether the sprite has been deleted from the game engine.\n         */\n        //% weight=58 help=game/is-deleted\n        //% blockId=\"game_sprite_is_deleted\" block=\"is %sprite|deleted\"\n        public isDeleted(): boolean {\n            return !this._enabled;\n        }\n\n        /**\n         * Sets the blink duration interval in millisecond.\n         * @param sprite TODO\n         * @param ms TODO\n         */\n        public setBlink(ms: number): void {\n            this._blink = Math.clamp(0, 10000, ms);\n        }\n\n        /**\n         * Changes the ``blink`` duration by the given amount of millisecons\n         * @param this TODO\n         * @param ms TODO\n         */\n        public changeBlinkBy(ms: number): void {\n            this.setBlink(this._blink + ms);\n        }\n\n        /**\n         * Reports the ``blink`` duration of a sprite\n         * @param this TODO\n         */\n        public blink(): number {\n            return this._blink;\n        }\n\n        //% weight=-1\n        //% parts=\"ledmatrix\"\n        public _plot(now: number) {\n            let ps = this\n            if (ps._brightness > 0) {\n                let r = 0;\n                if (ps._blink > 0) {\n                    r = Math.floor(now / ps._blink) % 2;\n                }\n                if (r == 0) {\n                    _img.setPixelBrightness(ps._x, ps._y, _img.pixelBrightness(ps._x, ps._y) + ps._brightness);\n                }\n            }\n        }\n    }\n\n    function init(): void {\n        if (_img) return;\n        const img = images.createImage(\n`0 0 0 0 0\n0 0 0 0 0\n0 0 0 0 0\n0 0 0 0 0\n0 0 0 0 0`);\n        _sprites = (<LedSprite[]>[]);\n        basic.forever(() => {\n            basic.pause(30);\n            plot();\n            if (game.isGameOver()) {\n                basic.pause(600);\n            }\n        });\n        _img = img;\n    }\n\n    /**\n     * Plots the current sprites on the screen\n     */\n    //% parts=\"ledmatrix\"\n    function plot(): void {\n        if (game.isGameOver() || game.isPaused() || !_img || _backgroundAnimation) {\n            return;\n        }\n        // ensure greyscale mode\n        const dm = led.displayMode();\n        if (dm != DisplayMode.Greyscale)\n            led.setDisplayMode(DisplayMode.Greyscale);\n        // render sprites\n        const now = input.runningTime();\n        _img.clear();\n        for (let i = 0; i < _sprites.length; i++) {\n            _sprites[i]._plot(now);\n        }\n        _img.plotImage(0);\n    }\n\n    /**\n     * Gets an invalid sprite; used to initialize locals.\n     */\n    //% weight=0\n    export function invalidSprite(): LedSprite {\n        return null;\n    }\n\n}\n\n","gc.cpp":"#include \"pxtbase.h\"\n\n#ifndef GC_BLOCK_SIZE\n#define GC_BLOCK_SIZE (1024 * 16)\n#endif\n\n#ifndef GC_MAX_ALLOC_SIZE\n#define GC_MAX_ALLOC_SIZE (GC_BLOCK_SIZE - 16)\n#endif\n\n#ifndef GC_ALLOC_BLOCK\n#define GC_ALLOC_BLOCK xmalloc\n#endif\n\n#ifdef PXT64\n#define HIGH_SHIFT 48\n#define BYTES_TO_WORDS(x) ((x) >> 3)\n#define WORDS_TO_BYTES(x) ((x) << 3)\n#define ALIGN_TO_WORD(x) (((x) + 7) & (~7ULL))\n#define VAR_BLOCK_WORDS(vt) ((uint32_t)(uint64_t)(vt) >> 2)\n#else\n#define HIGH_SHIFT 28\n#define BYTES_TO_WORDS(x) ((x) >> 2)\n#define WORDS_TO_BYTES(x) ((x) << 2)\n#define ALIGN_TO_WORD(x) (((x) + 3) & (~3U))\n#define VAR_BLOCK_WORDS(vt) (((uint32_t)(vt) << 4) >> (4 + 2))\n#endif\n\n#define FREE_MASK (1ULL << (HIGH_SHIFT + 3))\n#define ARRAY_MASK (1ULL << (HIGH_SHIFT + 2))\n#define PERMA_MASK (1ULL << (HIGH_SHIFT + 1))\n#define MARKED_MASK 0x1\n#define ANY_MARKED_MASK 0x3\n\n// the bit operations should be faster than loading large constants\n#define IS_FREE(vt) ((uintptr_t)(vt) >> (HIGH_SHIFT + 3))\n#define IS_ARRAY(vt) (((uintptr_t)(vt) >> (HIGH_SHIFT + 2)) & 1)\n#define IS_PERMA(vt) (((uintptr_t)(vt) >> (HIGH_SHIFT + 1)) & 1)\n#define IS_VAR_BLOCK(vt) ((uintptr_t)(vt) >> (HIGH_SHIFT + 2))\n#define IS_MARKED(vt) ((uintptr_t)(vt)&MARKED_MASK)\n#define IS_LIVE(vt) (IS_MARKED(vt) || (((uintptr_t)(vt) >> (HIGH_SHIFT)) == 0x6))\n\n//#define PXT_GC_DEBUG 1\n#ifndef PXT_GC_CHECKS\n#define PXT_GC_CHECKS 1\n#endif\n//#define PXT_GC_STRESS 1\n\n//#define PXT_GC_CHECKS 1\n\n#define MARK(v)                                                                                    \\\n    do {                                                                                           \\\n        GC_CHECK(inGCArea(v), 42);                                                                 \\\n        *(uintptr_t *)(v) |= MARKED_MASK;                                                          \\\n    } while (0)\n\n#ifdef PXT_GC_DEBUG\n#define LOG DMESG\n#define VLOG DMESG\n#define VVLOG DMESG\n#else\n#define LOG NOLOG\n#define VLOG NOLOG\n#define VVLOG NOLOG\n#endif\n\n#ifdef PXT_GC_CHECKS\n#define GC_CHECK(cond, code)                                                                       \\\n    if (!(cond))                                                                                   \\\n    oops(code)\n#else\n#define GC_CHECK(cond, code) ((void)0)\n#endif\n\nnamespace pxt {\n\n// keep in sync with base/control.ts, function gcStats()\nstruct GCStats {\n    uint32_t numGC;\n    uint32_t numBlocks;\n    uint32_t totalBytes;\n    uint32_t lastFreeBytes;\n    uint32_t lastMaxBlockBytes;\n    uint32_t minFreeBytes;\n};\n\nstatic GCStats gcStats;\n\n//% expose\nBuffer getGCStats() {\n    return mkBuffer((uint8_t *)&gcStats, sizeof(gcStats));\n}\n\n//%\nvoid popThreadContext(ThreadContext *ctx);\n//%\nThreadContext *pushThreadContext(void *sp, void *endSP);\n\nunsigned RefRecord_gcsize(RefRecord *r) {\n    VTable *tbl = getVTable(r);\n    return BYTES_TO_WORDS(tbl->numbytes);\n}\n\n#ifdef PXT_GC_THREAD_LIST\nThreadContext *threadContexts;\n#endif\n\n#define IN_GC_ALLOC 1\n#define IN_GC_COLLECT 2\n#define IN_GC_FREEZE 4\n#define IN_GC_PREALLOC 8\n\n#ifndef PXT_VM\nstatic TValue *tempRoot;\nstatic uint8_t tempRootLen;\n#endif\n\nuint8_t inGC;\n\nvoid popThreadContext(ThreadContext *ctx) {\n#ifndef PXT_VM\n    VLOG(\"pop: %p\", ctx);\n\n    if (!ctx)\n        return;\n\n    auto n = ctx->stack.next;\n    if (n) {\n        VLOG(\"seg %p\", n);\n        ctx->stack.top = n->top;\n        ctx->stack.bottom = n->bottom;\n        ctx->stack.next = n->next;\n        app_free(n);\n    } else {\n#ifdef PXT_GC_THREAD_LIST\n        if (ctx->next)\n            ctx->next->prev = ctx->prev;\n        if (ctx->prev)\n            ctx->prev->next = ctx->next;\n        else {\n            if (threadContexts != ctx)\n                oops(41);\n            threadContexts = ctx->next;\n            if (threadContexts)\n                threadContexts->prev = NULL;\n        }\n#endif\n        app_free(ctx);\n        setThreadContext(NULL);\n    }\n#endif\n}\n\n#define ALLOC(tp) (tp *)app_alloc(sizeof(tp))\n\nThreadContext *pushThreadContext(void *sp, void *endSP) {\n#ifdef PXT_VM\n    return NULL;\n#else\n    if (PXT_IN_ISR())\n        target_panic(PANIC_CALLED_FROM_ISR);\n\n    auto curr = getThreadContext();\n    tempRoot = (TValue *)endSP;\n    tempRootLen = (uintptr_t *)sp - (uintptr_t *)endSP;\n    if (curr) {\n#ifdef PXT_GC_THREAD_LIST\n#ifdef PXT_GC_DEBUG\n        auto ok = false;\n        for (auto p = threadContexts; p; p = p->next)\n            if (p == curr) {\n                ok = true;\n                break;\n            }\n        if (!ok)\n            oops(49);\n#endif\n#endif\n        auto seg = ALLOC(StackSegment);\n        VLOG(\"stack %p / %p\", seg, curr);\n        seg->top = curr->stack.top;\n        seg->bottom = curr->stack.bottom;\n        seg->next = curr->stack.next;\n        curr->stack.next = seg;\n    } else {\n        curr = ALLOC(ThreadContext);\n        LOG(\"push: %p\", curr);\n        curr->globals = globals;\n        curr->stack.next = NULL;\n        curr->thrownValue = TAG_NON_VALUE;\n        curr->tryFrame = NULL;\n\n#ifdef PXT_GC_THREAD_LIST\n        curr->next = threadContexts;\n        curr->prev = NULL;\n        if (curr->next)\n            curr->next->prev = curr;\n        threadContexts = curr;\n#endif\n        setThreadContext(curr);\n    }\n    tempRootLen = 0;\n    curr->stack.bottom = sp;\n    curr->stack.top = NULL;\n    return curr;\n#endif\n}\n\nclass RefBlock : public RefObject {\n  public:\n    RefBlock *nextFree;\n};\n\nstruct GCBlock {\n    GCBlock *next;\n    uint32_t blockSize;\n    RefObject data[0];\n};\n\nstruct PendingArray {\n    PendingArray *next;\n    TValue *data;\n    unsigned len;\n};\n\n#define PENDING_ARRAY_THR 100\n\nstatic PendingArray *pendingArrays;\nstatic LLSegment gcRoots;\nLLSegment workQueue; // (ab)used by consString making\nstatic GCBlock *firstBlock;\nstatic RefBlock *firstFree;\nstatic uint8_t *midPtr;\n\nstatic bool inGCArea(void *ptr) {\n    for (auto block = firstBlock; block; block = block->next) {\n        if ((void *)block->data <= ptr && ptr < (void *)((uint8_t *)block->data + block->blockSize))\n            return true;\n    }\n    return false;\n}\n\n#define NO_MAGIC(vt) ((VTable *)vt)->magic != VTABLE_MAGIC\n#define VT(p) (*(uintptr_t *)(p))\n#define SKIP_PROCESSING(p)                                                                         \\\n    (isReadOnly(p) || (VT(p) & (ANY_MARKED_MASK | ARRAY_MASK)) || NO_MAGIC(VT(p)))\n\nvoid gcMarkArray(void *data) {\n    auto segBl = (uintptr_t *)data - 1;\n    GC_CHECK(!IS_MARKED(VT(segBl)), 47);\n    MARK(segBl);\n}\n\nvoid gcScan(TValue v) {\n    if (SKIP_PROCESSING(v))\n        return;\n    MARK(v);\n    workQueue.push(v);\n}\n\nvoid gcScanMany(TValue *data, unsigned len) {\n    // VLOG(\"scan: %p %d\", data, len);\n    for (unsigned i = 0; i < len; ++i) {\n        auto v = data[i];\n        // VLOG(\"psh: %p %d %d\", v, isReadOnly(v), (*(uint32_t *)v & 1));\n        if (SKIP_PROCESSING(v))\n            continue;\n        MARK(v);\n        workQueue.push(v);\n        if (workQueue.getLength() > PENDING_ARRAY_THR) {\n            i++;\n            // store rest of the work for later, when we have cleared the queue\n            auto pa = (PendingArray *)xmalloc(sizeof(PendingArray));\n            pa->next = pendingArrays;\n            pa->data = data + i;\n            pa->len = len - i;\n            pendingArrays = pa;\n            break;\n        }\n    }\n}\n\nvoid gcScanSegment(Segment &seg) {\n    auto data = seg.getData();\n    if (!data)\n        return;\n    VVLOG(\"seg %p %d\", data, seg.getLength());\n    gcMarkArray(data);\n    gcScanMany(data, seg.getLength());\n}\n\n#define getScanMethod(vt) ((RefObjectMethod)(((VTable *)(vt))->methods[2]))\n#define getSizeMethod(vt) ((RefObjectSizeMethod)(((VTable *)(vt))->methods[3]))\n\nvoid gcProcess(TValue v) {\n    if (SKIP_PROCESSING(v))\n        return;\n    VVLOG(\"gcProcess: %p\", v);\n    MARK(v);\n    auto scan = getScanMethod(VT(v) & ~ANY_MARKED_MASK);\n    if (scan)\n        scan((RefObject *)v);\n    for (;;) {\n        while (workQueue.getLength()) {\n            auto curr = (RefObject *)workQueue.pop();\n            VVLOG(\" - %p\", curr);\n            scan = getScanMethod(curr->vt() & ~ANY_MARKED_MASK);\n            if (scan)\n                scan(curr);\n        }\n        if (pendingArrays) {\n            auto pa = pendingArrays;\n            pendingArrays = pa->next;\n            auto data = pa->data;\n            auto len = pa->len;\n            xfree(pa);\n            gcScanMany(data, len);\n        } else {\n            break;\n        }\n    }\n}\n\nstatic void mark(int flags) {\n#ifdef PXT_GC_DEBUG\n    flags |= 2;\n#endif\n    auto data = gcRoots.getData();\n    auto len = gcRoots.getLength();\n    if (flags & 2) {\n        DMESG(\"--MARK\");\n        DMESG(\"RP:%p/%d\", data, len);\n    }\n    for (unsigned i = 0; i < len; ++i) {\n        auto d = data[i];\n        if ((uintptr_t)d & 1) {\n            d = *(TValue *)((uintptr_t)d & ~1);\n        }\n        gcProcess(d);\n    }\n\n#ifdef PXT_GC_THREAD_LIST\n    for (auto ctx = threadContexts; ctx; ctx = ctx->next) {\n        gcProcess(ctx->thrownValue);\n        for (auto seg = &ctx->stack; seg; seg = seg->next) {\n            auto ptr = (TValue *)threadAddressFor(ctx, seg->top);\n            auto end = (TValue *)threadAddressFor(ctx, seg->bottom);\n            VLOG(\"mark: %p - %p\", ptr, end);\n            while (ptr < end) {\n                gcProcess(*ptr++);\n            }\n        }\n    }\n#else\n    gcProcessStacks(flags);\n#endif\n\n    if (globals) {\n#ifdef PXT_VM\n        auto nonPtrs = vmImg->infoHeader->nonPointerGlobals;\n#else\n        auto nonPtrs = bytecode[21];\n#endif\n        len = getNumGlobals() - nonPtrs;\n        data = globals + nonPtrs;\n        if (flags & 2)\n            DMESG(\"RG:%p/%d\", data, len);\n        VLOG(\"globals: %p %d\", data, len);\n        for (unsigned i = 0; i < len; ++i) {\n            gcProcess(*data++);\n        }\n    }\n\n#ifndef PXT_VM\n    data = tempRoot;\n    len = tempRootLen;\n    for (unsigned i = 0; i < len; ++i) {\n        gcProcess(*data++);\n    }\n#endif\n}\n\nstatic uint32_t getObjectSize(RefObject *o) {\n    auto vt = o->vt() & ~ANY_MARKED_MASK;\n    uint32_t r;\n    GC_CHECK(vt != 0, 49);\n    if (IS_VAR_BLOCK(vt)) {\n        r = VAR_BLOCK_WORDS(vt);\n    } else {\n        auto sz = getSizeMethod(vt);\n        // GC_CHECK(0x2000 <= (intptr_t)sz && (intptr_t)sz <= 0x100000, 47);\n        r = sz(o);\n    }\n    GC_CHECK(1 <= r && (r <= BYTES_TO_WORDS(GC_MAX_ALLOC_SIZE) || IS_FREE(vt)), 41);\n    return r;\n}\n\nstatic void setupFreeBlock(GCBlock *curr) {\n    gcStats.numBlocks++;\n    gcStats.totalBytes += curr->blockSize;\n    curr->data[0].setVT(FREE_MASK | (TOWORDS(curr->blockSize) << 2));\n    ((RefBlock *)curr->data)[0].nextFree = firstFree;\n    firstFree = (RefBlock *)curr->data;\n    midPtr = (uint8_t *)curr->data + curr->blockSize / 4;\n}\n\nstatic void linkFreeBlock(GCBlock *curr) {\n    // blocks need to be sorted by address for midPtr to work\n    if (!firstBlock || curr < firstBlock) {\n        curr->next = firstBlock;\n        firstBlock = curr;\n    } else {\n        for (auto p = firstBlock; p; p = p->next) {\n            if (!p->next || curr < p->next) {\n                curr->next = p->next;\n                p->next = curr;\n                break;\n            }\n        }\n    }\n}\n\nvoid gcPreAllocateBlock(uint32_t sz) {\n    auto curr = (GCBlock *)GC_ALLOC_BLOCK(sz);\n    curr->blockSize = sz - sizeof(GCBlock);\n    LOG(\"GC pre-alloc: %p\", curr);\n    GC_CHECK((curr->blockSize & 3) == 0, 40);\n    setupFreeBlock(curr);\n    linkFreeBlock(curr);\n}\n\nstatic GCBlock *allocateBlockCore() {\n    int sz = GC_BLOCK_SIZE;\n    void *dummy = NULL;\n#ifdef GC_GET_HEAP_SIZE\n    if (firstBlock) {\n#ifdef GC_STACK_BASE\n        if (!firstBlock->next) {\n            int memSize = getConfig(CFG_RAM_BYTES, 0);\n            int codalEnd = GC_STACK_BASE;\n            // round up to 1k - there is sometimes a few bytes below the stack\n            codalEnd = (codalEnd + 1024) & ~1023;\n            int codalSize = codalEnd & 0xffffff;\n            sz = memSize - codalSize - 4;\n            if (sz > 0) {\n                auto curr = (GCBlock *)codalEnd;\n                curr->blockSize = sz - sizeof(GCBlock);\n                return curr;\n            }\n        }\n#endif\n        gc(2); // dump roots\n        soft_panic(PANIC_GC_OOM);\n    }\n    auto lowMem = getConfig(CFG_LOW_MEM_SIMULATION_KB, 0);\n    auto sysHeapSize = getConfig(CFG_SYSTEM_HEAP_BYTES, 4 * 1024);\n    auto heapSize = GC_GET_HEAP_SIZE();\n    DMESG(\"heap: %d (minus %d sys bytes)\", heapSize, sysHeapSize);\n    sz = heapSize - sysHeapSize;\n    if (lowMem) {\n        auto memIncrement = 32 * 1024;\n        // get the memory size - assume it's increment of 32k,\n        // and we don't statically allocate more than 32k\n        auto memSize = ((heapSize + memIncrement - 1) / memIncrement) * memIncrement;\n        int fillerSize = memSize - lowMem * 1024;\n        if (fillerSize > 0) {\n            dummy = GC_ALLOC_BLOCK(fillerSize);\n            sz -= fillerSize;\n        }\n    }\n#endif\n    auto curr = (GCBlock *)GC_ALLOC_BLOCK(sz);\n    curr->blockSize = sz - sizeof(GCBlock);\n    // make sure reference to allocated block is stored somewhere, otherwise\n    // GCC optimizes out the call to GC_ALLOC_BLOCK\n    curr->data[4].setVT((uintptr_t)dummy);\n    return curr;\n}\n\n__attribute__((noinline)) static void allocateBlock() {\n    auto curr = allocateBlockCore();\n    DMESG(\"GC block %db @ %p\", curr->blockSize, curr);\n    GC_CHECK((curr->blockSize & 3) == 0, 40);\n    setupFreeBlock(curr);\n    linkFreeBlock(curr);\n}\n\nstatic void sweep(int flags) {\n    RefBlock *prevFreePtr = NULL;\n    uint32_t freeSize = 0;\n    uint32_t totalSize = 0;\n    uint32_t maxFreeBlock = 0;\n    firstFree = NULL;\n\n    gcStats.numGC++;\n\n    for (auto h = firstBlock; h; h = h->next) {\n        auto d = h->data;\n        auto words = BYTES_TO_WORDS(h->blockSize);\n        auto end = d + words;\n        totalSize += words;\n        VLOG(\"sweep: %p - %p\", d, end);\n        while (d < end) {\n            if (IS_LIVE(d->vtable)) {\n                VVLOG(\"Live %p\", d);\n                d->setVT(d->vt() & ~MARKED_MASK);\n                d += getObjectSize(d);\n            } else {\n                auto start = (RefBlock *)d;\n                while (d < end) {\n                    if (IS_FREE(d->vtable)) {\n                        VVLOG(\"Free %p\", d);\n                    } else if (IS_LIVE(d->vtable)) {\n                        break;\n                    } else if (IS_ARRAY(d->vtable)) {\n                        VVLOG(\"Dead Arr %p\", d);\n                    } else {\n                        VVLOG(\"Dead Obj %p\", d);\n                        GC_CHECK(d->vtable->magic == VTABLE_MAGIC, 41);\n                        d->destroyVT();\n                        VVLOG(\"destroyed\");\n                    }\n                    d += getObjectSize(d);\n                }\n                auto sz = d - (RefObject *)start;\n                freeSize += sz;\n                if (sz > (int)maxFreeBlock)\n                    maxFreeBlock = sz;\n#ifdef PXT_GC_CHECKS\n                memset((void *)start, 0xff, WORDS_TO_BYTES(sz));\n#endif\n                start->setVT((sz << 2) | FREE_MASK);\n                if (sz > 1) {\n                    start->nextFree = NULL;\n                    if (!prevFreePtr) {\n                        firstFree = start;\n                    } else {\n                        prevFreePtr->nextFree = start;\n                    }\n                    prevFreePtr = start;\n                }\n            }\n        }\n    }\n\n    if (midPtr) {\n        uint32_t currFree = 0;\n#ifdef PXT_ESP32\n        auto limit = freeSize * 1 / 4;\n#else\n        auto limit = freeSize * 1 / 2;\n#endif\n        for (auto p = firstFree; p; p = p->nextFree) {\n            auto len = VAR_BLOCK_WORDS(p->vtable);\n            currFree += len;\n            if (currFree > limit) {\n                midPtr = (uint8_t *)p + ((limit - currFree + len) << 2);\n                break;\n            }\n        }\n    }\n\n    freeSize = WORDS_TO_BYTES(freeSize);\n    totalSize = WORDS_TO_BYTES(totalSize);\n    maxFreeBlock = WORDS_TO_BYTES(maxFreeBlock);\n\n    gcStats.lastFreeBytes = freeSize;\n    gcStats.lastMaxBlockBytes = maxFreeBlock;\n\n    if (gcStats.minFreeBytes == 0 || gcStats.minFreeBytes > freeSize)\n        gcStats.minFreeBytes = freeSize;\n\n    if (flags & 1)\n        DMESG(\"GC %d/%d free; %d maxBlock\", freeSize, totalSize, maxFreeBlock);\n    else\n        LOG(\"GC %d/%d free; %d maxBlock\", freeSize, totalSize, maxFreeBlock);\n\n#ifndef GC_GET_HEAP_SIZE\n    // if the heap is 90% full, allocate a new block\n    if (freeSize * 10 <= totalSize) {\n        allocateBlock();\n    }\n#endif\n}\n\nvoid gc(int flags) {\n    startPerfCounter(PerfCounters::GC);\n    GC_CHECK(!(inGC & IN_GC_COLLECT), 40);\n    inGC |= IN_GC_COLLECT;\n    VLOG(\"GC mark\");\n    mark(flags);\n    VLOG(\"GC sweep\");\n    sweep(flags);\n    VLOG(\"GC done\");\n    stopPerfCounter(PerfCounters::GC);\n    inGC &= ~IN_GC_COLLECT;\n}\n\n#ifdef GC_GET_HEAP_SIZE\nextern \"C\" void free(void *ptr) {\n    if (!ptr)\n        return;\n    if (inGCArea(ptr))\n        app_free(ptr);\n    else\n        xfree(ptr);\n}\n\nextern \"C\" void *malloc(size_t sz) {\n    if (PXT_IN_ISR() || inGC)\n        return xmalloc(sz);\n    else\n        return app_alloc(sz);\n}\n\nextern \"C\" void *realloc(void *ptr, size_t size) {\n    if (inGCArea(ptr)) {\n        void *mem = malloc(size);\n\n        if (ptr != NULL && mem != NULL) {\n            auto r = (uintptr_t *)ptr;\n            GC_CHECK((r[-1] >> (HIGH_SHIFT + 1)) == 3, 41);\n            size_t blockSize = VAR_BLOCK_WORDS(r[-1]);\n            memcpy(mem, ptr, min(blockSize * sizeof(void *), size));\n            free(ptr);\n        }\n\n        return mem;\n    } else {\n        return device_realloc(ptr, size);\n    }\n}\n#endif\n\nvoid *gcAllocateArray(int numbytes) {\n    numbytes = ALIGN_TO_WORD(numbytes);\n    numbytes += sizeof(void *);\n    auto r = (uintptr_t *)gcAllocate(numbytes);\n    *r = ARRAY_MASK | (TOWORDS(numbytes) << 2);\n    return r + 1;\n}\n\nstatic void *gcAllocAt(void *hint, int numbytes) {\n    gc(0);\n    size_t numwords = BYTES_TO_WORDS(ALIGN_TO_WORD(numbytes));\n\n    for (auto p = firstFree; p; p = p->nextFree) {\n        GC_CHECK(!isReadOnly((TValue)p), 49);\n        auto vt = p->vtable;\n        GC_CHECK(IS_FREE(vt), 43);\n        int offset = BYTES_TO_WORDS((uint8_t *)hint - (uint8_t *)p);\n        int left = (int)(VAR_BLOCK_WORDS(vt) - numwords - offset);\n        // we give ourselves some space here, so we don't get some strange overlaps\n        if (offset >= 8 && left >= 8) {\n            auto nf = (RefBlock *)((void **)p + numwords + offset);\n            nf->setVT((left << 2) | FREE_MASK);\n            nf->nextFree = p->nextFree;\n            p->nextFree = nf;\n            p->setVT((offset << 2) | FREE_MASK);\n            p = (RefBlock *)((void **)p + offset);\n            p->setVT(0);\n            return p;\n        }\n    }\n\n    return NULL;\n}\n\nvoid *app_alloc_at(void *at, int numbytes) {\n    if (numbytes < 8)\n        return NULL;\n    if (!at)\n        return NULL;\n\n    numbytes = ALIGN_TO_WORD(numbytes) + sizeof(void *);\n    auto r = (uintptr_t *)gcAllocAt((uintptr_t *)at - 1, numbytes);\n    if (!r)\n        return NULL;\n    *r = ARRAY_MASK | PERMA_MASK | (TOWORDS(numbytes) << 2);\n    gc(0);\n    return r + 1;\n}\n\nvoid *app_alloc(int numbytes) {\n    if (!numbytes)\n        return NULL;\n\n    // gc(0);\n    auto r = (uintptr_t *)gcAllocateArray(numbytes);\n    r[-1] |= PERMA_MASK;\n    return r;\n}\n\nvoid *app_free(void *ptr) {\n    auto r = (uintptr_t *)ptr;\n    GC_CHECK((r[-1] >> (HIGH_SHIFT + 1)) == 3, 41);\n    r[-1] |= FREE_MASK;\n    return r;\n}\n\nvoid gcFreeze() {\n    inGC |= IN_GC_FREEZE;\n}\n\nvoid gcReset() {\n    inGC &= ~IN_GC_FREEZE;\n\n    gcRoots.setLength(0);\n\n    if (inGC)\n        oops(41);\n\n    if (workQueue.getLength())\n        oops(41);\n\n    memset(&gcStats, 0, sizeof(gcStats));\n    firstFree = NULL;\n    for (auto h = firstBlock; h; h = h->next) {\n        setupFreeBlock(h);\n    }\n}\n\n#ifdef PXT_VM\nvoid gcPreStartup() {\n    inGC |= IN_GC_PREALLOC;\n}\n\nvoid gcStartup() {\n    inGC &= ~IN_GC_PREALLOC;\n}\n#endif\n\nvoid *gcAllocate(int numbytes) {\n    size_t numwords = BYTES_TO_WORDS(ALIGN_TO_WORD(numbytes));\n    // VVLOG(\"alloc %d bytes %d words\", numbytes, numwords);\n\n    if (numbytes > GC_MAX_ALLOC_SIZE)\n        soft_panic(PANIC_GC_TOO_BIG_ALLOCATION);\n\n    if (PXT_IN_ISR() || (inGC & (IN_GC_PREALLOC | IN_GC_ALLOC | IN_GC_COLLECT | IN_GC_FREEZE)))\n        target_panic(PANIC_CALLED_FROM_ISR);\n\n    inGC |= IN_GC_ALLOC;\n\n#if defined(PXT_GC_CHECKS) && !defined(PXT_VM)\n    {\n        auto curr = getThreadContext();\n        if (curr && !curr->stack.top)\n            oops(46);\n    }\n#endif\n\n#ifdef PXT_GC_STRESS\n    gc(0);\n#endif\n\n    for (int i = 0;; ++i) {\n        RefBlock *prev = NULL;\n        for (auto p = firstFree; p; p = p->nextFree) {\n            VVLOG(\"p=%p\", p);\n            if (i == 0 && (uint8_t *)p > midPtr) {\n                VLOG(\"past midptr %p; gc\", midPtr);\n                break;\n            }\n            GC_CHECK(!isReadOnly((TValue)p), 49);\n            auto vt = p->vtable;\n            if (!IS_FREE(vt))\n                oops(43);\n            int left = (int)(VAR_BLOCK_WORDS(vt) - numwords);\n            VVLOG(\"%p %d - %d = %d\", (void *)vt, (int)VAR_BLOCK_WORDS(vt), (int)numwords, left);\n            if (left >= 0) {\n                auto nf = (RefBlock *)((void **)p + numwords);\n                auto nextFree = p->nextFree; // p and nf can overlap when allocating 4 bytes\n                // VVLOG(\"nf=%p nef=%p\", nf, nextFree);\n                if (left)\n                    nf->setVT((left << 2) | FREE_MASK);\n                if (left >= 2) {\n                    nf->nextFree = nextFree;\n                } else {\n                    nf = nextFree;\n                }\n                if (prev)\n                    prev->nextFree = nf;\n                else\n                    firstFree = nf;\n                p->setVT(0);\n                VVLOG(\"GC=>%p %d %p -> %p,%p\", p, numwords, nf, nf ? nf->nextFree : 0,\n                      nf ? (void *)nf->vtable : 0);\n                GC_CHECK(!nf || !nf->nextFree || !isReadOnly((TValue)nf->nextFree), 48);\n                inGC &= ~IN_GC_ALLOC;\n                return p;\n            }\n            prev = p;\n        }\n\n        // we didn't find anything, try GC\n        if (i == 0)\n            gc(0);\n        // GC didn't help, try new block\n        else if (i == 1) {\n            DMESG(\"gcAlloc(%d) (%d/%d free; %d max block) -> new block\", numbytes,\n                  gcStats.lastFreeBytes, gcStats.totalBytes, gcStats.lastMaxBlockBytes);\n            allocateBlock();\n        } else\n            // the block allocated was apparently too small\n            soft_panic(PANIC_GC_OOM);\n    }\n}\n\nstatic void removePtr(TValue v) {\n    int len = gcRoots.getLength();\n    auto data = gcRoots.getData();\n    // scan from the back, as this is often used as a stack\n    for (int i = len - 1; i >= 0; --i) {\n        if (data[i] == v) {\n            if (i == len - 1) {\n                gcRoots.pop();\n            } else {\n                data[i] = gcRoots.pop();\n            }\n            return;\n        }\n    }\n    oops(40);\n}\n\nvoid registerGC(TValue *root, int numwords) {\n    if (!numwords)\n        return;\n\n    if (numwords > 1) {\n        while (numwords-- > 0) {\n            registerGC(root++, 1);\n        }\n        return;\n    }\n\n    gcRoots.push((TValue)((uintptr_t)root | 1));\n}\n\nvoid unregisterGC(TValue *root, int numwords) {\n    if (!numwords)\n        return;\n    if (numwords > 1) {\n        while (numwords-- > 0) {\n            unregisterGC(root++, 1);\n        }\n        return;\n    }\n\n    removePtr((TValue)((uintptr_t)root | 1));\n}\n\nvoid registerGCPtr(TValue ptr) {\n    if (isReadOnly(ptr))\n        return;\n    gcRoots.push(ptr);\n}\n\nvoid unregisterGCPtr(TValue ptr) {\n    if (isReadOnly(ptr))\n        return;\n    removePtr(ptr);\n}\n\nvoid RefImage::scan(RefImage *t) {\n    gcScan((TValue)t->buffer);\n}\n\nvoid RefCollection::scan(RefCollection *t) {\n    gcScanSegment(t->head);\n}\n\nvoid RefAction::scan(RefAction *t) {\n    gcScanMany(t->fields, t->len);\n}\n\nvoid RefRefLocal::scan(RefRefLocal *t) {\n    gcScan(t->v);\n}\n\nvoid RefMap::scan(RefMap *t) {\n    gcScanSegment(t->keys);\n    gcScanSegment(t->values);\n}\n\nvoid RefRecord_scan(RefRecord *r) {\n    VTable *tbl = getVTable(r);\n    gcScanMany(r->fields, BYTES_TO_WORDS(tbl->numbytes - sizeof(RefRecord)));\n}\n\n#define SIZE(off) TOWORDS(sizeof(*t) + (off))\n\nunsigned RefImage::gcsize(RefImage *t) {\n    return SIZE(0);\n}\n\nunsigned RefCollection::gcsize(RefCollection *t) {\n    return SIZE(0);\n}\n\nunsigned RefAction::gcsize(RefAction *t) {\n    return SIZE(WORDS_TO_BYTES(t->len));\n}\n\nunsigned RefRefLocal::gcsize(RefRefLocal *t) {\n    return SIZE(0);\n}\n\nunsigned RefMap::gcsize(RefMap *t) {\n    return SIZE(0);\n}\n\n} // namespace pxt\n","gcstats.ts":"namespace control {\n    //% shim=pxt::getGCStats\n    function getGCStats(): Buffer {\n        return null\n    }\n\n    export interface GCStats {\n        numGC: number;\n        numBlocks: number;\n        totalBytes: number;\n        lastFreeBytes: number;\n        lastMaxBlockBytes: number;\n        minFreeBytes: number;\n    }\n\n    /**\n     * Get various statistics about the garbage collector (GC)\n     */\n    export function gcStats(): GCStats {\n        const buf = getGCStats()\n        if (!buf)\n            return null\n        let off = 0\n        const res: any = {}\n\n        addField(\"numGC\")\n        addField(\"numBlocks\")\n        addField(\"totalBytes\")\n        addField(\"lastFreeBytes\")\n        addField(\"lastMaxBlockBytes\")\n        addField(\"minFreeBytes\")\n\n        return res\n\n        function addField(name: string) {\n            res[name] = buf.getNumber(NumberFormat.UInt32LE, off)\n            off += 4\n        }\n    }    \n}","gestures.jres":"{\n  \"*\": {\n    \"namespace\": \"gestures\",\n    \"dataEncoding\": \"base64\"\n  },\n  \"shake\": {\n    \"icon\": \"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAEAAAABACAYAAACqaXHeAAAACXBIWXMAAAsSAAALEgHS3X78AAAEe0lEQVR4nO2a0XHjNhCGP2bybnZgpgLzKjBTwTkVRKkgSgXhVRC5Assd+CoIXUHkCkJXELmCzQMWIQSREgjSB4/CfwYDAlgSi5/A7gJkJiL8n/FdagVSYyEgtQKpsRCQWoHUWAhIrUBqLASkViA1FgJSKzA3MigzKELlL4qADFZAAzyF3nNRBCiugJsM6hDh7NJ2gxlsgZ+1+INAe1J+JgIqTMfXWn7BdLzTZK/fHRnk2t8V8ChmWQzLz0BAgRncFfCqnd8OyD5re4tZq/Z6VmSwBv7Q4sEsyKA4mBUiMjWtxWDr1RciUolIrW2tDKNRmVrvKabqhcheC1stV4jsENl7cpMJ2OoghpTOReRJB+kSs48gJh9BwEYLey0XjkA1JwE7HURfW+UMsHYIsPeslIgx2CsxGzGzr5cYREp/wIi0Wq5lJgJyVeqpp23jKV5FDjgUjXhE+ANGZKtlOxsnxwGl5juvbgf86snWwAPGWL4HbjkOgBrNK81bzQsrMJUA+2Db0Rr4C7jpkbWe4QXjDV4n9t0H3/u0mheaN5pbd833Ezu0M6DVhw+5P4CvGIJar77CKFjodUn8LHnzyg3wO86AfUwloNJObRwwhEe6gKTEBCtWwaZHPseQtT7zXB99z3LRAl/ciimBUAH8HSD3qrI5Zo36s8QGTw3HUWOJWVKh+IKzB9Bd4QpAhvYGZ6z8qXQXaJ1XKl87dad8v20veu47h//8e2iaYgSrQLnWk78HNmfuuXZktiN0Gr3fmGIDyvMivfDdo4tHzFJ4AD5rXRv43BdgP1aZKTPglMV3YYk699YB7hw56yaLwH6idpuxBPhv/yvwG+Yt+KjpDOCPmLfcJwfG4lurb4moAnWK226PNRqa7A5QxMT1tr4cME476d8slWKMaS3dhqmRznDmct5gWpQxY4m1Ae4MaJzrnH7cYFzmI90hiZv6zvByffZgEOMhagbExgE7DsPdXzAGaEO4wtAFUb7/v8P479Ag6JnwpXKAGAJy4J+YzmbCC8d7jXtM1DgaMUYw1v1NxRvwSfv/yWtrYh8aQ0AV29lE2KUCxzYj+sB1kIAMGk3+G081A0q6mKB26t+YcrBq3QEijaZSDo+KVp7reK8TnVDsvHLfaVTUXuBWk33Dz5oXjkzB+53ohMI3gJO+N7gE9A3YL/ttHwHNlJv7bIB7WAHp1nwoZpsBjeaV9+Cb7JCUoTg+BaJ2gC5cAvwBN07bnXNdYQKPZ47P4L41pn9vlM4L5L7lR+TJP0fvSbmYk5i1mG8BjXw7T7EOsfSn0kEonJkAYw9sBHb6w8GDNp/91OyhoDvptdehZwih+MTEWXB2L5AZQoI+NQeiYB5i3hjefYbj3BRBpHYqRh86jkiFHH5N9gMeH/Uc/QbtBjMz9a8xx1SlTLS8I2FD4JLOJW8Z8R/QKYQSUAF/avFeIreeHxFBu0ExLvEes+5mYf6jYNSByNHvJReAi/tLbCwu8T/BUVgISK1AaiwEpFYgNRYCUiuQGgsBqRVIjYWA1Aqkxr8PLUpMvtN12gAAAABJRU5ErkJggg==\"\n  },\n  \"freefall\": {\n    \"icon\": \"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAEAAAABACAYAAACqaXHeAAAACXBIWXMAAAsSAAALEgHS3X78AAADqElEQVR4nO2b4XWbMBSFP3r6P2wQOkGcCUonqDtB0wnqbuBO0GSCJhvYG5AJiiconaD2BK8/JGpZAVtIYJGEew7HRAi9x0W670kiiYjwmvEmtgOxMREQ24HYmAiI7YCJBMoEVme1OaYokIAACCTnsjmqHtCEBIoEloO1P/YeMHSvGH0PGBoTAbEMJyAJlLHs//cjlga4jvdJAwbGREBsB2JjIiC2A7ExERDR9hr441DvDngcyonRzwWGxqsfAm9jO2DhOzA7p8G+hkAO3AOX+u8NUKFy/dI4Hx36ICBDPdwFStQq4H1L3Ud9vQIK4zwa+iBgAfwAHoAbozzTR278XtKMaMT0QcA98Bl4R7PTqa6TsicjQy1+ruhGTAlsQx0+gIiEHqWIVC3Xcn1NRGSpyzLjnhsR2Uo3bEWkEJFbEVloG6mv/6EPn2qnVg3Xbi3Hc88HdkUhHkSEEpBr40ujbCbqDTc5ODSKBh+PHqGJUK5/C/27AH4BVw1168iwQY1tlzS4K9qiTytCE6E6aalQJBxzYI0iqLLKcw4jxgwVUn2w63pDaBQwFfmY02aInKEiAux7jo0URdbiRLs21sC8Q/0gDcgcx2UdIVJp1oFKly9FZC5KQ0w96QJTiwYXwbmjUze6/tJ66GOoRBFs33cK+RF/exfB3LFeZdW/A25P3HNp1Lnv4FPn+UaICPrO2r4eufaA0oWfwEddVjm2u8EjSwzpAa4hpybq1FsHJWB1vTpMZo52vGabvgTYb38NfEO9BRtLlKqvgA+ot9xUD5Ti16pfE5E7+uQ33e4qGvpYGMJTGuVtql0aooZVf66FbiUqGhSyF85UTgtmDTN6OB++GmD2gMI4T2nGFfAb9fbLhqPps5hUt902U7Th1QN8E6GSw3T3C0qAbnF3GFTm1rRqNEclTq5J0CPuQ+UAPgSkwF8fYz1hw9O5xh0qa+wMHxE866KlgR1wre1/sq4Vvo36EJD7GgtEPVTgqWZ4L7g+px4wY58TLI3yHQHrhz5RIPc1FogLVCSxNaAIabRrD8jwn6v3BVsAg/YbfAgYG4qQm1/C3uBZe0BBex4fA14zQBO+YbDes++8BtczgvcbfaLAlsOsK0WFqDpM1efnEMtgAob8QCLjcG8ww2PZ+gSuCSQhxhciGf0Qs6N99umMGB9IVOz3EUxkHBIzo3mDpYbLCtNJjOoboRbY2gJqobSXf615DgQMipeQCAVhIiC2A7ExERDbgdh49QT8A9YP5MUcc2wYAAAAAElFTkSuQmCC\"\n  },\n  \"frontsideup\": {\n    \"icon\": \"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAEAAAABACAYAAACqaXHeAAAACXBIWXMAAAsSAAALEgHS3X78AAADSUlEQVR4nO2a63XaQBCFP+Xkv9WB1QG4AquD0EFwBy6BElwC7oBUEFxBoAKLDnAFkx+jjVZCbyQNOeieswehx+7cuzOzDykQEe4Z36wNsMYsgLUB1pgFsDbAGqYCBLAJYGNqg9UwGMAS+JP+fRI4WNhh6QHbiuNJYSJA6vYL79TCKhQmD4EAIuCz4vLkoWDhAduaa29TGeEwqQABvALPNbc8p/dMBrNRACAAARAIrGy4+4nQd8vGLXve4e49wHoqLC4PWOHuPWDOAdYGWGPOAZaN3wLmHGBtgDXmHGDZ+C3g7nPAWAKE6Lp+DTym577Q3R5XEmA/UvutMcZ+wBIl9gC8k5GMgDj9ffTuP5GJkZAJNAmGFsCRByVbR+QV3QjdoaIsUdEcjuQFcV4zKIYUoIl8mJ5fpeUBeCHbI1yhIXNOy5q8IA4fqBAJmdckfY0eSoAq8hFKLAZ+FJ75hfb+qnDtRD5E2sDPL4l3fG56cAgBiuRDMtKL0iemgxNm75UcrhXAT3hHtMfL3LZo1I7MfR2itD5Xmurpg4th9xoBfPJt8IUmvi35EQHyrusQkokRoV7VNTSK7YcXZ0WkT1mKyFna4yAiYVq2Le7dichGRFYiEnntvnZo08dZ1OYLLlOQT0SJIyJ77/y68L8OK6/9Q4e2RWrISw8Bysg3ibHxnm+LveR729URtmivaFsleekoQJH8oVB5Vc/svHtW6f+kheEOiWRh0BQ+xTpqyUsHAcp6PvauN8XmTvJu7EosGgpvor1eJL4R7fVI2oeLSEvyItJqFKjL9h90H7JOXE5vq6bMS3Tk+Nmh/i+ap+H/0CRA16HuGhzJz9z6zAU6kYd6AaYk3xZuZgflr9mf6LiSrNoPCNHZ2i2Rf0cXSA5n8va90GMZXbYlFqI9f82sawy4r0eWXHaOv6rshLIQiIHffSozQm/yUO4BBzS7/w+4ijw0jwIxuhCJ0uOxVml9cDV56LcaLK7Sxly+VmEQ8jDsllhEfpkbUf9FWF8MRh6m+UosIr/REdF/p2hQ8mD7mZwfQjGX2+U+TugcYD+0EabfCVYgJgsh0DF/tPcEtyjApLj7l6OzANYGWGMWwNoAa8wCWBtgjVkAawOs8ReItTjrXj7vnAAAAABJRU5ErkJggg==\"\n  },\n  \"backsideup\": {\n    \"icon\": \"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAEAAAABACAYAAACqaXHeAAAACXBIWXMAAAsSAAALEgHS3X78AAACbUlEQVR4nO2a75GbMBDFf2TyPXRwdHCkgqOEdJCkg5TgElyCS0gJTgVxKojdwV0Fmw9CA7H5Zwx6HOjNMCNAg/Y97a6EpMTM2DI+qA1QIwqgNkCNKIDaADWkAiSwS2AntUE1DCaQA7/L288GJ4UdSg84tJSDQiJA6fbPtUfPqlAIHgIJZMDfltfBQ0HhAYeOd/tQRngEFSCBH8BLR5WXsk4wyEYBgAQMwCBR2bD5idBHZePKnvfYvAeop8Lm84AKm/eAmAPUBqgRc4Cy8SUg5gC1AWrEHKBsfAnYfA6YS4AU91//DXgqn73hVnv8dQaOM7U/GHOsB+Q4Yp8G1r9QiXGmEigIphbgXvJd+MP/gvjypJhSgCnJX+MN+MJtyKTldR774alGgbnJFzSTP+JWmA34OerrZvbolZvZq82HfUObqZmdanVeSzua7EvNbGdmRdP7R0Ngzp6v40KVCzJcOPg2vYc05QfvJX4T5nbY7eldZc8PQVfPY2aHq7o3dcbmgFA934c97SPDAfhalr2X3GBMCCyFvEd9gnXGhUhB5fZdIXK3AEsj34dO8nDfMLg68jBcgFWSh2ECrJY89AuwavLQLcDqyUO7ACluHH0v5MGtP9z9t9gkwPX08T3gOyMPWjUJkLMR8tAswAn4NfaDgfEQeeifCRa4qWVWlnOWkxceJg/j/gVSnBA5ThhfDinMJORh2iWxjMpTfLnrRNhYTEYewpwSy6i8xHvN2CQ7KXnQHpOrh1BRlp9a6l5wewzHqY2QnhNsQUEVQuAWO2fbJ1iiAEGx+c3RKIDaADWiAGoD1IgCqA1QIwqgNkCNf+aBYPgHiIEjAAAAAElFTkSuQmCC\"\n  },\n  \"impact3g\": {\n    \"icon\": \"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAEAAAABACAYAAACqaXHeAAAACXBIWXMAAAsSAAALEgHS3X78AAAEWklEQVR4nO2a/5XiNhDHP87L/0sqWKeCdQdxB6GDkArCVXCkA0rwdcBWcN4Kju3A2wFUMPljpEMI/5AtEXMc3/f8hKVhNJoZjWYEmYjwM+OXuQWYGw8FzC3A3HgoYG4B5sZDAXMLMDceCphbgGsig0UGVR/Nr/+TLHOhAhZ9BHfrARksgT+H6O5SARnkDLi+xV0qAF38Uwjh3SkggzXwRyj9XSkggwLYjPnOXSmAEa5vcdMKyGCZwSqQdgO8tAzlvV8UkZt9ECnMS41I0UNX9jHqmyO79SuxDFwB/wW2AgdnfAHsgecuHgJZ5wRzWznAC2qvs0GkdMa3Q0z6hm86BhjsTXs07TPwNYOdyfb+8ehfR3Gf28IBHrA0L4Wxft8XGkQWd+kBom0BvHfQHYGlGx9CkEoBOVCjAetgPm/RrKxkoCLrg0CDcX+zuJJ2N1/L5XYJmCCNq+7V06QRkVpEDnKJgxnbishanEAWsA12LX2V07H1xs4CZx/vFPcBBZqAvKJByWJhxuxTmtbP0z9QK9emtZ9dVP6kAqtMaUtRT5uGBNZfGQt3WXRprL8077mIVKJWrVs8xcJ608bMMcZj/KOzL4mKVsDWCLzw+hfOmJiFL8zCxYy1bZUhuIpZGr7+ovzc4IBuu6soYG8et68wglocRC3o9qXEylvUpkPYHZ6hUihARF3avm9aBJxi6TFofLnQ+qBqEfiAs51ia4ES+Ap8AnbmaavIQI+mCj2qcs6D5KgStgOt+X6mMu68OY5o8NzHngKFaXN0YV0LeUXL2q4kxT8xlj282vDhd5giaQ18Nl1HjJFEW6WL9IAdwzev76gVQGt2q7SGy+PPIqffm3x8wbk3MFavHBl3cnm0Ki63yKgnJKjZ468OoLXR3Z4iobHje4RHZG1Ogc6jz31iFr8IFM6nLQMWZpWwHaBzeU5aR0wtUI6gdWuBivb9/YZeeLi8dy10bahHyHKGGAUUwyTf6Rp0gdB9c2ODn4uQIuptmKQbqTzgiFqvrVTdmHaJBquucvaJU9CrTLsKkGM/TNKNmFPgwMmVfzPvBfCthfYsShsUaLS3R5+1dmWeLl4+/ibwZ7A2TFWAK9yRk/B9Qn+ge7pBrVYP8K8JywV+5/wIHYWpiZC7/584ZYGbnu88c3l/55bCNkkqgL8C5TgSsXiY7gFbLhdzbbyhnvbi9ZUxTKcGwahJJ+ALpwsVN+rXsYynKiA0RU0FNx9w64k6lvGUGFDGTjoBG04Xom7tEXUEwjQFhCZAKfGClt0uPhh5Bd6GKVugjJ00EeoUTKYoYPIdf2JEuz9MU0CdYuIESKKAmDxgRZqrrKno/sl7DJOIWgA0l8/RuGA/B/9BKQLRCZBF7J1gQ/svOTnXVUwS94fr/VW2oVsx7uVnzrSkKpkCbuUvMn5pnNOtmHcS5iK3ooAuuIoBTXwqEiRAFreugKvjR/iHyFXxUMDcAsyNhwLmFmBuPBQwtwBz4z9jSdC1TZEC4AAAAABJRU5ErkJggg==\"\n  },\n  \"impact6g\": {\n    \"icon\": \"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAEAAAABACAYAAACqaXHeAAAACXBIWXMAAAsSAAALEgHS3X78AAAEjElEQVR4nO2a0ZGkNhCGP1x+XxzBkcGNI7AcgdcR3GRgQsAReJwBm8FkYDYDLgKzEdxMBO0HtQotIwZGaI6hvH8VBUhNq/UjtboRmYjwf8YPaxuwNj4IWNuAtfFBwNoGrI3NEZBBmVLf5ggAygx2qZRtigDt+CfApNK5KQKAvZ5NKoXZliLBDE7AE3AWyFPo3MwIyOAZ23mAp1R+YDMEYAnwYVIo3TIBw/sobIKAzDq/p0HxLyl0b4IARt52lmAaPDwBmfX2v41Um6X6VyMggyKbt5Rdm+tmqR1rjoAc+JZBPTGU91fqZvuBDEwwjxCR1Q5EGq+gQ2SPSO7VF4OHuoAiE9BrECkRqRFpvcpDQHZVAkyg4qSG77QTft1e6/2yWssPg86G9OYBG9YjQA3otBPHCeFO5afkxo4qVPwIq0AF5GKd3a/A24hcrecmoo03se1cYu0RoG+18a5zRKqx4YudGrc28nyl7SSdyEWklh6N3ldindTF3BsYUTGQwTpA5yQPg7qhHzjp1Cix/sCva661nSodroEvwBlogQL74cKHq2uBzrs+uXhAbLr7DpoFtmKfcWUH7DON1rVenbPF4We//kJ/IgIEO3d39J3I9d4dLqAZxvSjxNxqRGaJ/9crepHrcUSSKWB02Jcj9TsRaaX3wrleu2kyhpPKHERkL4H1PjCVDiG/MfHMYgJKNThkYOV1yNUf9L4Wu7Tdik6JqZSYndcZP1D6bgS4t+iXFWqkDyN2JNwDpXZmx3sH2UzZn4IA90bc/V7s8B0iVJYS/jLpk3AR/vrHj7c6mgFyrLc/6nXNeOoK8IL13IXeG8IrRgx2QCPQqjNsgM/AH5ldKergU9fYmXEYZb+eeMOt2GkxpasU+8ZiRstwaOf0ucEJz1cM5BYRUM0w7CS9M6rETpdGRI56/yyXxg0Dqym0I53L6XOHjjskQ80M4yqVPUwJSr9cOkPnOs1QmltgI0x/ZTgG5BYRMGeomoHs84yO1dI71DnYex3KsSHxUQnYY9Pu4JK4pPPFTOMcAQ7diFw36PAtbQTn95xjSTpsZsoVen7R85jH/0Qftp71POeboQulo7CEAH9r6gz8DXwNyJXe+U/g9YpO942v1vOczY/ozgOLpoDvAN0wz0eGeC2Xc7DQ5yqxzqmRPsR1uub4GCcfdSzJBv0Hf6LP3sYUnrEBU8t0xleo7OcZdvyuslGIJcAA/3j3r9hhWzLPaIdhKnxS3f5O8BR88m9GLAEl8Fdso5H4iu2ovxfwRu9koxDrBJP9ozMTr9qmoV9NYKkDJJ4As7ThG9F4191IeRRiskGXAX5PlPTfGv3trcUjIMYHGN47wDWRLVUQMwXM0kYTIRR03YxH2BmKRZNCSQwBXYqGE2Dx/Ic4AmpsTH+ekLs3khCwdGPE3/wovOu5UVwsziT6UfJef4o6YgyWmIJEf3UpXknkjJd+FR7DCeukmkF5oYdhGTFDvdF4lH+FC+YTc9b66ATIx6MQMIaCnhiHA4k6D49PwN2x5UAoCT4IWNuAtfFBwNoGrI0PAtY2YG38B6VuuBeejFXUAAAAAElFTkSuQmCC\"\n  },\n  \"impact8g\": {\n    \"icon\": \"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAEAAAABACAYAAACqaXHeAAAACXBIWXMAAAsSAAALEgHS3X78AAAFVUlEQVR4nO2a7XHjNhCGH2Tuv5kKzFQgXgXHVHDq4HQVxCUoHSgVRK4gcgWhK4hUwUkVhK5g8wOABYMACRHUUTfxO4ORjY8F8AJY7C6hRIT/CxSUAkc376eZxhKFgkJBcwW5W2Dl598cAUANfFKwnEKYIXQPfAF2fvmtEgCwVVDkCFJQobf8AjiJJuINbpmAO/S2HQWlt/s/Rg7EjpWI3ExCpAgU1CPkbAMFy0jd+SfuDGYZKDgiUiS2LxHZhwpjbW7tCNSBvHtgPdRQ6bZ79Hn38RRtOPeqeysYXD2Tqp52DwPCVz1t55+4s337Ku0DbQrC591P5Y9wBOqB8oVyjoKCEq3Zvwy0O/jWn4sfiQCABwXlwHn30TF+XCiR2/AFlF6l+4Sqp8R6Fh9DBtBrv7dAgNnO37zsF85GzFicRMuO4kNmB70wE+sdgEEVyFsBGy5bbR+92x+uTAB68n+PaHcS2Blf4M+M/pvBGt/heku5pvz04LQ/juy8TRzf1QkoEGlNxhKRNSLNQMPCaV/3TbJH1i5lfFe/BgVazvd3IbAWqAUU8BH4CvwBHEydR9PGtm+A54DoA2HdYTF4/nUHV94BzkruEWkS6pWBvMqruLW7JGUXzXoEAlu5M8HE9laXrBKOR8dsnp0AZxKbkW1LPIcIrU9CDVrTVzAGMCcBxSWrkyBvSJkK+hbZENl5390SNKGqVlKVVL+sSwd/QBtXO6top7oFSrS2FrTgxnT0gHZcXoObkhHnc6H6b4AYFmjD6l8bdZ5qB1jP7IR2aiq6dvyLqbc3dfZMEP83nqFNnxKbPcmEBFTo6OsTb2P5hSmzqTZ5PjGWtMb82r9HwaxsbVLIXT6g7RBta0ygjFaiUUfKl6LNUquRSxHZirbUGonjaMrXpo+Y/JiC3AQK9nj2wRQEbMyAfcOjcMrETLwwExdT1vYQkELMUsKGU8g+aEM3wRQE7KV7tVVmoBat6BV086bEyplQQdeBaokEVacgQERvafv/OjDAMSt9CY5ynlBo60cjyrnxgNr87tFX4S6ieO7Qt8DWqesqydzIjxs0WXllh76QWC4B9i4u0Z3EJvJkBtZGyv0bY9kjK4ST83eJvkXsQiyU9kDXwZaxrZGYrELrw1608rNKsTFpK/q41NJVTqVplwr3CL6a3CnHIJeAFKVmr78moW4jmhREE5aqO14jSBInIfiNMWfyReLg/Lp1wsQsCZuBeq7M4Dh5G5LrRIlyfIH6grruQ4ct4fP9DPzuyU51mJqesh1aAQN8Vp6SzCEg1RmxrzRsWCsW5rbKz0XKC5FOuEzBUukXJi3wF2fCn/0+ptoBL+jVOwTqrc3vEniM1AE9SKu5t+Z3lTCO1ytOQa20F1qZ/CXwq4AyqRaPgBxnqOXM7M/mf+sY+XikO5kKfWXZq8+u9takmCwfX8l5SjOSAHdwL5wH3zfoE/o8Hhl2hStTnmIL/ELP198hjDWE3PN/h57Yjv6XHPfAb16e6wpbI6li+JO3xQsZk4fxO2BDdzLXxjN6py28vDpH6FglmNXpCDyaPiveav0mV/BYAlIeJkwJ1x5w/YkmV/AYHVDndjoCa/TEa+Czkx/18lIxhoAx0dhcLOh+Zj8R9y6TMeYI1LmdToRmCiFjCMh6wDwhsrc/jCOgmaLjCTAJATl2wIr8UFYO1CRCMnwBOD+Cqp2/U7/O5CDbALLIjQkeCX/JKbkuMZNsf7jeK7EjcWLc4GfJOKNqMgJu4qEkXde4JE7M0Nugi3ArBMTgEgPa8NkygQFkcesEXB239Fp8FrwTMPcA5sY7AXMPYG68EzD3AObGf4L8LJx8Ylq2AAAAAElFTkSuQmCC\"\n  },\n  \"tiltleft\": {\n    \"icon\": \"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAEAAAABACAYAAACqaXHeAAAACXBIWXMAAAsSAAALEgHS3X78AAAD5ElEQVR4nO1b7XWbMBS99PR/2CBM0HiDsEG9QckG3qDqBu4EpRt4g+AN6AZ4AzLB7Q89HTA1BiEJuYnvORwsIYn3rt6HJJKEJD4yPsUWIDbuBMQWIDbuBIQcPAFUAlQJsJFyKeVtyPdagaS3C2QOsgK5lXIrDwspc1BuQB5AbnzKYXN99sxnCeARQAPgIOVUygDwQ+7GKh7lKgHUCbAhUHuW6To8zPoO5EF+FyBrYwET/VJpb/pu5aFa0wJcOxe9ikmlJ8aqpFCDTP8XAlIRuHIVWsYqIfEAEidukgCQKuRMCREEuQ9NgHUalOD1HcATAOU7Jg2wCTz+YgvYBbaAdC0XSMj5u8EEyAGAQBVoPlaHrQsoAK8JsA8gSxTMJiDRCxrjk1UQaSLAygUA7QbvyQVmL4UToIBe0jaBZIkCmxhQAHiV+5pIoYNvkJQ46gLi84de1bPcT+isYM/zNj6RA9gB+NqrO0JvpVtvb5mx4htrUAfKzTnJiuOo6XH7PKdBPfLQ9x6+INlcUbyPlo6bLxsC8gsPlCelU0vFh3CWY26jfa+igfsSOBXh24WK93GggzxzG6WiOKF9dKniGfUOz4fifSyOCzYNcyzfnmYkywklKjcOlsUFFzOec+XUJjomsKImp9+n4HULqaTf2Li7WyAgZzejQ0EbUfILtVU0Ul/3yNjPVG6MqJIz44Lv7wIF9CJJoVss5XI/AXiBXsjkAP7Ib7OQesL09wIzZgZ9kvww0u4b9H4lm5TYw2ynMjNmJgvqgGRmpxKL6FuFQdvr14oFpFdm1hYtJ4K2q+JKXlKK4qQ235pdULqk+BAVNWmZ9PWNgp4J2LFTPOP5jFN+b9j58phSB3YzZMYMhYsZYqny7Ame8l8FjcmTWqlhIDTEGStqGB6KnghoeW5SQ+XNJqkY1LfUFpHJZdxnLVx0gyXfBh8kAkPuT4Pnbe9ZKlfbKyuJ0mviJzqZz3GJlYmLcldX2B7625bTK0Hf6MeoUX2szwQBEDqf/5poZw5Onifa+cYb9Kn1HjMOTpYScIs4QStdwuLEyPffB8TACTqulEs62xKQXqg7yn1tUz9Cz7jTmaQtAcOT2Rd0zK/lGkfoGa98DObiAr/RKa+cJZn3PgXP3yVcCDDn9QXC5fU3aBNXCPRBxjYL5NAfR0LDKpW54NaywKJU5oJbIcAplbkgNgFeUpkLbAnIPb3XaypzwdoWECSVuWANAoKnMheEJGC1VOaCEASsnspc4JOAaKnMBbYENBfqoqcyF9gSUELvAbbQf9d/wA2kMhcsORF6V7j/01RsAWLjTkBsAWLjTkBsAWLjwxPwF0Pxx3Dj8Xp5AAAAAElFTkSuQmCC\"\n  },\n  \"tiltright\": {\n    \"icon\": \"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAEAAAABACAYAAACqaXHeAAAACXBIWXMAAAsSAAALEgHS3X78AAAEIElEQVR4nO2a77WbRhDFf+Tk+6MD4wqsDowriFKBeRVE7oB0oFRg3IHSAelAr4KQDpQKbj7M7gHLgFj+CEnRPYejB+wuM5fZubPLiyTxf8ZPaxuwNp4ErG3A2ngSsLYBHhEUEZQRZO58765lSz53NQIiyCOoIti5Swnw0f0CbIDP/twRso/q+/NA0lUPpMT9lu5i6c4zpBwpbZwfkFKkuDFIPrM913Mc6YhUOYdSpAJpM6BvjLRv9PVjXex7SwRsGxeyiWP56DnhIupmCUDaUIf1bqrzbpzUOT/HWIs6H2NhK6TtQs/I3DOSMf2XVoENELu/Tws9Yw+8Aw6jel9hCsRLvf1GBJSMTIiR9DirwQgyQRHS5+eFbLk6IptiLxEQQsLNlMIz4Oh+NyGdHmYK+BJZUIX0e5gIcI4nEWQh64WHIcChAL4C26EdliBgiyUkuaNkwSVtYxldUtccO38tgrx3gJl1OZd00veavJWt+CrNULq21AFpT4OLa4W5DImdk0d1PzBtEJG7PnORsO+4ubtGIbTBytB3wBv9JW+JJagUC9e9OyaVyZGNdXQ2eLxpiCROZD9zIR8CP0USSYU7L3oiZ+xUGFQaT3G+CHS8SUCpesrojIjRmxzYDpII2DUaMwUSLOQ/BPb7F5MpH+4JphgvLW3/wrJ3GfIANxUOsik2DIEsp/ox5DN3L5F06HnrPultZMlp6/pkssTYhlILKMdZ1AxunHcYmZ61a8sJhWqS2u6lztGy4xnVUkQMaRSr+802nch72lUtBOSqc4Cc86lquewaJ9e8EtrbYHNm5BT4KMgutDu6Nht1E3HSTET03cwULnGXcHBGp7qsIpWMhEuEFZogoV030jC/gtB8e4naichlBPia4RIJcuMER0TXjXyUa2E4SdrLSEhUryPOkTubuqZDE0cFEtC1GgzS35F4AX4D/sY0v8Bqg9+Bfxrt/E7PEJs+EFID0L0cLoFXrHi5Bj5jRBTU64XIHX67O2irayguVYIx9vV2R3vFthTeMMdLZ0MG/DKw7yshO8MD50qs/ortluBzxqQccI4T9Rx95fs5etcYsyVWYER8whYtd40pe4IllnE/AX/OYUwAvgC/MsMLmGNTtMSWte+BbzOMNwRHLEmmWMIcjTl3hSssW78H/mBZCT1Q7/3vetpdxBLb4hVmVIIVNUsQ8YLVDSVjP4s7LPlh5IRVeAnLKcdHJtYn1/gydNMSeu1PYwU3JqFrfRssqSX0WsrRirU/jpbUyrEKEWsT4FFREzFVOZKQxrdCgEdFrRxjiUhCGt8aAR5eQmMWVo5bJaCJglpCJ5W9bbgHAjwKbFdoVgm9JwI8SvolNKg0foT/EkswBUmwVeI+pPMjEDAJ9zgFZsWTgLUNWBtPAtY2YG08CVjbgLXxH2loFxEWi9ZNAAAAAElFTkSuQmCC\"\n  },\n  \"tiltbackwards\": {\n    \"icon\": \"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAEAAAABACAYAAACqaXHeAAAACXBIWXMAAAsSAAALEgHS3X78AAACyUlEQVR4nO2Z7W3bMBCGXxX9H21gbVBngmgEb1BlgqIb2BtkgzobpBNUmaDyBHE2kCe4/iAJEQo/JRKX2nwAQbJM8o6vT8czVRERbpkv3A5wUwTgdoCbIgC3A9wUAbgd4KYIwO0AN0UAbge4KQJwO8BNEYDbAW6+BrZr5PFZGACMKQYKEaAD8CuFsYRcALQQQqyi8uwINQDe1hrJxDsSRKUvB6w2kJFNikFuPglerQAVQBXg3fG9WgFCCV0G/zsIqELa3XwEXK0AJQcEskSAVwCn1I54OMXaJKAKyQOxAjxClKBbAL8j+y7lWdrbyuukxApw1K5X1+ELbB4tbT4QmgNil8FOOlED2HnanhD2j62Bu6ztAPTadVqIyHW09JGeiM6G+4oXImo845rsDI4xB8v3MTaMh+/fYAvgT4SePwE8yesa4rn10WvtewDfIuwFFTtOFkSAjV7r9xTRbySiTvar5edQrL6rC1cbIkpaB6hffgfgR0S/O4gNlwYiZ7wk9MlLSgHO8txp93zL1qt2rZJqn8KZXHWAi3F2fgewl2cT6vs59RLjFdCopc9xNPN+KQVo5fkozxuI7TTbErfBlGAvmELflziNVSGJCDw4+h1oilKtY54kuI/oNxLRjsKS4CDb9PKzKfkNhokMpraUYRk8YArr1MvgSfozynYPMDzjlbD5d3b7nmyVq00Zio8ARa5CqNbaWyNARsFeu7F32U4dATpLSuELxLI4H6edjdXDEgGKSj7v5NnZzrklFlPRAdPLDj18TZMPpQtp9Fn2BE1vetZMHhRYT3DuCKnlbMnkG3kOSbJOfAIkeQFpQE3wjLjJbyHqhQ2EcNnfDQKisPm+1lAGHhGxQWIjRABAJJQdFpapiTlDTLxPMVioAFdL2RbndoCbIgC3A9wUAbgd4KYIwO0AN0UAbge4KQJwO8BNEYDbAW5uXoB/c4v7pl/dd2gAAAAASUVORK5CYII=\"\n  },\n  \"tiltforward\": {\n    \"icon\": \"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAEAAAABACAYAAACqaXHeAAAACXBIWXMAAAsSAAALEgHS3X78AAAC2klEQVR4nO2Y3ZHaMBRGjzN5hw5CB0sqiNMBqSCUQDogHZAKQjqgg7AVLFtB2ApiKrh5kDxoja0fY+9liM6MByMk67ufpCuZQkT4n3mnLUCbbIC2AG2yAdoCtMkGaAvQJhugLUCbbIC2AG2yAdoCtMkGaAvQJmTAFNgDckPXEZhfFbVDEfhDZA98svePnnpz4NBRNgcmPfV1cQJmQHX1k0TEd9XMPXWWto5bthWRvfPbGJQB7VFXjAF7z+9ugG7wIiLVsPFeMIgB1yTBJfCzUbYFvtr7oaf9KPQ1YIk/eHUKKAsoQ/Xe93j2ksvg4Rz8I7DjMim2McOIHMO4rdNHN4E1IvI6B/iSWiUii55rcS7pOaMzByCydgrWvr5D26BgRrSke+RrvmBGHlt3gTlH+NhhRqrCbJd74nPHZ1v/FYV5zlOj+KN0zcjIGRDaztxZsg3UbXIQkaltu0lo1zoDEDm0BHJoqyuR22DM1FzZ+gunbB9o4xpVty8j+qq5MKAx9ZtX61KIMSBFzLpRduyofxSRmfN7PYOmPfqsA5lHJJuLA12fXaCNev266+y3p/4H4I/zvW7X+4xv13iR2m6ot8GF/dwBz4ltT8DG3pcD6aEAKUwS99eT8C4QS52Vp8CKuGCOwNp+zjCjeNUuUFMHL6FZEVg2KVTNdZlwzcRk6hT69tU7B5ww+zuYvbs5UhPMuv+FWQqxr6oL+9yukf+GmRkb4CFWbDQBh1zcU95C3oaN02dzh/DOACcAb4wpSbDquB+T0ftMMWCDSXBTzll7bFact8ZtSkOBIpgASXsbfAD+pogYgAmX5/pBudt/hWPPAXdrQCxDHYVvjpj1D3kG3K8BOQdEknPA2EJunZABP95ERTrPeF6FUwgZsAK+Ay9DdDYAL5i3zXKoB4b+ELl7cg7QFqBNNkBbgDbZAG0B2mQDtAVokw3QFqBNNkBbgDbZAG0B2mQDtAVo8w/leGQvtJ6OAwAAAABJRU5ErkJggg==\"\n  }\n}","helpers.ts":"namespace Math {\n    /**\n     * Generates a `true` or `false` value randomly, just like flipping a coin.\n     */\n    //% blockId=logic_random block=\"pick random true or false\"\n    //% help=math/random-boolean weight=0\n    export function randomBoolean(): boolean {\n        return Math.randomRange(0, 1) === 1;\n    }\n}","icons.jres":"{\n  \"*\": {\n    \"namespace\": \"icons\",\n    \"dataEncoding\": \"base64\"\n  },\n  \"heart\": {\n    \"icon\": \"data:image/png;base64,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\"\n  },\n  \"smallheart\": {\n    \"icon\": \"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAMgAAADICAYAAACtWK6eAAAACXBIWXMAAAsTAAALEwEAmpwYAAAE5ElEQVR4nO3dMY5URxQF0NdGTtAQY3sB3gALsNgTJBapneA9WXbOBryAARIiRABBO5i2Ru2hLv9P9W9V9ZyT8nveVfXcgZGaelUAAADAEHbf+POrqnpaVY+r6vsTz/5SVZ+q6n1Vfbzn15BPvvtalC8V5Ieq+unEoVquq+rdytfId0u+Ps183zVecFXnC1eHWVcrnpfvmHx9mvlaBXm6XZamNTPl65sp38KZrYI83jBIy5qZ8vXNlG/hzFZBTv0L0RJrZsrXN1O+hTNbBQFKQSBSEAgUBAIFgUBBIFAQCBQEAgWBQEEgUBAIFAQCBYFAQSBQEAgUBAIFgUBBIFAQCFoF+XLWFOtnytc3U76FM1sF+bRhkJY1M+XrmynfwpmtgrzfMEjLmpny9c2Ub+HMR42HP1fVvqqebBbn2HVVfVjxvHzH5OvTzOfy6jb5+jyEfAAAAAAAAADwwEz9UZP9fv9LVb2sqmd1szb4lN5V1Zuqer3b7f6659dwfpOf37R70vf7/a9V9ds2cY5HVdWr3W73+8rXOb/DqJr4/FoFuaqqnzeL83X/1MKfhIeffH/Wt/8GPJV9VT1f8ZPQ+f1vZE16frPuSX9Z53tz6zDrxYrnnd+xac9v1j3pzzZLcZqZzq9v5jDnN+ue9FP/QrnEjyuedX53TXl+bjWBQEEgUBAIFAQCBYFAQSBQEAgUBAIFgUBBIFAQCBQEAgWBQEEgUBAIFAQCBYFAQSBQEAhm3ZO+6g6oE3m74lnnd9eU5zfrnvQ3m6U4zUzn1zdzmPObdU/667q5jOxc9oeZSzm/Y9OeX6sgH+vmOsZzua4V98sebuh7Ved5k/+7OvPvFa9xfremPr9LuLz6Rd1cSrbm3qUl3tbNPwv+mPny5cT52ZMOAAAAAAAAAOtcwkdNht3zLZ896adycXu+5bsdVfakn8TF7PmW7+7Isie92yXt+ZbvmD3pJ3BJe77l65s5zPefPenLrfn/EvLdZU86XBoFgUBBIFAQCBQEAgWBQEEgUBAIFAQCBYFAQSBQEAgUBAIFgUBBIFAQCBQEAgWBQEEgsCd9uTV7vuW7y570Tpe051u+vpnDfP/Zk77M2j3f8h2zJ73TRe35lu+IPen3dPF7vuWzJx0AAAAAAAAALsvUHzWpwfPZQz7/+zvtnvQaPJ895EemfX+n3JNeg+ezh/yrpnx/Z92TPno+e8j7Zg6Tb9Y96aPns4e8b+Yw+Wbdkz56PnvI+2YOk8+tJhAoCAQKAoGCQKAgECgIBAoCgYJAoCAQKAgECgKBgkCgIBAoCAQKAoGCQKAgECgIBAoCwax70kfPZw9538xh8s26J330fPaQ980cJt+se9JHz2cPed/MYfJNuSe9Bs9nD/kd076/Lq9uu/g97jX4+dX4+QAAAAAAAADggfFRkzb5+lxEPnvSl5Gvz7T5Wp/mvarzhavDrKsVz8t3TL4+zXz2pG8zU76+mcPksyd9m5ny9c0cJp896dvMlK9v5jD53GoCgYJAoCAQKAgECgKBgkCgIBAoCAQKAoGCQKAgECgIBAoCgYJAoCAQKAgECgKBgkCgIBDYk77NTPn6Zg6Tz570bWbK1zdzmHz2pG8zU76+mcPke9R4+HPd7N9+slmcY9dV9WHF8/Idk69PM5/Lq9vk6/MQ8gEAAADn8i9uSXT/dv6GSgAAAABJRU5ErkJggg==\"\n  },\n  \"yes\": {\n    \"icon\": \"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAMgAAADICAYAAACtWK6eAAAACXBIWXMAAAsTAAALEwEAmpwYAAAFHUlEQVR4nO3dQY5UZRQF4FsaJ6Qdoy7ADbAA455gYpjqBPdkdM4GXADCxBFhIINy0G2k0u+efsVfr/ir+L4h3e09eckRiOU7VQAAAMAUdg98/aaqHlfVo6r66sS331fVu6p6U1VvP/KfIZ98H2tVvlSQb6rquxOH6ryqqtdH/ox8/5NvTJvvi+YHbup84eru1s0R3y/fIfnGtPm6gjzeLkvrmJvyjd2Ub+XNriCPNgzSOeamfGM35Vt5syvIqf9CtMYxN+UbuynfyptdQYBSEIgUBAIFgUBBIFAQCBQEAgWBQEEgUBAIFAQCBYFAQSBQEAgUBAIFgUBBIFAQCBQEgq4g78+a4vib8o3dlG/lza4g7zYM0jnmpnxjN+VbebMryJsNg3SOuSnf2E35Vt78svnmf6pqX1Vfbxbn0Kuq+vuI75fvkHxj2nxeXt2Tb8znkA8AAAAAAAAAPjM+atKTb8xwvv1+/0NVPauqJ3U7C31Kr6vqZVW92O12v3ffZCd9HfnGHJ1vv9//VFU/bxPn8FRVPd/tdr8sfbEryE1Vfb9ZpGV/1vp/08h339Xku/ud47d6+E84p7Kvqh+Xfiexk77NTfnGbj6r85Wj7m49XfqCnfRtbso3dvPJZimOvGknfZub8o3dPPVfyNf4dukXvdUEAgWBQEEgUBAIFAQCBYFAQSBQEAgUBAIFgUBBIFAQCBQEAgWBQEEgUBAIFAQCBYFAQSCwk77NTfnGbh77jq9T+GvpF+2kb3NTvrGbLzdLceRNO+nb3JRv7OaLun2Z27ns727e0xXkbd2+LvJcXtVx72+V79BV5bt7w+HzOk9J/nv16B+LWR744alfblzyXXW+u1eQPq3bl7otvrdqwF91+8eqX9PLqwEAAAAAAACAD/moSe/q882wQ/6AT/787KSvc3X5ZtkhD6Z4fnbS17uafDPtkDemeX520re5OXu+aXbIG9M8Pzvp29ycPd80O+SNaZ6fnfRtbs6eb5od8sY0z89bTSBQEAgUBAIFgUBBIFAQCBQEAgWBQEEgUBAIFAQCBYFAQSBQEAgUBAIFgUBBIFAQCBQEAjvp29ycPd80O+SNaZ6fnfRtbs6eb5od8sY0z89O+jY3Z883zQ55Y5rnZyd9navKN9MOeWOa5+fl1b2rz3cBO+RTPz8AAAAAAAAA+PzEj5rY0bZDPuAqPqrTFsSO9gE75GMudmd+sSB2tBfZIR9zkTvz3cfd7WiP3fT8xm5Ok68riB3tsZue39jNafJ1BbGjPXbT8xu7OU0+bzWBQEEgUBAIFAQCBYFAQSBQEAgUBAIFgUBBIFAQCBQEAgWBQEEgUBAIFAQCBYFAQSBQEAi6gtjRHrvp+Y3dnCZfVxA72mM3Pb+xm9Pk6wpiR3vspuc3dnOafIsFsaN9jx3yMRe7M7/m5dV2tO2Qf4yreHk1AAAAAAAAAPChh4Ymp/5P/XbIr/6jHJ88XyrIFDvVHTvkBy52hzyYIl9XkGl2qpfYIV90kTvkjWnydf8/yDQ71Q075GM35Vt5syvINDvVDTvkYzflW3mzK8g0O9UNO+RjN+VbedNbTSBQEAgUBAIFgUBBIFAQCBQEAgWBQEEgUBAIFAQCBYFAQSBQEAgUBAIFgUBBIFAQCBQEgq4g0+xUN+yQj92Ub+XNriDT7FQ37JCP3ZRv5c2uINPsVDfskI/dlG/lza4g0+xUL7FDfs/F7pA3psl3DS+vtkN+wS+HfsDs+QAAAIBz+RdDw2v5jDe3GQAAAABJRU5ErkJggg==\"\n  },\n  \"no\": {\n    \"icon\": \"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAMgAAADICAYAAACtWK6eAAAACXBIWXMAAAsTAAALEwEAmpwYAAAFCElEQVR4nO3dMY5URxQF0NeWnCBysBfgDbAAy3uCxCK1E7wny87ZgBcAJkckBO1g2sJN/7r+f6p7VPXnnJQZ3lNNXRBSU7cKAAAAGMIh/eLxePyxql5V1Yuqen7l2X9X1duqenM4HP645+/xtKqeVdWTqvr2WoudfK6qT1X1oao+3vP3sF/HfiPcv2ZAjsfjz1X1y5WXWhxVVa8Ph8OvG7/veVV9f4N9lryruwPdwn5fbN5vlPu3GJBTcn9v/foNHKvqpw1/kzytqh9uuM+Sv2r9n4T2u7R6v5Hu3zeNb3hVD7dcnWa93PD1z261yJVm2q9v5jD3rxWQF7fbpWnLzCc32+I6M+3XN3OY+9cKyLX/QbTGdxu+9tr/oLz2TPv1zRzm/rUCApSAQCQgEAgIBAICgYBAICAQCAgEAgKBgEAgIBAICAQCAoGAQCAgEAgIBAICgYBAICAQtAKy9Y2la3i/4Ws/32yL68y0X9/MYe5fKyBvb7hIy5aZn262xXVm2q9v5jD3rxWQN3X3mNZDOZ5mrvXhVotcaab9+mYOc/8WA3J6Ye51PcyS/z79+OeG7/lYd89ZPpR3te19Wfud27TfSPdvzePVL+vuUa0t71at8b7u/lr7zePV97L7/Sa4fwAAAAAAAADwyPxfUeIMH0XQ4+787mPV+aWA6NE+jaod9rg7vzPN82sFRI/2VyNrRz3uzm/R4vm1/j+IHu1ze+txd34rZ7YCoke7b6bz65s5zPm1AqJH+9Keetyd38qZXjWBQEAgEBAIBAQCAYFAQCAQEAgEBAIBgUBAIBAQCAQEAgGBQEAgEBAIBAQCAYFAQCAQEAhaAdGjfWlPPe7Ob+XMVkD0aPfNdH59M4c5v1ZA9Gif21uPu/NbObMVED3aX+yux935XWie3x4erx65R9v57fj8AAAAAAAAAODxmfqjJjX4fnrI5//5TtuTXoPvp4f8zLQ/3yl70mvw/fSQL5ry5ztrT/ro++kh75s5zH6z9qSPvp8e8r6Zw+w3a0/66PvpIe+bOcx+XjWBQEAgEBAIBAQCAYFAQCAQEAgEBAIBgUBAIBAQCAQEAgGBQEAgEBAIBAQCAYFAQCAQEAhm7UkffT895H0zh9lv1p700ffTQ943c5j9Zu1JH30/PeR9M4fZb8qe9Bp8Pz3kF6b9+Xq8uk0PeZ/d/3wBAAAAAAAA4PGZ+qMmesidX4d996TrIT/j/PrsqyddD/ki59dnVz3pesj7Zjq/lTNn7UnXQ9430/mtnDlrT7oe8r6Zzm/lTK+aQCAgEAgIBAICgYBAICAQCAgEAgKBgEAgIBAICAQCAoGAQCAgEAgIBAICgYBAICAQCAgEs/ak6yHvm+n8Vs6ctSddD3nfTOe3cuasPel6yPtmOr+VM6fsSddDfsH59dlnT7oecufXQU86AAAAAAAAAGwWP2qiR7v7owj2m7zHvRkQPdpnNveQl/3+a9oe98WA6NFetLqHvOy3ZMoe99bH3fVo9820X9/MYe5fKyB6tPtm2q9v5jD3rxUQPdp9M+3XN3OY++dVEwgEBAIBgUBAIBAQCAQEAgGBQEAgEBAIBAQCAYFAQCAQEAgEBAIBgUBAIBAQCAQEAgGBoBUQPdp9M+3XN3OY+9cKiB7tvpn265s5zP1rBUSPdt9M+/XNHOb+LQZEj/aFTT3kZb+vTdvjvubxaj3aO30cugbfb4L7BwAAADyUfwDmcbblze7mOAAAAABJRU5ErkJggg==\"\n  },\n  \"happy\": {\n    \"icon\": \"data:image/png;base64,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\"\n  },\n  \"sad\": {\n    \"icon\": \"data:image/png;base64,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\"\n  },\n  \"confused\": {\n    \"icon\": \"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAMgAAADICAYAAACtWK6eAAAACXBIWXMAAAsTAAALEwEAmpwYAAAFd0lEQVR4nO3dMW5TWxAG4N8PvQaFmsdbABvIAhB7ShqUFpqwJwR9NsACAjRUiAKK+wob8UxyhntzbMuHfF/LdWY01u8QyZpJAAAAgKOw+s2/nyR5nORhkr93XPt7kq9JPiX5csefoT/93dWs/qqA/JPk3x031XKd5OPC1+jvJ/31afb3V+MFJzlcc9nUOlnwvP626a9Ps79WQB7vr5emJTX111dTfzNrtgLycI+NtCypqb++mvqbWbMVkF3/QTTHkpr666upv5k1WwEBIiBQEhAoCAgUBAQKAgIFAYGCgEBBQKAgIFAQECgICBQEBAoCAgUBgYKAQEFAoCAgUBAQKLQC8v2gXSyvqb++mvqbWbMVkK97bKRlSU399dXU38yarYB82mMjLUtq6q+vpv5m1nzQePhbkinJo721s+06yecFz+tvm/76NPuzvLpNf33uQ38AAAAAAAAAcM8M/VWTaZqeJTlPcpr12eBd+pjkKsnlarV6e8efYX6Dz2/YO+nTNL1I8nI/7WyXSnKxWq1eLXyd+W1KZeD5tQJykuTp3tq53fvM/CTcfPK9ye9/A+7KlOT5gk9C8/ulZAad36h30s9zuDc3m1pnC543v23Dzm/UO+mne+tiNzXNr6/m0cxv1Dvpu/6Dco4nC541v5uGnJ+tJlAQECgICBQEBAoCAgUBgYKAQEFAoCAgUBAQKAgIFAQECgICBQGBgoBAQUCgICBQEBAoCAgURr2TvmgH1I58WPCs+d005PxGvZN+tbcudlPT/PpqHs38Rr2Tfpn1MrJDmTY15zK/bcPOrxWQL1mvYzyU6yzYL7vZ0HeRw7zJP1ZnvlvwGvP7aej5/QnLq8+yXkq2ZO/SHB+y/m/B65GXL1fMz510AAAAAAAAAFhm6K+aRH/6u7s/+0569Pd/+uvT7K/1bd6THK65bGqdLHhef9v016fZ36h30vXXV1N/M2uOeiddf3019Tez5qh30vXXV1N/M2vaagIFAYGCgEBBQKAgIFAQECgICBQEBAoCAgUBgYKAQEFAoCAgUBAQKAgIFAQECgICBQGBgoBAYdQ76frrq6m/mTVHvZOuv76a+ptZc9Q76frrq6m/mTUfNB7+lvV960d7a2fbdZLPC57X3zb99Wn2Z3l1m/763If+AAAAAAAAAOCeGfqrJtM0PUtynuQ067PBu/QxyVWSy9Vq9faOP8P8Bp/fsHfSp2l6keTlftrZLpXkYrVavVr4OvPblMrA82sF5CTJ0721c7v3mflJuPnke5Pf/wbclSnJ8wWfhOb3S8kMOr9R76Sf53Bvbja1zhY8b37bhp3fqHfST/fWxW5qml9fzaOZ36h30nf9B+UcTxY8a343DTk/W02gICBQEBAoCAgUBAQKAgIFAYGCgEBBQKAgIFAQECgICBQEBAoCAgUBgYKAQEFAoCAgUBAQKIx6J33RDqgd+bDgWfO7acj5jXon/WpvXeympvn11Tya+Y16J/0y62VkhzJtas5lftuGnV8rIF+yXsd4KNdZsF92s6HvIod5k3+szny34DXm99PQ8/sTllefZb2UbMnepTk+ZP3fgtcjL1+umJ876QAAAAAAAACwTPlVE3e03SHv8EfMrxkQd7S3uEPeZ9j53RoQd7Rv5Q55nyHn1/q6uzvafTXNr6/m0cyvFRB3tPtqml9fzaOZXysg7mj31TS/vppHMz9bTaAgIFAQECgICBQEBAoCAgUBgYKAQEFAoCAgUBAQKAgIFAQECgICBQGBgoBAQUCgICBQEBAotALijnZfTfPrq3k082sFxB3tvprm11fzaObXCog72n01za+v5tHM79aAuKN9gzvkfYad35zl1e5ou0N+F/dhfgAAAMCh/AecHIXJK5h09QAAAABJRU5ErkJggg==\"\n  },\n  \"angry\": {\n    \"icon\": \"data:image/png;base64,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\"\n  },\n  \"asleep\": {\n    \"icon\": \"data:image/png;base64,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\"\n  },\n  \"surprised\": {\n    \"icon\": \"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAMgAAADICAYAAACtWK6eAAAACXBIWXMAAAsTAAALEwEAmpwYAAAFc0lEQVR4nO3dP25UVxQG8G8SpUFODWQBbMALiNiT3SC30Jg9Iei9ARbAnyYVogjFpJhBycR+h/d8543uNb9fmzHn07E+EyTrngQAAADowuYH//0syeMkj5L8duTZ35J8TfI5yZf7/AHb7fbPJJdJzpM8OV60JMmnJDdJrjebzdt7/hn2N/j+qoI8SfLHkUNN+ZDdQmfbbrcvkrxcJ87hqCRXm83m1cKvs7/9qAy8v6mCnCV5tlqcu73PzJ+E+598b/LjvwGPZZvk+YKfhPb3v5EZdH+/THz48bpZmmde5nTf3OxnXSz4vP0dGnZ/UwV5tGKQKUtmnq+W4jgz7a9tZjf7myrIsf9BNMeSmcf+B+UcTxd81v5uG3J/UwUBoiBQUhAoKAgUFAQKCgIFBYGCgkBBQaCgIFBQECgoCBQUBAoKAgUFgYKCQEFBoKAgUFAQKEwV5NtJUyyfuegNqCP5uOCz9nfbkPubKsjXFYNMWTLzZrUUx5lpf20zu9nfVEE+rxhkypKZ19k9RnYq2/3Muezv0LD7myrIl+yeYzyVD1nwvuz+hb6rnOab/P3pzHcLvsb+/jX0/h7C49UX2T1KtuTdpTk+Zve/Ba9Hfny5Yn9t+wMAAAAAAACAn8/Qv2oS+eS7v4d9Jz3y/Zd8bSbzTf0271lOFy77WWcLPi/fIfnaTOYb9U66fG0z5Zs5c9Q76fK1zZRv5sxR76TL1zZTvpkzvWoCBQWBgoJAQUGgoCBQUBAoKAgUFAQKCgIFBYGCgkBBQaCgIFBQECgoCBQUBAoKAgUFgYKCQGHUO+nytc2Ub+bMUe+ky9c2U76ZM0e9ky5f20z5Zs78deLDf2d33/r31eIc+pDkrwWfl++QfG0m83m8epp8bX6GfAAAAAAAAADwk/GrJtOa82232z+TXCY5z+6s8TF9SnKT5Hqz2by955/R9f7SQT530udZnG+73b5I8nKdOIejklxtNptXC7+u6/2lk3xTBTlL8my1OHd7n/k/abrOt/+b401+/Df0sWyTPF/wN0nX+0tH+dxJX2fmZU5XjuxnXSz4fO/76yafO+nrzDxfLcVxZva+v27yuZO+zsxj/4N8jqcLPtv7/rrJ51UTKCgIFBQECgoCBQWBgoJAQUGgoCBQUBAoKAgUFAQKCgIFBYGCgkBBQaCgIFBQECgoCBQUBArupK8zc+kbUMfwccFne99fN/ncSV9n5s1qKY4zs/f9dZPPnfR1Zl5n95jbqWz3M+fqfX/d5JsqyJfsnmM8lQ9Z9n5r1/n2Lxxe5TQl+f706LsFX9P1/tJRPo9XTzvW49UX2T3qtuTdqjk+Zve/Va89Xn0v7qQDAAAAAAAAwGJD/6qJO+T21+Bh30l3h/yA/bV5WHfS3SG/k/21eVB30t0hb5tpfzNnjnon3R3ytpn2N3PmqHfS3SFvm2l/M2d61QQKCgIFBYGCgkBBQaCgIFBQECgoCBQUBAoKAgUFgYKCQEFBoKAgUFAQKCgIFBQECgoCBQWBwqh30t0hb5tpfzNnjnon3R3ytpn2N3PmqHfS3SFvm2l/M2cOeSfdHfJb7K/Nw7yT7g65/TVwJx0AAAAAAAAAFhv6V03SeT53yMf//g57Jz2d53OH/MCw398h76Sn83zukN9pyO/vqHfSe8/nDnnbzG7yjXonvfd87pC3zewm36h30nvP5w5528xu8nnVBAoKAgUFgYKCQEFBoKAgUFAQKCgIFBQECgoCBQWBgoJAQUGgoCBQUBAoKAgUFAQKCgIFBYHCqHfSe8/nDnnbzG7yjXonvfd87pC3zewm36h30nvP5w5528xu8g15Jz2d53OH/JZhv78er57mDnmbB//9BQAAAE7oHzt4fMP9uDtRAAAAAElFTkSuQmCC\"\n  },\n  \"silly\": {\n    \"icon\": \"data:image/png;base64,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\"\n  },\n  \"fabulous\": {\n    \"icon\": \"data:image/png;base64,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\"\n  },\n  \"meh\": {\n    \"icon\": \"data:image/png;base64,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\"\n  },\n  \"tshirt\": {\n    \"icon\": \"data:image/png;base64,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\"\n  },\n  \"rollerskate\": {\n    \"icon\": \"data:image/png;base64,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\"\n  },\n  \"duck\": {\n    \"icon\": \"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAMgAAADICAYAAACtWK6eAAAACXBIWXMAAAsTAAALEwEAmpwYAAAFW0lEQVR4nO3dMXIcVRQF0DdQJC4R27AAFoAXQLEnO6GcQmL2REFuFsACZJwQuRzgYAhGYKZm/tP/+t1Tr0fnpG7p36ruK1tlqW8EAAAAUMLunj+/iYinEfEkIr5Y+OyPEfEhIt5FxPuHfIL9fv9dRLyMiOcR8Wy5aBER8WdEvImI17vd7teHfILq+aL4/Y0C+bKCPIuIrxcO1XIbhxvebb/f/xARP64T5/ioiHi12+1+Gvqg4vmi+P2NIvlaBbmJiG9Wi3PeH9H5lebuK/Mvcf/fgEvZR8T3vV+pq+eL4vc3CuX7rHHx03WzTJ/5Mi738MXdWS8Grq+er/r9LZOvVZAnKwZpGTnz+Wopljmzer7q97dMvlZBlv6GqMfImUt/w9vjq4Frq+erfn/L5GsVBAgFgZSCQEJBIKEgkFAQSCgIJBQEEgoCCQWBhIJAQkEgoSCQUBBIKAgkFAQSCgIJBYGEgkCiVZCPF00xfuboO5aW8Hbg2ur5qt/fMvlaBfmwYpCWkTPfrJZimTOr56t+f8vkaxXk3YpBWkbOfB2Hl6Vdyv7uzF7V81W/v2XytQryPg6vY7yU2xh4f+vdGwRfxWUewn9f7flb7wdUzxfF728UyncNL69+EYeXpo28F6rH2zj8s+XnyZdXl80Xxe9v1M8HAAAAAAAAAI9M+qMm1Xe+5bOTPmFuJ736zrd8n44KO+mzxnbSq+98y3d6ZNhJnzW0k15951u+Y3bS5w3tpFff+ZZv7swyO+QLXLuUoZ306jvf8p2ykz7HTjqMUhBIKAgkFAQSCgIJBYGEgkBCQSChIJBQEEgoCCQUBBIKAgkFgYSCQEJBIKEgkFAQSCgIJFoFqb7zLd8pO+lzhnbSq+98yzd3Zpkd8gWuXcrQTnr1nW/5jtlJn9e/k15951u+I3bS5z1sJ736zrd8dtIn2EkHAAAAAAAAgGH3DU2W/q/+6jvk8m0/X1aQEjvVLdV3yOX7dFRsOF+rIGV2qs+pvkMu3+mRsdF8rd8HKbNT3VB9h1y+Y5vN1ypImZ3qhuo75PLNnVkmX6ul364YJPN7z0X7/f6Sv633n91u1/VVTb7ztpjPW00goSCQUBBIKAgkFAQSCgIJBYGEgkBCQSChIJBQEEgoCCQUBBIKAgkFgYSCQEJBIKEgkFAQSLQKUmanuqH6Drl8pzaZr1WQMjvVDdV3yOWbO7NMvlZByuxUN1TfIZfv2GbztQpSZqf6nOo75PId2XS+a3h5ddkdcvmuOx8AAAAAAAAAPD7X8KMmdr6vNF8UeP7spHccFRve+W5+UPF8UeT5s5PeZ7M732cvLp4vCj1/dtL7bHbnu6F6vjLPn530dc6Ub+7MMs9fqyBLf0PUY+TMpb+h7DHy+wjynRrJV+b581YTSCgIJBQEEgoCCQWBhIJAQkEgoSCQUBBIKAgkFAQSCgIJBYGEgkBCQSChIJBQEEgoCCQUBBJ20vttcue7oXq+Ms+fnfR1zpRv7swyz5+d9D6b3fluqJ6vzPNnJ/1+m975Pqd6vij0/F3Dy6vL7mjLN71DXvr5AwAAAAAAAIDHZ9M/ahLyyfdw172THvL9n3xzmvlaP817E5cLF3dn3QxcL98x+eY08211J12+uTPl6zxzqzvp8s2dKV/nmVvdSZdv7kz5Os/0VhNIKAgkFAQSCgIJBYGEgkBCQSChIJBQEEgoCCQUBBIKAgkFgYSCQEJBIKEgkFAQSCgIJBQEElvdSZdv7kz5Os/c6k66fHNnytd55lZ30uWbO1O+zjM/b1z8dxz2rb9cLc6x24j4a+B6+Y7JN6eZz8ur2+Sb8xjyAQAAAJfyD92s8bBtlgWFAAAAAElFTkSuQmCC\"\n  },\n  \"house\": {\n    \"icon\": \"data:image/png;base64,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\"\n  },\n  \"tortoise\": {\n    \"icon\": \"data:image/png;base64,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\"\n  },\n  \"butterfly\": {\n    \"icon\": \"data:image/png;base64,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\"\n  },\n  \"stickfigure\": {\n    \"icon\": \"data:image/png;base64,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\"\n  },\n  \"ghost\": {\n    \"icon\": \"data:image/png;base64,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\"\n  },\n  \"sword\": {\n    \"icon\": \"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAMgAAADICAYAAACtWK6eAAAACXBIWXMAAAsTAAALEwEAmpwYAAAE40lEQVR4nO3dMY4UVxQF0NeWnCBysBfgDbAAy3uCBJHaCd6TZedswAsAkyMSgnYwY1mjoS5V86ta7/eckzLwrrq4HiON6lYBAAAALZy+8etPq+pZVT2pqu93vv2lqj5X1ceq+vTAP6N1vvP5/HNVvaqqF1X1fL9oVVX1T1W9q6q3p9Ppzwf+Ga0/v2qQLxXkeVX9uHOoJe/r5oFv0Trf+Xx+XVW/HhPn7qmqenM6nX7b+Ptaf37VJN9SQZ5W1U+Hxfm6v2v9f2la57v9zvFHffs79F7OVfXLhu8krT+/apTvu4UvfnZsluGb3fO9qsuVo25vvdzw9d0/vzb5lgry5MAgS7bc7J7vxWEp9rnZ/fNrk2+pIHv/g2iNLTe759v7H+Rr/LDha7t/fm3yLRUEKAWBSEEgUBAIFAQCBYFAQSBQEAgUBAIFgUBBIFAQCBQEAgWBQEEgUBAIFAQCBYFAQSBYKsiXi6bYfrN7vq3vgNrDhw1f2/3za5NvqSCfDwyyZMvN7vneHZZin5vdP782+ZYK8vHAIEu23Oye723dvMztUs63N9fq/vm1ybdUkE918zrGS3lf297f2jrf7RsO39RlSvLfq0f/2vB7Wn9+1Sifl1cv2+vl1S/r5qVuW95btcaHuvnfqt+9vPpB9sgHAAAAAAAAAI+MHzVZZid9zFU8Xzvp69hJHzPt87WTvp6d9DFTPl876cfctJM+drNNPjvpx9y0kz52s00+O+nH3LSTPnazTT5vNYFAQSBQEAgUBAIFgUBBIFAQCBQEAgWBQEEgUBAIFAQCBYFAQSBQEAgUBAIFgUBBIFAQCOykH3PTTvrYzTb57KQfc9NO+tjNNvnspB9z00762M02+eykr2Mnfcy0z9fLq5fZSR9z9c8XAAAAAAAAAB4fP2qyzE76mKt4vnbS17GTPmba52snfT076WOmfL520o+5aSd97GabfHbSj7lpJ33sZpt8dtKPuWknfexmm3zeagKBgkCgIBAoCAQKAoGCQKAgECgIBAoCgYJAoCAQKAgECgKBgkCgIBAoCAQKAoGCQKAgENhJP+amnfSxm23y2Uk/5qad9LGbbfLZST/mpp30sZtt8tlJX8dO+phpn6+XVy+zkz7m6p8vAAAAAAAAADw+U/+oSfcdcvnm33Gfdie9+w65fP+fqol33KfcSe++Qy7f/ZM16Y77rDvp3XfI5btr2h33WXfSu++Qyzd2s83fv1l30rvvkMt335Q77t5qAoGCQKAgECgIBAoCgYJAoCAQKAgECgKBgkCgIBAoCAQKAoGCQKAgECgIBAoCgYJAoCAQzLqT3n2HXL77ptxxn3UnvfsOuXxjN9v8/Zt1J737Drl8d0274z7lTnr3HXL57ph6x/0aXl7ddodcvqvfcQcAAAAAAACAR2bqHzWp5vnskM//fKfdSa/m+eyQ3zHt851yJ72a57ND/lVTPt9Zd9K757NDPnazTb5Zd9K757NDPnazTb5Zd9K757NDPnazTT5vNYFAQSBQEAgUBAIFgUBBIFAQCBQEAgWBQEEgUBAIFAQCBYFAQSBQEAgUBAIFgUBBIFAQCGbdSe+ezw752M02+WbdSe+ezw752M02+WbdSe+ezw752M02+abcSa/m+eyQ3zPt8/Xy6mVXv+NezT+/6p8PAAAAuJR/ATEXlVHvyECcAAAAAElFTkSuQmCC\"\n  },\n  \"giraffe\": {\n    \"icon\": \"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAMgAAADICAYAAACtWK6eAAAACXBIWXMAAAsTAAALEwEAmpwYAAAE+UlEQVR4nO3dPY4cVRQF4NtIJBY5PwtgA14AYk92gpxCYvaEIPcGWICNc+TEQRP0IGs09U6/mqqy3+v5vtRj36PSnBEW7TpVAAAAwBBO6RfP5/NPVfWyqp5X1Xc73/6nqt5U1evT6fTnY/6A0fNV1TdV9W1VPauqr/cKdudjVX2oqvdV9e8j/wz5ruRrFuR8Pv9SVb/uHGrxVFW9Op1Ov636TYPnq0thfzggz5K3dSn0GvJ90sy3WJC7n8x/tH79AOeq+rn3J/Xo+eryk+/HA/Ms+bv6f1LL99Bivq8aX/yyPt83X93derHi60fP9+1RQXa6KV/nzVZBnh8YpGXNzdHzPTssxT435eu82SrI3n/h7fH9iq8dPd/ef6Hc+6Z8nTdbBQFKQSBSEAgUBAIFgUBBIFAQCBQEAgWBQEEgUBAIFAQCBYFAQSBQEAgUBAIFgUBBIFAQCFoFWfsOoz28W/G1o+f7eFiKfW7K13mzVZA3BwZpWXNz9HwfDkuxz035Om+2CvK6Li9L+1zOdzd7jZ7v/VFBdropX+fNxYLcvUHwVX2eb8L/X+35V+9vGD1fXd7Q9/agPEve1rr338p3XzNfz8urX9TlpWlr3gvV411d/rPl940vrx42Xw3w8uUr5NuWDwAAAAAAAACemGtDmEP/r3476Tf/UY4vni8VZIid6hY76fdMu0MeDJGvVZBhdqqX2ElfNOUOecMw+Vr/HmSYneoGO+nbbsrXebNVkGF2qhvspG+7KV/nzVZBhtmpbrCTvu2mfJ03vdUEAgWBQEEgUBAIFAQCBYFAQSBQEAgUBAIFgUBBIFAQCBQEAgWBQEEgUBAIFAQCBYFAQSBoFWSYneoGO+nbbsrXebNVkGF2qhvspG+7KV/nzVZBhtmpbrCTvu2mfJ03WwUZZqd6iZ30B6bdIW8YJt8tvLzaTvrEL4e+YvR8AAAAAAAAAPDE3MJHTeyk3+5HOb54PjvpHafKTvpW0+azk97HTvp2U+azk97HTvp2U+azk37MzdGfn3ydN+2k97OTvs2U+bzVBAIFgUBBIFAQCBQEAgWBQEEgUBAIFAQCBYFAQSBQEAgUBAIFgUBBIFAQCBQEAgWBQEEgsJPez076NlPms5N+zM3Rn598nTftpPexk77dlPnspF9nJ327afPdwsur7aRP/HLoK0bPBwAAAAAAAABPzC181GTYnXT55t+Zt5PecaoesZMu36dTNfHOvJ30Pqt20uV7eLIm3Zm3k95n7U66fPdNuzNvJ/2Ym/JtuznM95+d9H5r/r2JfA9NuTPvrSYQKAgECgKBgkCgIBAoCAQKAoGCQKAgECgIBAoCgYJAoCAQKAgECgKBgkCgIBAoCAQKAoGd9H5rdtLle2jKnXk76cfclG/bzWG+/+yk91m7ky7ffdPuzNtJv271Trp890y9M38LL68ediddvpvfmQcAAAAAAACAJ+YWPmpi59vzeww76TuZeue7xfO7x076RtPufC/x/BbZSd9g2p3vBs+v86ad9GNuen7bbg7z/Oyk95ty57vB8+u86a0mECgIBAoCgYJAoCAQKAgECgKBgkCgIBAoCAQKAoGCQKAgECgIBAoCgYJAoCAQKAgECgKBnfR+U+58N3h+nTftpB9z0/PbdnOY52cnvc+0O98Nnl/nTTvp1029873E83vATvoj3PzOt+dnJx0AAACm8R/nWLbllDXkpAAAAABJRU5ErkJggg==\"\n  },\n  \"skull\": {\n    \"icon\": \"data:image/png;base64,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\"\n  },\n  \"umbrella\": {\n    \"icon\": \"data:image/png;base64,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\"\n  },\n  \"snake\": {\n    \"icon\": \"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAMgAAADICAYAAACtWK6eAAAACXBIWXMAAAsTAAALEwEAmpwYAAAFE0lEQVR4nO3dMY5bVRQG4GMQTTTUARbAAsgCIvaUNCgtNGFPCPqwABYwIQ1VlCIpTGHDYOx75r6571nnvfm+djxzfl35t8aSfU8EAAAAUMIu++F+v38eES8j4llEfDXz7D8j4k1EvN7tdr8+5A9UzxcRNxHxNCKeRMQXcwU7+hQRHyLiXUS8f+DfkO+efM2C7Pf7HyLix5lDXRwVEa92u91Pk36peL44FPabBfJcchuHQk8h351mvosFOb4y/9L6+QL2EfF97yt19XxxeOX7dsE8l/wR/a/U8p27mO+zxoNfxvWefHGc9WLC46vne7pUkJlmytc5s1WQZwsGaZkys3q+J4ulmGemfJ0zWwWZ+w1vj68nPLZ6vrnfUM49U77Oma2CAKEgkFIQSCgIJBQEEgoCCQWBhIJAQkEgoSCQUBBIKAgkFAQSCgIJBYGEgkBCQSChIJBQEEi0CjL1DqM5vJ3w2Or5Pi2WYp6Z8nXObBXkzYJBWqbMrJ7vw2Ip5pkpX+fMVkFex+GytGvZH2f2qp7v3VJBZpopX+fMiwU53iD4Kq7zJPznas/fen+her443NB3u1CeS25j2v238p1q5uu5vPpFHC5Nm3IvVI+3cfi35efBy6vL5osCly/fQ76xfAAAAAAAAADwyNiT3rb5PenVz69CPnvSO0bFBvekVz+/KvnsSe+zqT3p1c+vUj570vtsbU969fMrk8+e9GVmltnz3VD9/Mrka/2Ldc1v6/1rt9t1vWpUzxcR3y0apO33ngdVP79K+dxqAgkFgYSCQEJBIKEgkFAQSCgIJBQEEgoCCQWBhIJAQkEgoSCQUBBIKAgkFAQSCgIJBYGEgkDCnvR+W9qTXv38yuSzJ32ZmWX2fDdUP78y+exJ77O1PenVz69MPnvS77e5PenVz69SPnvS2za/J736+VXPBwAAAAAAAACPz30rsdbwUYmye77D+a3+/LKC2PN9HBX2pI9Y9fm1CmLP9/9Ghj3pI1Z7fq3vg9jzfcqe9DGrPb9WQez5Hpvp/MZmljm/VkHmfkPUY8rMud9Q9pjyfQTnd26V5+dWE0goCCQUBBIKAgkFgYSCQEJBIKEgkFAQSCgIJBQEEgoCCQWBhIJAQkEgoSCQUBBIKAgkFAQSrYLY833OnvQxqzy/VkHs+R6b6fzGZpY5v1ZB7Pk+ZU/6mNWeX6sg9nzfsSd9zKrPbwuXV1feo+38Nnx+AAAAAAAAAPD4bOGjJmX3fMtnT/pcNrfnW767UWFP+iw2s+dbvvORYU/6sC3t+ZbvlD3pM9jSnm/5xmaWef7Zk95vyvcl5DtnTzpsjYJAQkEgoSCQUBBIKAgkFAQSCgIJBYGEgkBCQSChIJBQEEgoCCQUBBIKAgkFgYSCQEJBIGFPer8pe77lO2dP+qAt7fmWb2xmmeefPel9pu75lu+UPemDNrXnW74T9qQ/0Ob3fMtnTzoAAAAAAAAAbMuqP2oS8sn3cNvekx7y/Zd8Y5r5Wp/mvYnrhYvjrJsJj5fvlHxjmvnWuiddvrGZ8nXOXOuedPnGZsrXOXOte9LlG5spX+dMt5pAQkEgoSCQUBBIKAgkFAQSCgIJBYGEgkBCQSChIJBQEEgoCCQUBBIKAgkFgYSCQEJBIKEgkFjrnnT5xmbK1zlzrXvS5RubKV/nzLXuSZdvbKZ8nTM/bzz4Yxz2W3+5WJxTtxHx14THy3dKvjHNfC6vbpNvzGPIBwAAAFzL3/Yj4OZvgj/VAAAAAElFTkSuQmCC\"\n  },\n  \"rabbit\": {\n    \"icon\": \"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAMgAAADICAYAAACtWK6eAAAACXBIWXMAAAsTAAALEwEAmpwYAAAE50lEQVR4nO3dTW4UVxQF4FuRMkHMIVlAFgALiLInmERMkwnZU5TMYQFZAD9zxIRBZ2AH3O5+J1V+Va3Xpe8bGtv36prTsiW7ThUAAAAwhCn94+Fw+LmqXlbV86p6uvLsD1X1pqpeT9P01wM/x+OqelJVj6rq+7UWu/Wlqj5X1ceq+vSQT+B+fferAfZrBuRwOPxaVb+tvNTZUVX1apqm3xd+3NOq+nGDfc55Vzf/IWdzvyOL71eD7Hc2ILevfH+2/n0Dh6r6ZcEr4eOq+mnDfc75p2a+ErrfWbPvVwPt913jnV/W5b64dTvrxYL3f7LVIivNdL++mcPs1wrI8w0XaVky89FmW6wz0/36Zg6zXysga/9AOccPC9537R/Y1p7pfn0zh9mvFRCgBAQiAYFAQCAQEAgEBAIBgUBAIBAQCAQEAgGBQEAgEBAIBAQCAYFAQCAQEAgEBAIBgaAVkKXPMFrD+wXv+2WzLdaZ6X59M4fZrxWQNxsu0rJk5ufNtlhnpvv1zRxmv1ZAXtfNw8gu5XA7c66PWy2y0kz365s5zH5nA3L7hL5XdZkv8n+Pzvx7wcd8qpvHRV7Ku1rwfFn3O7HofjXQfnMeXv2ibh5KtuS5S3O8r5tvC/7Y68OX3e/6H14NAAAAAAAAANylJ71NT3qfXfyqiZ70efSk99GT3mlXPd/ud5ae9A576/l2v76Zw+ynJ32bme7XN3OY/fSkbzPT/fpmDrOfp5pAICAQCAgEAgKBgEAgIBAICAQCAoGAQCAgEAgIBAICgYBAICAQCAgEAgKBgEAgIBAICAR60reZ6X59M4fZT0/6NjPdr2/mMPvpSd9mpvv1zRxmPz3p8+hJ76Mn/QF23/Ptftf/8GoAAAAAAAAA4K6r7km33773qwF+1eRqe9Lt921U7XC/0pN+PLIW9Hzb73Rk7Wi/0pN+YmnPt/2O7W0/PemdM+3XN3P0/YbpSW99i3XJv4b7apqmWa9q9jtvL/tV1bNNF2l7e/8NnmoCgYBAICAQCAgEAgKBgEAgIBAICAQCAoGAQCAgEAgIBAICgYBAICAQCAgEAgKBgEAgIBBca0+6/U7taT896Z0z7dc3c/T99KTfs7Tn237H9rafnvQ7Fvd82+/I7vYrPelVtULPt/32vV8N8PBqAAAAAAAAAOAuPeltu+j5TtxPT/oarrrnu8X9juhJ73S1Pd/nuN9ZetI7XG3Pd4P7zZypJ32bmcP0fDe438yZrYCs/QPbHEv+HmH0/db+gXLtme43c6anmkAgIBAICAQCAoGAQCAgEAgIBAICgYBAICAQCAgEAgKBgEAgIBAICAQCAoGAQCAgEAgIBHrS57vKnu8G95s5U0/6NjOH6flucL+ZM/Wkz3O1Pd8N7jdzpp70/3fVPd/nuN8JPekPsPueb/fTkw4AAAAAAAAAy+hJb7NfHz3pK9llT7r9vo0qPenddtWTbr/TkaUnvcveetLtd0xP+gr21JNuv76Zw/Skt77FuuRfm301TdOsVzX7nbeX/arq2aaLtL29/wZPNYFAQCAQEAgEBAIBgUBAIBAQCAQEAgGBQEAgEBAIBAQCAYFAQCAQEAgEBAIBgUBAIBAQCPSkz2e/PnrSO+2pJ91+fTP1pN+zt550+x3Tk95hdz3p9juiJ/2Bdt+Tbj896QAAAMBK/gVsdTwSu+HRwQAAAABJRU5ErkJggg==\"\n  },\n  \"cow\": {\n    \"icon\": \"data:image/png;base64,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\"\n  },\n  \"quarternote\": {\n    \"icon\": \"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAMgAAADICAYAAACtWK6eAAAACXBIWXMAAAsTAAALEwEAmpwYAAAE8ElEQVR4nO3dQY4VZRQF4PtMnBDmoAtwAyzAuCeYEKY6wT0ZnbMBFwAyJ0wYPAfdxnTaOl3V/1/P+4rvm1pwT97LAUk6daoAAACAFk4P/PenVfWsqp5U1beTb3+pqs9V9bGqPj3y92id73w+/1hVr6rqRVU9nxetqqr+qqp3VfX2dDr9/sjfo/XnVw3ypYI8r6rvJ4da8r5uvvAtWuc7n8+vq+rnfeLcPVVVb06n0y8bf13rz6+a5FsqyNOq+mG3OP/tz1r/J03rfLd/c/xWD/8NPcu5qn7a8DdJ68+vGuX7ZuHhZ/tmGb7ZPd+rulw56vbWyw3Pd//82uRbKsiTHYMs2XKze74Xu6WYc7P759cm31JBZv+DaI0tN7vnm/0P8jW+2/Bs98+vTb6lggClIBApCAQKAoGCQKAgECgIBAoCgYJAoCAQKAgECgKBgkCgIBAoCAQKAoGCQKAgECgIBEsF+XLRFNtvds+39R1QM3zY8Gz3z69NvqWCfN4xyJItN7vne7dbijk3u39+bfItFeTjjkGWbLnZPd/bunmZ26Wcb2+u1f3za5NvqSCf6uZ1jJfyvra9v7V1vts3HL6py5Tkn1eP/rHh17T+/KpRPi+vXjbr5dUv6+alblveW7XGh7r536pfvbz6UWbkAwAAAAAAAICvjB81WWYnfcwhvl876evYSR9ztd+vnfT17KSPucrv1076PjftpI/dbJPPTvo+N+2kj91sk89O+j437aSP3WyTz1tNIFAQCBQEAgWBQEEgUBAIFAQCBYFAQSBQEAgUBAIFgUBBIFAQCBQEAgWBQEEgUBAIFAQCO+n73LSTPnazTT476fvctJM+drNNPjvp+9y0kz52s00+O+nr2Ekfc7Xfr5dXL7OTPubw3y8AAAAAAAAAfH38qMkyO+ljDvH92klfx076mKv9fu2kr2cnfcxVfr920ve5aSd97GabfHbS97lpJ33sZpt8dtL3uWknfexmm3zeagKBgkCgIBAoCAQKAoGCQKAgECgIBAoCgYJAoCAQKAgECgKBgkCgIBAoCAQKAoGCQKAgENhJ3+emnfSxm23y2Unf56ad9LGbbfLZSd/npp30sZtt8tlJX8dO+pir/X69vHqZnfQxh/9+AQAAAAAAAODrE3/UpPvOt3x20geM7aR33/mW799TZSd91Lad9O473/LdP1l20kdt2knvvvMt31120sdt2knvvvMt39jNNjvkE56dZdNOevedb/nus5M+xk46bKUgECgIBAoCgYJAoCAQKAgECgKBgkCgIBAoCAQKAoGCQKAgECgIBAoCgYJAoCAQKAgESwXpvvMt33120sds2knvvvMt39jNNjvkE56dZdNOevedb/nuspM+bv1Oevedb/nusJM+7nE76d13vuWzkz7ATjoAAAAAAAAAbGYnfdnh81X/H+X43/PZSV9xqg6Yr5rskAct8tlJX+dQ+arRDvmCNvnspK9ztHxtdsgnPDuLnfRBR8rXZod8wrOz2EkfdKR8bXbIJzw7i5102EpBIFAQCBQEAgWBQEEgUBAIFAQCBYFAQSBQEAgUBAIFgUBBIFAQCBQEAgWBQEEgUBAI7KSvd6R8bXbIJzw7i530QUfK12aHfMKzs9hJH3C0fG12yCc8O4ud9Ec6XL5qtEO+oE0+O+nLDp+vGrwc+gHd8wEAAACX8jdzZLbl0C/0iwAAAABJRU5ErkJggg==\"\n  },\n  \"eighthnote\": {\n    \"icon\": \"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAMgAAADICAYAAACtWK6eAAAACXBIWXMAAAsTAAALEwEAmpwYAAAFM0lEQVR4nO3dQY4VVRgF4P+ZOCHMQRfgBliAcU8wMUx1gnsyOmcDLgBkTpgweA66JXa6799V/W61J5fvm1pwT27lgCSdOlUAAABAhNM9//1pVT2rqidV9e3ksz9X1aeq+lBVHx/4e0TnO5/PP1bVq6p6UVXP50Wrqqq/q+ptVb05nU5/PPD3iL6/CsjXFeR5VX0/OdTIu7p64XtE5zufzz9X1S/HxLl5VFW9Pp1Ov+78ddH3VyH5RgV5WlU/HBbnbn/V9j9povNd/83xe93/N/Qs56r6acffJNH3V0H5vhk8/OzYLBefmZ7vVT1eOer6rJc7nk+/v5h8o4I8OTDIyJ4z0/O9OCzFnDPT7y8m36ggs/9BtMWeM9Pzzf4H+Rbf7Xg2/f5i8o0KApSCQEtBoKEg0FAQaCgINBQEGgoCDQWBhoJAQ0GgoSDQUBBoKAg0FAQaCgINBYGGgkBDQaAxKsjnR02x/8z0fHu/ATXD+x3Ppt9fTL5RQT4dGGRkz5np+d4elmLOmen3F5NvVJAPBwYZ2XNmer43dfUxt8dyvj5zq/T7i8k3KsjHuvoc42N5V/u+3xqd7/oLh6/rcUry76dH/9zxa6Lvr4Ly+Xj12KyPV7+sq4+67flu1Rbv6+p/q37z8eoHmZEPAAAAAAAAAL4yftRkbPmd9PR8FfB+7aRvs9xOenq+Cnm/dtK3W2YnPT1fBb1fO+nHnJm+k56eL+b92kk/5sz0nfT0fDHv1076MWem76Sn54t5v75qAg0FgYaCQENBoKEg0FAQaCgINBQEGgoCDQWBhoJAQ0GgoSDQUBBoKAg0FAQaCgINBYGGgkDDTvoxZ6bvpKfni3m/dtKPOTN9Jz09X8z7tZN+zJnpO+np+WLer530bZbaSU/PV0Hv18erx5bfSU/PV+HvFwAAAAAAAAC+Pn7UZGz5nfRyf/fen530bZbbSS/39+Woau7PTvp2y+ykl/u7dWQN7s9O+jFn2iG/7MyY+7OTfsyZdsgvOzPm/uykH3OmHfLLzoy5P181gYaCQENBoKEg0FAQaCgINBQEGgoCDQWBhoJAQ0GgoSDQUBBoKAg0FAQaCgINBYGGgkBDQaBhJ/2YM+2QX3ZmzP3ZST/mTDvkl50Zc3920o850w75ZWfG3J+d9G2W2kkv9/df7f35ePXY8jvp5f4uvT8AAAAAAAAA+Mq0P2qSsFPdkW/tnfQKyDcsSMpO9fAXyfflqFpwJ71C8t1ZkKSd6jsflu/WkbXQTnoF5Rv9uHvMTvWAfDettpMek29UkJid6gnPzrJSvvSd9Jh8o4LE7FQPyHfbSjvpMfl81QQaCgINBYGGgkBDQaChINBQEGgoCDQUBBoKAg0FgYaCQENBoKEg0FAQaCgINBQEGgoCDQWBxqggMTvVA/LdttJOeky+UUFidqonPDvLSvnSd9Jj8o0KErNTPSDfTavtpMfku7MgSTvVd5HvhuV20iso35aPV8fuVMu39k565ecDAAAAAAAAgK+MnfSx5fNV/o9y/O/57KRvOKoWzFchO+SNiHx20rdZKl8F7ZAPxOSzk77NavlidsgnPDuLnfQLrZQvZod8wrOz2Em/0Er5YnbIJzw7i5102EtBoKEg0FAQaCgINBQEGgoCDQWBhoJAQ0GgoSDQUBBoKAg0FAQaCgINBYGGgkBDQaChINCwk77dSvlidsgnPDuLnfQLrZQvZod8wrOz2Em/wGr5YnbIJzw7i530B1ouXwXtkA/E5LOTPrZ8vgr4OPQ90vMBAAAAj+Uf73PYeRwCFc4AAAAASUVORK5CYII=\"\n  },\n  \"pitchfork\": {\n    \"icon\": \"data:image/png;base64,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\"\n  },\n  \"target\": {\n    \"icon\": \"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAMgAAADICAYAAACtWK6eAAAACXBIWXMAAAsTAAALEwEAmpwYAAAFeElEQVR4nO3dMY5bVRgF4N9INFH6BBbAAsgCEHtKGpQWmrAnBH1YAAtISB+lSWGKGYiMff/xm/dsnTvzfW08uUfP72QykuedKgAAACDC7o4/f1pVz6rqSVV9vfHZn6vqU1V9qKqP9/w7ovPt9/sfqupVVb2oqufbRauqqr+r6m1Vvdntdr/f8++Ivn4VkK8ryPOq+nbjUCPv6uYNXyI6336//6mqfr5MnMOjqur1brf7ZeHXRV+/Csk3KsjTqvruYnFO+6vO/5cmOt/td47f6u7v0FvZV9WPC76TRF+/Csr31eDFzy6bZfWZ6fle1fXKUbdnvVzw+vTrF5NvVJAnFwwysuTM9HwvLpZimzPTr19MvlFBtv6B6BxLzkzPt/UP5Of4ZsFr069fTL5RQYBSEGgpCDQUBBoKAg0FgYaCQENBoKEg0FAQaCgINBQEGgoCDQWBhoJAQ0GgoSDQUBBoKAg0RgX5fNUUy89Mz7f0GVBbeL/gtenXLybfqCCfLhhkZMmZ6fneXizFNmemX7+YfKOCfLhgkJElZ6bne1M3D3O7lv3tmedKv34x+UYF+Vg3j2O8lne17Pmt0flun3D4uq5Tkn8fPfrHgq+Jvn4VlM/Dq8e2enj1y7p5qNuS51ad433d/LfqVw+vvpct8gEAAAAAAADAIzP1R03Sd8jlm3/Hfdqd9PQdcvm+HFUT77hPuZOevkMu3/GRNemO+6w76ek75PIdmnbHfdad9PQdcvnWnRlz/826k56+Qy7fsSl33D3VBBoKAg0FgYaCQENBoKEg0FAQaCgINBQEGgoCDQWBhoJAQ0GgoSDQUBBoKAg0FAQaCgINBYHGrDvp6Tvk8h2bcsd91p309B1y+dadGXP/zbqTnr5DLt+haXfcp9xJT98hl+/A1DvuD+Hh1bE75PI9+B13AAAAAAAAAHhk2o+apO9op+er8I9KpF+/hHzDgqTvaKfnq5Cd75H065eS72RB0ne00/NV0M73KenXLynf6OPu6Tva6flidr4H0q9fTL5RQdJ3tNPzxex8D6Rfv5h8o/9iXfO3zf6z2+3O+lcjPV9VfX/RIGN/nvOi9OuXlM9TTaChINBQEGgoCDQUBBoKAg0FgYaCQENBoKEg0FAQaCgINBQEGgoCDQWBhoJAQ0GgoSDQUBBojAqSvqOdni9m53sg/frF5BsVJH1HOz1fzM73QPr1i8k3Kkj6jnZ6vpid74H06xeT72RB0ne00/NV0M73KenXLynfOQ+vjt3RTs9Xczy8Ovb6pecDAAAAAAAAgMfnrkmsGT4qYef7geargPuvK4id79ujauKd7+EXheerkPtvVBA73/87sibd+T754vB8FXT/jX4fxM73oWl3vgfS88Xcf6OC2Pled6Z8686Muf9GBdn6B6JzLDlz6x8oz7Hk9xHkO7YkX8z956km0FAQaCgINBQEGgoCDQWBhoJAQ0GgoSDQUBBoKAg0FAQaCgINBYGGgkBDQaChINBQEGgoCDRGBbHzfWzKne+B9Hwx99+oIHa+150p37ozY+6/UUHsfB+adud7ID1fzP03Koid7y+m3vk+JT1fBd1/D+Hh1bE72vI97J15AAAAAAAAAHh8pv6oSYXns0M+//s77U56heezQ35g2vd3yp30Cs9nh/ykKd/fWXfS0/PZIV93Zky+WXfS0/PZIV93Zky+WXfS0/PZIV93Zkw+TzWBhoJAQ0GgoSDQUBBoKAg0FAQaCgINBYGGgkBDQaChINBQEGgoCDQUBBoKAg0FgYaCQENBoDHrTnp6Pjvk686MyTfrTnp6Pjvk686MyTfrTnp6Pjvk686MyTflTnqF57NDfmTa99fDq8ce/I57hV+/ys8HAAAAXMs/4tr5dC58svsAAAAASUVORK5CYII=\"\n  },\n  \"triangle\": {\n    \"icon\": \"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAMgAAADICAYAAACtWK6eAAAACXBIWXMAAAsTAAALEwEAmpwYAAAFX0lEQVR4nO3dsW5URxQG4LNBNJapTXiAvAAPYOWdoEG0SUPeJumjpOcF8gA2bqiQCywxKXYBrfAcZjz3LrP297Xc3fNrpN+LpfWcCAAAAGAKm+/8+2lEnEXESUQ8Xnj2TURcR8RVRHy443vIJ99dNeXLCvI0Ip4tHKrmIiLedb5Gvq/kG1PN91PlBadxuHCxm3Xa8bx8++QbU81XK8jZelmqembKNzZTvsaZtYKcrBikpmemfGMz5WucWSvI0r8QteiZKd/YTPkaZ9YKAoSCQEpBIKEgkFAQSCgIJBQEEgoCCQWBhIJAQkEgoSCQUBBIKAgkFAQSCgIJBYGEgkBCQSBRK8jNQVP0z5RvbKZ8jTNrBbleMUhNz0z5xmbK1zizVpCrFYPU9MyUb2ymfI0zH1Ue/hgRJSKerBZn30VEvO94Xr598o2p5nN5dZ18Yx5CPgAAAAAAAAB4YHzVpG44XynlPCJeRsTz2K41XtK7iHgbEW82m80/d3yPqc8vJshnT3qb7nyllFcR8ds6cfZHRcTrzWbze+frpj6/mCRfrSCnEfHLanFu91+0/6SZOt/uk+Pv+P4n9FJKRPza8Uky9fnFRPnsSV9n5ss4XDliN+tFx/Ozn980+exJX2fm89VSLDNz9vObJp896evMXPoX8hY/dzw7+/lNk8+tJpBQEEgoCCQUBBIKAgkFgYSCQEJBIKEgkFAQSCgIJBQEEgoCCQWBhIJAQkEgoSCQUBBIKAgk7ElfZ2bvHVBLuOx4dvbzmyafPenrzHy7WoplZs5+ftPksyd9nZlvYnuZ26GU3cxWs5/fNPlqBfkQ2+sYD+Ui+u5vnTrf7obD13GYkny+evTfjtdMfX4xUT6XV9ctdXn1i9he6tZzb1WLy9j+t+oPl1ffiT3pAAAAAAAAANDtqL9qYg+58xtwv/ek20O+x/mNuV970u0hv5XzG3Ov9qTbQz420/k1zjzWPen2kI/NdH6NM491T7o95GMznV/jTLeaQEJBIKEgkFAQSCgIJBQEEgoCCQWBhIJAQkEgoSCQUBBIKAgkFAQSCgIJBYGEgkBCQSChIJA41j3p9pCPzXR+jTOPdU+6PeRjM51f48xj3ZNuD/nYTOfXOPMo96TbQ/4N5zfmfu5Jt4fc+Q2wJx0AAAAAAAAAllVKOS+l/FVKuSzLu9y997l88h1dvlLKqxVC3eZT2e7slk++48hXts39dKCAn0M2N1k++Q6Vr/Z199n3aMu3T74x1Xy1gsy+R1u+sZnyNc68taWllEP+tdkXm82m6aeGfLeTb8xt+dxqAgkFgYSCQEJBIKEgkFAQSCgIJBQEEgoCCQWBhIJAQkEgoSCQUBBIKAgkFAQSCgIJBYGEgkCiVpDZ92jL9y35xtyar1aQ2fdoyzc2U77GmbWCzL5HW7598o3pzffl6sdD3G43cjWlfPL9kHyfQ56XUv4spVysEOxi996jlxvLJ98PyQcAAAAAAAAAD8/3VmKdRsRZRJxExOOFZ99ExHVEXEXEhzu+h3zy3VVTvqwgTyPi2cKhai6i/28A5PtKvjHVfLWvu5/G4cLFbtZpx/Py7ZNvTDVfrSBn62Wp6pkp39hM+Rpn1gpysmKQmp6Z8o3NlK9xZq0gS/9C1KJnpnxjM+VrnOlWE0goCCQUBBIKAgkFgYSCQEJBIKEgkFAQSCgIJBQEEgoCCQWBhIJAQkEgoSCQUBBIKAgkFAQStYLcHDRF/0z5xmbK1zizVpDrFYPU9MyUb2ymfI0zawW5WjFITc9M+cZmytc481Hl4Y+xXa7+ZLU4+y4i4n3H8/Ltk29MNZ/Lq+vkG/MQ8gEAAACH8j9qsKYdhQgxPgAAAABJRU5ErkJggg==\"\n  },\n  \"lefttriangle\": {\n    \"icon\": \"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAMgAAADICAYAAACtWK6eAAAACXBIWXMAAAsTAAALEwEAmpwYAAAFGklEQVR4nO3dPY4UVxQG0NuWnCBysBfgDbCAkfcECSK1E7wbO7fsnA14ATOQIxIknoPuAY+m6rpq6lVzX3NOOtV9P1Xpmx+p590IAAAAoIRD9sXW2lVEvIiIZxHxtPPstxHxJiJeHw6Hvx74Ho8j4klEPIqI73sFO/kYER8i4l1EvH/ge8g3eL7ZgrTWXkbEL51DTY6KiFeHw+HXla97GhE/7pBnynUcC72GfF8Mm2+yIKefHH/OfX0HLSJ+XvGT5HFE/LRjnin/xPLvhPLdN2S+72YufhHnK0ecZj1fcf2TvYJ0minftpll8s0V5NmOQeasmflotxR9Zsq3bWaZfHMF6f0H+RI/rLi29x9svWfKt21mmXxzBQFCQSClIJBQEEgoCCQUBBIKAgkFgYSCQEJBIKEgkFAQSCgIJBQEEgoCCQWBhIJAQkEgoSCQmCvI2jOMerhZce3H3VL0mSnftpll8s0V5M2OQeasmflhtxR9Zsq3bWaZfHMFeR3Hw9zOpZ1mLvVuryCdZsq3bWaZfJMFOZ1w+CrOU5Lbo0f/XvGa93E8LvJcrmPd+bLy3TVsviWHVz+P46Fua86tWuImjr9W/ebw6geRb5se+QAAAAAAAADgGzP0nvTq+aL+RyXku9Q96dXzRZE93wn5vrisPenV80WhPd8z5LvvovakV89XZs93h2t7GTLfqHvSq+crs+e7w7W9DJlv1D3p1fOV2fPd4dpehsznVBNIKAgkFAQSCgIJBYGEgkBCQSChIJBQEEgoCCQUBBIKAgkFgYSCQEJBIKEgkFAQSCgIJBQEEqPuSa+er8ye7w7X9jJkvlH3pFfPV2bPd4drexky36h70qvnK7Pnu8O1vQyZb8g96dXzRaE93zPku+sy96RXzxcFDl/+H/LZkw4AAAAAAAAAKwy9Jz2KfxTB/Rv/oybD7kmPInu057h/d9iTvtFF7SF3/ybZk77Bpe0hd/+2zSyTb9Q96WX2aM9w/7bNLJNv1D3pZfZoz3D/ts0sk8+pJpBQEEgoCCQUBBIKAgkFgYSCQEJBIKEgkFAQSCgIJBQEEgoCCQWBhIJAQkEgoSCQUBBIKAgkRt2TXmaP9gz3b9vMMvlG3ZNeZo/2DPdv28wy+Ubdk15mj/YM92/bzDL5htyTHoX2aE9x/+6xJ/0BLn4Pufs3/uHVAAAAAAAAAMB/2ZM+7+I/KuH52pPey7B7vud4vnfYk97BkHu+p3i+k+xJ32jIPd8zPN+FM+1J32dm9Xye78KZ9qTvM7N6Ps934UynmkBCQSChIJBQEEgoCCQUBBIKAgkFgYSCQEJBIKEgkFAQSCgIJBQEEgoCCQWBhIJAQkEgoSCQsCd9n5nV83m+C2fak77PzOr5PN+FM+1J32dm9Xye78KZ9qQvM+ye7yme7z32pD/At3J4tedrTzoAAAAAAAAA9NBau2qt/dFau2n93Zze+0o++YbL11p7uUOoKZ/acWe3fPKNka8dm/vpTAFvQy5usnzynSvfqHvS5btLvm1m8426J12+bTPlWzhzsqWttXP+t9lnh8Nh0XcN+abJt81UPqeaQEJBIKEgkFAQSCgIJBQEEgoCCQWBhIJAQkEgoSCQUBBIKAgkFAQSCgIJBYGEgkBCQSChIJAYdU+6fPfJt81kvlH3pMu3baZ8C2eOuiddvrvk22Ztvs9HP57jdLstR1PKJ99XyXcb8qq19ntr7XqHYNen9956uLF88n2VfAAAAMAZ/QsAIPjNRI6mtwAAAABJRU5ErkJggg==\"\n  },\n  \"chessboard\": {\n    \"icon\": \"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAMgAAADICAYAAACtWK6eAAAACXBIWXMAAAsTAAALEwEAmpwYAAAE7klEQVR4nO3dMY5TZxQF4OtIaRA9JAvIBlhAlD1BE9EmDdlTlPRsIAuA0CMaCqcYRyNj/2f85trW+z3f1zJwnw46A0jmnSoAAABgFTYP/PjzqnpRVc+q6vsz3/5aVV+q6lNVfX7ML7Ddbn+uqjdV9aqqXp7v0aqq6t+qel9V7zabzV+P/DXkN3l+qSAvq+rHMz/UyIe6C/Rk2+3216r67TKPs3+qqt5uNpvfF/48+e1O1cT5jQryvKp+utjjHPdPnfidcPed7896+E/Ac9lW1S8LvhPK75uTNWl+3w2++MVln6V9801d7ze3drdeL/h6+e2bNr9RQZ5d8EFGltx8dbGnOM9N+fVuria/UUHO/Q+iUyy5ee5/UJ7ihwVfK79DU+Y3KghQCgKRgkCgIBAoCAQKAoGCQKAgECgIBAoCgYJAoCAQKAgECgKBgkCgIBAoCAQKAoGCQDAqyNerPsXym4veAXUmHxd8rfwOTZnfqCBfLvggI0tuvr/YU5znpvx6N1eT36ggny74ICNLbr6ru5eRXct2d/NU8ts3bX6jgnyuu9cxXsuHWvB+2d0b+t7WdX6T/3915t8Lfo787k2d3y28vPp13b2UbMl7l07xse7+WvDHzC9fTuTXyw8AAAAAAAAAnp74URM72nbIG24iv2FB7GjvsUPeM21+RwtiR/soO+Q9U+Y3+ri7He3eTfn1bq4mv1FB7Gj3bsqvd3M1+Y0KYke7d1N+vZuryc9bTSBQEAgUBAIFgUBBIFAQCBQEAgWBQEEgUBAIFAQCBYFAQSBQEAgUBAIFgUBBIFAQCBQEglFB7Gj3bsqvd3M1+Y0KYke7d1N+vZuryW9UEDvavZvy691cTX5HC2JH+4Ad8p5p8zvl5dV2tO2QP8ZTyA8AAAAAAAAAnpiHhhJn+CiCHXL5PcZJ+aWC2NHenSo75B1T5zcqiB3tb06WHfKOafMb/X8QO9r77JD3TJvfqCB2tHs35de7uZr8RgWxo33IDnnPlPl5qwkECgKBgkCgIBAoCAQKAoGCQKAgECgIBAoCgYJAoCAQKAgECgKBgkCgIBAoCAQKAoGCQDAqiB3tQ3bIe6bMb1QQO9q9m/Lr3VxNfqOC2NHeZ4e8Z9r8RgWxo33PDnnP1Pndwsur17yjLb8bzg8AAAAAAAAAnp74URM72nbIG24iv2FB7GjvsUPeM21+RwtiR/soO+Q9U+Y3+ri7He3eTfn1bq4mv1FB7Gj3bsqvd3M1+Y0KYke7d1N+vZuryc9bTSBQEAgUBAIFgUBBIFAQCBQEAgWBQEEgUBAIFAQCBYFAQSBQEAgUBAIFgUBBIFAQCBQEglFB7Gj3bsqvd3M1+Y0KYke7d1N+vZuryW9UEDvavZvy691cTX5HC2JH+4Ad8p5p8zvl5dV2tO2QP8ZTyA8AAAAAAAAAnpiHhhJn+CiCHXL5PcZJ+aWC2NHenSo75B1T5zcqiB3tb06WHfKOafMb/X8QO9r77JD3TJvfqCB2tHs35de7uZr8RgWxo33IDnnPlPl5qwkECgKBgkCgIBAoCAQKAoGCQKAgECgIBAoCgYJAoCAQKAgECgKBgkCgIBAoCAQKAoGCQDAqiB3tQ3bIe6bMb1QQO9q9m/Lr3VxNfqOC2NHeZ4e8Z9r8RgWxo33PDnnP1Pndwsur17yjLb8bzg8AAAC4ov8AwGjpQ+5xFXQAAAAASUVORK5CYII=\"\n  },\n  \"diamond\": {\n    \"icon\": \"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAMgAAADICAYAAACtWK6eAAAACXBIWXMAAAsTAAALEwEAmpwYAAAFF0lEQVR4nO3dMY4UZxAF4BpLThA52AfwBTiA5TtBYpHaCb6TZedcwAcAkyMSgnGwa9nDzv+2e/+ZVXXzfSm7VKlmHgvS0K8KAAAAaOFwz68/rapnVfWkqr698OzPVfWpqj5U1ccH/h6t9zsejz9W1auqelFVzy+3WlVV/V1Vb6vqzeFw+OOBv0fr+1WD/VJAnlfV9xdeauRd3bzga7Te73g8/lxVv1xnndNRVfX6cDj8uvL7Wt+vmuw3CsjTqvrhauuc91ct/5Om9X63Pzl+r/t/Ql/Ksap+WvGTpPX9qtF+3wy++Nl1d5me2X2/V/V44ajbWS9XfH33+7XZbxSQJ1dcZGTNzO77vbjaFpeZ2f1+bfYbBeTS/yBaYs3M7vtd+h/kS3y34mu736/NfqOAACUgEAkIBAICgYBAICAQCAgEAgKBgEAgIBAICAQCAoGAQCAgEAgIBAICgYBAICAQCAgEo4B8ftQt1s/svt/aZ0BdwvsVX9v9fm32GwXk0xUXGVkzs/t+b6+2xWVmdr9fm/1GAflwxUVG1szsvt+bunmY22M53s5cqvv92uw3CsjHunkc42N5V+ue39p6v9snHL6uxwnJv48e/XPF97S+XzXaz8Orxy718OqXdfNQtzXPrVrifd38teo3D69+kEvsBwAAAAAAAABfmU1/1EQPuftN2HdPuh7yE+43Z1896XrIz3K/ObvqSddDPjfT/RbO3GpPuh7yuZnut3DmVnvS9ZDPzXS/hTM91QQCAYFAQCAQEAgEBAIBgUBAIBAQCAQEAgGBQEAgEBAIBAQCAYFAQCAQEAgEBAIBgUBAINhqT7oe8rmZ7rdw5lZ70vWQz810v4Uzt9qTrod8bqb7LZy5yZ50PeR3uN+cffak6yF3vwl60gEAAAAAAABgtfhREz3a0x9FsN/Ge9yHAdGjfWJ1D3nZ7/822+N+NiB6tM9a3ENe9jtnkz3uo4+769Gem2m/uZlt3n+jgOjRnptpv7mZbd5/o4Do0Z6bab+5mW3ef55qAoGAQCAgEAgIBAICgYBAICAQCAgEAgKBgEAgIBAICAQCAoGAQCAgEAgIBAICgYBAICAQjAKiR3tupv3mZrZ5/40Cokd7bqb95ma2ef+NAqJHe26m/eZmtnn/nQ2IHu07VvWQl/2+tNke9yUPr9ajvdOHQ1fz/Tbw/gMAAAAAAACAr8x9RYlb+CiCHnf3e4hF90sB0aN9O6p22OPufieG9xsFRI/2FyNrRz3u7nfW2fuN/j+IHu1Te+txd7+FM0cB0aM9N9P95ma2ud8oIHq079pTj7v7LZzpqSYQCAgEAgKBgEAgIBAICAQCAoGAQCAgEAgIBAICgYBAICAQCAgEAgKBgEAgIBAICAQCAsEoIHq079pTj7v7LZw5Coge7bmZ7jc3s839RgHRo31qbz3u7rdw5iggerT/s7sed/e7Y3i/PTy8unOPtvvt+H4AAAAAAAAA8PXZ9EdNqvl+esi3//putie9mu+nh/zEZl/fTfakV/P99JCftcnXd6s96d3300M+N7PNflvtSe++nx7yuZlt9ttqT3r3/fSQz81ss5+nmkAgIBAICAQCAoGAQCAgEAgIBAICgYBAICAQCAgEAgKBgEAgIBAICAQCAoGAQCAgEAgIBFvtSe++nx7yuZlt9ttqT3r3/fSQz81ss99We9K776eHfG5mm/022ZNezffTQ37HZl9fD68e00M+Z/evLwAAAPCI/gFIfqYbRE+aDAAAAABJRU5ErkJggg==\"\n  },\n  \"smalldiamond\": {\n    \"icon\": \"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAMgAAADICAYAAACtWK6eAAAACXBIWXMAAAsTAAALEwEAmpwYAAAE7ElEQVR4nO3dMY5TVxQG4OOgNGioSbKAbIAFROwJmog2acieoqRnA1nAAA0VooDCKewospj78+5cP+s+z/e1PM/5da1/zEjWPVUAAADAFHbf+PebqnpaVY+r6vszz/5SVZ+q6n1Vfbznz5BPvvtalC8V5Ieq+unMoVpuq+pd52vk+598Y5r5vmu84KYuF66Os246npfvlHxjmvlaBXm6Xpamnpnyjc2Ub+HMVkEerxikpWemfGMz5Vs4s1WQc/9BtETPTPnGZsq3cGarIEApCEQKAoGCQKAgECgIBAoCgYJAoCAQKAgECgKBgkCgIBAoCAQKAoGCQKAgECgIBAoCQasgXy6aon+mfGMz5Vs4s1WQTysGaemZKd/YTPkWzmwV5P2KQVp6Zso3NlO+hTMfNR7+XFX7qnqyWpxTt1X1oeN5+U7JN6aZz+XVbfKNeQj5AAAAAAAAAOCB8VWTtuF8+/3+l6p6WVXP6rDW+JzeVdWbqnq92+3+uufPmPr8aoJ89qQv051vv9//WlW/rRPndFRVvdrtdr93vm7q86tJ8rUKclNVP68W527/1PLfNFPnO35y/Fnf/oQ+l31VPe/4JJn6/GqifPakrzPzZV2uHHWc9aLj+dnPb5p89qSvM/PZainOM3P285smnz3p68w89x/kS/zY8ezs5zdNPreaQKAgECgIBAoCgYJAoCAQKAgECgKBgkCgIBAoCAQKAoGCQKAgECgIBAoCgYJAoCAQKAgE9qSvM7P3DqhzeNvx7OznN00+e9LXmflmtRTnmTn7+U2Tz570dWa+rsNlbpeyP85cavbzmyZfqyAf63Ad46XcVt/9rVPnO95w+KouU5L/rh79u+M1U59fTZTP5dVt57q8+kUdLnXrubdqibd1+G/VHy6vvhd70gEAAAAAAACg26a/amIPufMbcN170u0hP+H8xlzXnnR7yO/k/MZc1Z50e8jHZjq/hTO3uifdHvKxmc5v4cyt7km3h3xspvNbONOtJhAoCAQKAoGCQKAgECgIBAoCgYJAoCAQKAgECgKBgkCgIBAoCAQKAoGCQKAgECgIBAoCwVb3pNtDPjbT+S2cudU96faQj810fgtnbnVPuj3kYzOd38KZm9yTbg/5V5zfmOvck24PufMbYE86AAAAAAAAAHTb9FdNavJ89pBv//3d7J70mjyfPeQnNvv+bnJPek2ezx7yO23y/d3qnvTZ89lDPjZzmnxb3ZM+ez57yMdmTpNvq3vSZ89nD/nYzGnyudUEAgWBQEEgUBAIFAQCBYFAQSBQEAgUBAIFgUBBIFAQCBQEAgWBQEEgUBAIFAQCBYFAQSDY6p702fPZQz42c5p8W92TPns+e8jHZk6Tb6t70mfPZw/52Mxp8m1yT3pNns8e8q9s9v11eXWbPeRjrv79BQAAAAAAAICHx1dN2uQbcxX57ElfRr4xm83X+jbvTV0uXB1n3XQ8L98p+cY089mTvs5M+cZmTpPPnvR1Zso3NnOafPakrzNTvrGZ0+RzqwkECgKBgkCgIBAoCAQKAoGCQKAgECgIBAoCgYJAoCAQKAgECgKBgkCgIBAoCAQKAoGCQGBP+joz5RubOU0+e9LXmSnf2Mxp8tmTvs5M+cZmTpPvUePhz3XYv/1ktTinbqvqQ8fz8p2Sb0wzn8ur2+Qb8xDyAQAAAJfyL3WaU2vK5kXFAAAAAElFTkSuQmCC\"\n  },\n  \"square\": {\n    \"icon\": \"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAMgAAADICAYAAACtWK6eAAAACXBIWXMAAAsTAAALEwEAmpwYAAAFJElEQVR4nO3dQW4UVxAG4OpI2SD2kBwgF8gBRrkTbCy2yYbcBvZRss8FcgAb9ogNkiuLGRtZ7i5187rHr4fv2wamfqT6baGYVxEAAABA/zLzkJnvM/Mm13dz+uyDfPLtLl9mXm0QasxtZl7JJ99u8uWxubdnCngXcnaT5ZPvXPl+mMj4OiKGuX+gFQwR8WrBr5fvIfnaTOabKsiv22WZtGSmfG0z5Zs5c7SlmZnbZhk3DMOsrxryjZOvzVi+qe8gQCgIlBQECgoCBQWBgoJAQUGgoCBQUBAoKAgUFAQKCgIFBYGCgkBBQaCgIFBQECgoCBQUBApTBflw1hRHNwt+rXyPyddmNN9UQf7dMMiUJTPla5sp38yZUwV5GxHnfFkiTzPnku8h+doszXf/9OM5XrdreZpSPvmeJN9dyENmvsvM6w2CXZ8+u/VxY/nke5J8AAAAAAAAAPD9KU9inf43/Os43m97ufLsD3H8Ccq3wzD8/Y2f8TwiXkTEs4j4ca1gJ18i4nNEfIyIT9/4GfI15Oth/yYLkscf4Pp95VCjoyLizTAMfyz8fS8j4ucN8oy5juX/RkG+rxbn62X/po54HiLir6n/voGMiN8WfCd5HhG/bJhnzH8x/yuhfI/NztfT/u31TvqLrYKsNFO+tpnd7N9e76Q/2yzFOjPla5vZzf5NFWTtvxDN8dOCX7v2XyjXnilf28xu9s+rJlBQECgoCBQUBAoKAgUFgYKCQEFBoKAgUFAQKCgIFBQECgoCBQWBgoJAQUGgoCBQUBAoKAgU9non/ctmKdaZKV/bzG72b6930j9vlmKdmfK1zexm//Z6J/3jVkFWmilf28xu9m+0IKcX5t7EeULePf34z4Lf8ymOz1mey3Use19WvocW5etp/+Y8Xv0qjo9qLXm3ao6bOH5b+9Pj1d/k4vPtYP8AAAAAAAAA4DvjTvq0i/9Rjug8Xw/75076PBd3hzw6z9fL/rmTPt/F3CGPzvP1tH/upG8zU762md3snzvp28yUr21mN/vnTvo2M+Vrm9nN/nnVBAoKAgUFgYKCQEFBoKAgUFAQKCgIFBQECgoCBQWBgoJAQUGgoCBQUBAoKAgUFAQKCgIFBYGCO+nbzJSvbWY3++dO+jYz5Wub2c3+uZO+zUz52mZ2s3/upM9zUXfIo/N8Pe2fO+nTLv5x6Og83w72DwAAAAAAAAC+M+6kT7v4H+WIzvP1sH/upM9zcXfIo/N8veyfO+nzXcwd8ug8X0/75076NjPla5vZzf65k77NTPnaZnazf+6kbzNTvraZ3eyfV02goCBQUBAoKAgUFAQKCgIFBYGCgkBBQaCgIFBQECgoCBQUBAoKAgUFgYKCQEFBoKAgUFAQKLiTvs1M+dpmdrN/7qRvM1O+tpnd7J876dvMlK9tZjf75076PBd1hzw6z9fT/rmTPu3iH4eOzvPtYP8AAAAAAAAAgK8y85CZ7zPzJtd3c/rsg3zy7S5fZl5tEGrMbR5vYssn3z7y5bG5t2cKeBdydpPlk+9c+fZ6J12+h+Rrc3F30uVrmynfzJmjLc3Mc/5rrnvDMMz6qiHfOPnajOXzqgkUFAQKCgIFBYGCgkBBQaCgIFBQECgoCBQUBAoKAgUFgYKCQEFBoKAgUFAQKCgIFBQECgoChb3eSZfvMfnaXNSddPnaZso3c+Ze76TL95B8bZbmu3/68Ryv27U8TSmffE+S7y7kITPfZeb1BsGuT5/d+rixfPI9ST4AAADgjP4Hm2pLjkVf1VMAAAAASUVORK5CYII=\"\n  },\n  \"smallsquare\": {\n    \"icon\": \"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAMgAAADICAYAAACtWK6eAAAACXBIWXMAAAsTAAALEwEAmpwYAAAE6ElEQVR4nO3dP44URxQH4DdGTtAQY3wAX4ADWNwJEkRqEnwny865gA+wQEKECCAYghkbWrP1tmqqe9TV+33p9uz7qbd/+0earRcBAAAArMLujo/vI+JxRDyMiJ9nnv01Ij5HxIeI+HTh55BPvktV5csK8ktE/DpzqJKbiHjf+Br5vpOvTzHfT4UX7ON64eI0a99wvXxT8vUp5isV5PFyWYpaZsrXN1O+ypmlgjxcMEhJy0z5+mbKVzmzVJC5/yCq0TJTvr6Z8lXOLBUECAWBlIJAQkEgoSCQUBBIKAgkFAQSCgIJBYGEgkBCQSChIJBQEEgoCCQUBBIKAgkFgYSCQKJUkK9XTdE+U76+mfJVziwV5POCQUpaZsrXN1O+ypmlgnxYMEhJy0z5+mbKVznzQeHiLxFxiIhHi8WZuomIjw3XyzclX59iPodXl8nX5z7kAwAAAAAAAIB7Zui3mhwOh98j4kVEPI3j2uA5vY+ItxHxZrfb/X3JJ5CvL1+s4Pkbdk/64XB4GRF/LBNnOioiXu12u9dNL5Lv/1FxQb5YyfNXKsg+In5bLM7t/o3KnySn73x/xd0/AedyiIhntd8J5TsfGQ35YkXP36h70l/E9b64cZr1vOF6+aZa863m+Rt1T/rTxVLMM1O+vpmref5G3ZM+9x+UNZ40XCvfuZZ8q3n+nGoCCQWBhIJAQkEgoSCQUBBIKAgkFAQSCgIJBYGEgkBCQSChIJBQEEgoCCQUBBIKAgkFgYSCQGLUPelNZ2jN5F3DtfKda8m3mudv1D3pbxdLMc9M+fpmrub5G3VP+ps4HkZ2LYfTzFryTbXmW83zVyrIpzgex3gtN9FwPu/phL5XcZ0v8n9HZ/5T+wL5JprzxYqevy0cXv08joeStZy7VONdHH8t+LPzcGj5Bj68GgAAAAAAAAD40RbeamLPt/t3CXvSZzL0nu8S92/CnvROw+75vo37dyt70jsMu+e7wP2rnGlP+jIz3b++mau5f/ak1xtyz3eB+1c506kmkFAQSCgIJBQEEgoCCQWBhIJAQkEgoSCQUBBIKAgkFAQSCgIJBYGEgkBCQSChIJBQEEgoCCTsSa835J7vAvevcqY96cvMdP/6Zq7m/tmTXmfYPd8F7l/lTHvS7zb0nu/buH9n7Em/wOb3fLt/9qQDAAAAAAAAQJstvNVktXu+5bMnfS6b2/Mt3/dRYU/6LDaz51u+85FhT3q3Le35lm/KnvQZbGnPt3x9M1fz/NmTXq/l/yXkO2dPOmyNgkBCQSChIJBQEEgoCCQUBBIKAgkFgYSCQEJBIKEgkFAQSCgIJBQEEgoCCQWBhIJAQkEgYU96vZY93/Kdsye905b2fMvXN3M1z5896XVa93zLN2VPeqdN7fmWb8Ke9Attfs+3fPakAwAAAAAAAMC2DP1Wk5BPvstte096yPcj+foU85XezbuP64WL06x9w/XyTcnXp5hv1D3p8vXNlK9y5qh70uXrmylf5cxR96TL1zdTvsqZTjWBhIJAQkEgoSCQUBBIKAgkFAQSCgIJBYGEgkBCQSChIJBQEEgoCCQUBBIKAgkFgYSCQEJBIDHqnnT5+mbKVzlz1D3p8vXNlK9y5qh70uXrmylf5cwHhYu/xHG/9aPF4kzdRMTHhuvlm5KvTzGfw6vL5OtzH/IBAAAA1/IN7YSWk669SX0AAAAASUVORK5CYII=\"\n  },\n  \"scissors\": {\n    \"icon\": \"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAMgAAADICAYAAACtWK6eAAAACXBIWXMAAAsTAAALEwEAmpwYAAAFUUlEQVR4nO3dMW6cRRgG4G+RaCL6AAfgAjkA4k5Jg9JCE+6EoM8FOEBC+ihNiqVYU0TZeT3rnd/6/vXztB57Ps3odWTFnrcKAAAAaOGQPng8Hn+uqldV9aKqvl+8979V9baq3hwOh78e8gW6z1dV31XV86p6VlXfrhrszueq+lRVH6rq4wO/Ruv5OtzvMCDH4/HXqvpt8VBnt6qq14fD4feLPqn5fHW60B83mOecd3W68Eu0nq/L/Z4NyF1y/xx9fAPHqvpl9jt19/nq9J35pw3nOeefmv9O3Xq+Tvf7zeATXtXjDVd3e728YH33+Z5vNciiPbvP1+Z+RwF5sd0sQ5fs2X2+Z5tNsWbP7vO1ud9RQFb/QDTjhwvWdp9v9Q+8q/fsPl+b+x0FBCgBgUhAIBAQCAQEAgGBQEAgEBAIBAQCAYFAQCAQEAgEBAIBgUBAIBAQCAQEAgGBQEAgGAXk0jeWVnh/wdru833ebIo1e3afr839jgLydsNBRi7Zs/t8nzabYs2e3edrc7+jgLyp02Naj+V4t+es7vN92GqQRXt2n6/N/Z4NyN0Lc6/rcYb8/+nHv2c/oft8dXpB8N1G85zzri57/7b1fJ3ud+bx6pd1elTrknehZryv0z9rf1z5eHXb+ar549DVfL4d3C8AAAAAAAAAPDF60sduvifd+d1/fnrSJ7aqG+xJd35fGJ6fnvQ5N9WT7vzOOnt+etLn3FpPuvOb3FNP+jZ76iG/bs8256cnfd4t9aQ7v8k9vWoCgYBAICAQCAgEAgKBgEAgIBAICAQCAoGAQCAgEAgIBAICgYBAICAQCAgEAgKBgEAgIBDoSZ93Sz3pzm9yTz3p2+yph/y6Pducn570ObfWk+78JvfUk36/m+tJd35fGZ6fnvSxm+9Jd35X98wDAAAAAAAAwBNzX5Fj9//qbz2fHvL9328KSIue6qD1fHrIv7Db+x0FpE1P9UDr+fSQn7XL+x39PUibnuoFa1fRQ36dXd7vKCBteqoXrF1FD/l1dnm/o4C06alesHYVPeTX2eX9etUEAgGBQEAgEBAIBAQCAYFAQCAQEAgEBAIBgUBAIBAQCAQEAgGBQEAgEBAIBAQCAYFAQCAYBaRNT/WCtavoIb/OLu93FJA2PdUL1q6ih/w6u7zfUUDa9FQvWLuKHvLr7PJ+RwFp01M90Ho+PeRf2e39erx6TA/5dW7+fgEAAAAAAADg6Ym/atK957v7fNX8VyWc3xU96d17vrvPV016vkec3xcu60nv3vPdfb5q1PN9jvM766Ke9O49393na9PzPeD8JvccBaR7z3f3+dr0fA84v8k9RwHp3vPdfb42Pd8Dzm9yT6+aQCAgEAgIBAICgYBAICAQCAgEAgKBgEAgIBAICAQCAoGAQCAgEAgIBAICgYBAICAQCAgEo4B07/nuPl+bnu8B5ze55ygg3Xu+u8/Xpud7wPlN7jkKSPee7+7zten5HnB+k3ueDUj3nu/u81Wjnu9znN9XHtaT3r3nu/t81eDx5cT56UkHAAAAAAAAgMvoSR+7iZ7ve7Ser8P96kmf2Kp23PMdtJ6vy/3qSZ+z257vgdbzdbpfPelzdtvzvWDtKrvscdeTvs2ebXq+F6xdZZc97nrS5+2y53vB2lV22ePuVRMIBAQCAYFAQCAQEAgEBAIBgUBAIBAQCAQEAgGBQEAgEBAIBAQCAYFAQCAQEAgEBAIBgUBP+rxd9nwvWLvKLnvc9aRvs2ebnu8Fa1fZZY+7nvQ5u+35XrB2lV32uOtJv9+ue74HWs/X6X71pI89hZ7v1vPt4H4BAACAx/IfV5v6DSxvZ+4AAAAASUVORK5CYII=\"\n  }\n}","icons.ts":"/*\nThe MIT License (MIT)\n\nCopyright (c) 2013-2016 The MicroPython-on-micro:bit Developers, as listed\nin the accompanying AUTHORS file\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\nall 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\n// Images from file microbitconstimage.cpp https://github.com/bbcmicrobit/micropython\n\nenum IconNames {\n    //% block=\"heart\"\n    //% jres=icons.heart\n    Heart = 0,\n    //% block=\"small heart\"\n    //% jres=icons.smallheart\n    SmallHeart,\n    //% block=\"yes\"\n    //% jres=icons.yes\n    Yes,\n    //% block=\"no\"\n    //% jres=icons.no\n    No,\n    //% block=\"happy\"\n    //% jres=icons.happy\n    Happy,\n    //% block=\"sad\"\n    //% jres=icons.sad\n    Sad,\n    //% block=\"confused\"\n    //% jres=icons.confused\n    Confused,\n    //% block=\"angry\"\n    //% jres=icons.angry\n    Angry,\n    //% block=\"asleep\"\n    //% jres=icons.asleep\n    Asleep,\n    //% block=\"surprised\"\n    //% jres=icons.surprised\n    Surprised,\n    //% block=\"silly\"\n    //% jres=icons.silly\n    Silly,\n    //% block=\"fabulous\"\n    //% jres=icons.fabulous\n    Fabulous,\n    //% block=\"meh\"\n    //% jres=icons.meh\n    Meh,\n    //% block=\"t-shirt\"\n    //% jres=icons.tshirt\n    TShirt,\n    //% block=\"roller skate\"\n    //% jres=icons.rollerskate\n    Rollerskate,\n    //% block=\"duck\"\n    //% jres=icons.duck\n    Duck,\n    //% block=\"house\"\n    //% jres=icons.house\n    House,\n    //% block=\"tortoise\"\n    //% jres=icons.tortoise\n    Tortoise,\n    //% block=\"butterfly\"\n    //% jres=icons.butterfly\n    Butterfly,\n    //% block=\"stick figure\"\n    //% jres=icons.stickfigure\n    StickFigure,\n    //% block=\"ghost\"\n    //% jres=icons.ghost\n    Ghost,\n    //% block=\"sword\"\n    //% jres=icons.sword\n    Sword,\n    //% block=\"giraffe\"\n    //% jres=icons.giraffe\n    Giraffe,\n    //% block=\"skull\"\n    //% jres=icons.skull\n    Skull,\n    //% block=\"umbrella\"\n    //% jres=icons.umbrella\n    Umbrella,\n    //% block=\"snake\"\n    //% jres=icons.snake\n    Snake,\n    //% block=\"rabbit\"\n    //% jres=icons.rabbit\n    Rabbit,\n    //% block=\"cow\"\n    //% jres=icons.cow\n    Cow,\n    //% block=\"quarter note\"\n    //% jres=icons.quarternote\n    QuarterNote,\n    //% block=\"eigth note\"\n    //% jres=icons.eighthnote\n    //% deprecated=true blockHidden=true\n    EigthNote,\n    //% block=\"eighth note\"\n    //% jres=icons.eighthnote\n    EighthNote,\n    //% block=\"pitchfork\"\n    //% jres=icons.pitchfork\n    Pitchfork,\n    //% block=\"target\"\n    //% jres=icons.target\n    Target,\n    //% block=\"triangle\"\n    //% jres=icons.triangle\n    Triangle,\n    //% block=\"left triangle\"\n    //% jres=icons.lefttriangle\n    LeftTriangle,\n    //% block=\"chess board\"\n    //% jres=icons.chessboard\n    Chessboard,\n    //% block=\"diamond\"\n    //% jres=icons.diamond\n    Diamond,\n    //% block=\"small diamond\"\n    //% jres=icons.smalldiamond\n    SmallDiamond,\n    //% block=\"square\"\n    //% jres=icons.square\n    Square,\n    //% block=\"small square\"\n    //% jres=icons.smallsquare\n    SmallSquare,\n    //% block=\"scissors\"\n    //% jres=icons.scissors\n    Scissors\n}\n\nenum ArrowNames {\n    //% blockIdentity=images.arrowNumber block=\"North\"\n    North = 0,\n    //% blockIdentity=images.arrowNumber block=\"North East\"\n    NorthEast,\n    //% blockIdentity=images.arrowNumber block=\"East\"\n    East,\n    //% blockIdentity=images.arrowNumber block=\"South East\"\n    SouthEast,\n    //% blockIdentity=images.arrowNumber block=\"South\"\n    South,\n    //% blockIdentity=images.arrowNumber block=\"South West\"\n    SouthWest,\n    //% blockIdentity=images.arrowNumber block=\"West\"\n    West,\n    //% blockIdentity=images.arrowNumber block=\"North West\"\n    NorthWest,\n}\n\nnamespace basic {\n\n    /**\n     * Draws the selected icon on the LED screen\n     * @param icon the predefined icon id\n     * @param interval the amount of time (milliseconds) to show the icon. Default is 600.\n     */\n    //% weight=90 blockGap=8\n    //% blockId=basic_show_icon\n    //% block=\"show icon %i\" icon=\"\\uf00a\"\n    //% parts=\"ledmatrix\"\n    //% help=basic/show-icon\n    //% icon.fieldEditor=\"imagedropdown\"\n    //% icon.fieldOptions.columns=\"5\"\n    //% icon.fieldOptions.width=\"380\"\n    //% icon.fieldOptions.maxRows=4\n    export function showIcon(icon: IconNames, interval = 600) {\n        let res = images.iconImage(icon)\n        res.showImage(0, interval)\n    }\n\n    /**\n     * Draws an arrow on the LED screen\n     * @param direction the direction of the arrow\n     * @param interval the amount of time (milliseconds) to show the icon. Default is 600.\n     */\n    //% weight=50 blockGap=8\n    //% blockId=basic_show_arrow\n    //% block=\"show arrow %i=device_arrow\"\n    //% parts=\"ledmatrix\"\n    //% help=basic/show-arrow\n    export function showArrow(direction: number, interval = 600) {\n        let res = images.arrowImage(direction)\n        res.showImage(0, interval)\n    }\n}\n\n\nnamespace images {\n\n    //% weight=50 blockGap=8\n    //% help=images/arrow-image\n    //% blockId=builtin_arrow_image block=\"arrow image %i\"\n    export function arrowImage(i: ArrowNames): Image {\n        switch (i) {\n            // compass directions\n            case ArrowNames.North: return images.createImage(`\n                                        . . # . .\n                                        . # # # .\n                                        # . # . #\n                                        . . # . .\n                                        . . # . .`);\n            case ArrowNames.NorthEast: return images.createImage(`\n                                        . . # # #\n                                        . . . # #\n                                        . . # . #\n                                        . # . . .\n                                        # . . . .`);\n            case ArrowNames.East: return images.createImage(`\n                                        . . # . .\n                                        . . . # .\n                                        # # # # #\n                                        . . . # .\n                                        . . # . .`);\n            case ArrowNames.SouthEast: return images.createImage(`\n                                        # . . . .\n                                        . # . . .\n                                        . . # . #\n                                        . . . # #\n                                        . . # # #`);\n            case ArrowNames.South: return images.createImage(`\n                                        . . # . .\n                                        . . # . .\n                                        # . # . #\n                                        . # # # .\n                                        . . # . .`);\n            case ArrowNames.SouthWest: return images.createImage(`\n                                        . . . . #\n                                        . . . # .\n                                        # . # . .\n                                        # # . . .\n                                        # # # . .`);\n            case ArrowNames.West: return images.createImage(`\n                                        . . # . .\n                                        . # . . .\n                                        # # # # #\n                                        . # . . .\n                                        . . # . .`);\n            case ArrowNames.NorthWest: return images.createImage(`\n                                        # # # . .\n                                        # # . . .\n                                        # . # . .\n                                        . . . # .\n                                        . . . . #`);\n            default: return images.createImage(`\n                                        . . . . .\n                                        . . . . .\n                                        . . . . .\n                                        . . . . .\n                                        . . . . .\n                                        `);\n        }\n    }\n\n    //% weight=50 blockGap=8\n    //% help=images/icon-image\n    //% blockId=builtin_image block=\"icon image %i\"\n    //% i.fieldEditor=\"imagedropdown\"\n    //% i.fieldOptions.columns=\"5\"\n    //% i.fieldOptions.width=\"380\"\n    //% i.fieldOptions.maxRows=4\n    export function iconImage(i: IconNames): Image {\n        switch (i) {\n            case IconNames.Heart: return images.createImage(`\n                                        . # . # .\n                                        # # # # #\n                                        # # # # #\n                                        . # # # .\n                                        . . # . .`);\n\n            case IconNames.SmallHeart: return images.createImage(`\n                                        . . . . .\n                                        . # . # .\n                                        . # # # .\n                                        . . # . .\n                                        . . . . .`);\n            //faces\n            case IconNames.Happy: return images.createImage(`\n                                        . . . . .\n                                        . # . # .\n                                        . . . . .\n                                        # . . . #\n                                        . # # # .`);\n            case IconNames.Sad: return images.createImage(`\n                                        . . . . .\n                                        . # . # .\n                                        . . . . .\n                                        . # # # .\n                                        # . . . #`);\n            case IconNames.Confused: return images.createImage(`\n                                        . . . . .\n                                        . # . # .\n                                        . . . . .\n                                        . # . # .\n                                        # . # . #`);\n            case IconNames.Angry: return images.createImage(`\n                                        # . . . #\n                                        . # . # .\n                                        . . . . .\n                                        # # # # #\n                                        # . # . #`);\n            case IconNames.Asleep: return images.createImage(`\n                                        . . . . .\n                                        # # . # #\n                                        . . . . .\n                                        . # # # .\n                                        . . . . .`);\n            case IconNames.Surprised: return images.createImage(`\n                                        . # . # .\n                                        . . . . .\n                                        . . # . .\n                                        . # . # .\n                                        . . # . .`);\n            case IconNames.Silly: return images.createImage(`\n                                        # . . . #\n                                        . . . . .\n                                        # # # # #\n                                        . . . # #\n                                        . . . # #`);\n            case IconNames.Fabulous: return images.createImage(`\n                                        # # # # #\n                                        # # . # #\n                                        . . . . .\n                                        . # . # .\n                                        . # # # .`);\n            case IconNames.Meh: return images.createImage(`\n                                        # # . # #\n                                        . . . . .\n                                        . . . # .\n                                        . . # . .\n                                        . # . . .`);\n            case IconNames.Yes: return images.createImage(`\n                                        . . . . .\n                                        . . . . #\n                                        . . . # .\n                                        # . # . .\n                                        . # . . .`);\n            case IconNames.No: return images.createImage(`\n                                        # . . . #\n                                        . # . # .\n                                        . . # . .\n                                        . # . # .\n                                        # . . . #`);\n            case IconNames.Triangle: return images.createImage(`\n                                        . . . . .\n                                        . . # . .\n                                        . # . # .\n                                        # # # # #\n                                        . . . . .`);\n            case IconNames.LeftTriangle: return images.createImage(`\n                                        # . . . .\n                                        # # . . .\n                                        # . # . .\n                                        # . . # .\n                                        # # # # #`);\n            case IconNames.Chessboard: return images.createImage(`\n                                        . # . # .\n                                        # . # . #\n                                        . # . # .\n                                        # . # . #\n                                        . # . # .`);\n            case IconNames.Diamond: return images.createImage(`\n                                        . . # . .\n                                        . # . # .\n                                        # . . . #\n                                        . # . # .\n                                        . . # . .`);\n            case IconNames.SmallDiamond: return images.createImage(`\n                                        . . . . .\n                                        . . # . .\n                                        . # . # .\n                                        . . # . .\n                                        . . . . .`);\n            case IconNames.Square: return images.createImage(`\n                                        # # # # #\n                                        # . . . #\n                                        # . . . #\n                                        # . . . #\n                                        # # # # #`);\n            case IconNames.SmallSquare: return images.createImage(`\n                                        . . . . .\n                                        . # # # .\n                                        . # . # .\n                                        . # # # .\n                                        . . . . .`);\n\n            case IconNames.Scissors: return images.createImage(`\n                                        # # . . #\n                                        # # . # .\n                                        . . # . .\n                                        # # . # .\n                                        # # . . #`);\n            // The following images were designed by Abbie Brooks.\n            case IconNames.TShirt: return images.createImage(`\n                                        # # . # #\n                                        # # # # #\n                                        . # # # .\n                                        . # # # .\n                                        . # # # .`);\n            case IconNames.Rollerskate: return images.createImage(`\n                                        . . . # #\n                                        . . . # #\n                                        # # # # #\n                                        # # # # #\n                                        . # . # .`);\n            case IconNames.Duck: return images.createImage(`\n                                        . # # . .\n                                        # # # . .\n                                        . # # # #\n                                        . # # # .\n                                        . . . . .`);\n            case IconNames.House: return images.createImage(`\n                                        . . # . .\n                                        . # # # .\n                                        # # # # #\n                                        . # # # .\n                                        . # . # .`);\n            case IconNames.Tortoise: return images.createImage(`\n                                        . . . . .\n                                        . # # # .\n                                        # # # # #\n                                        . # . # .\n                                        . . . . .`);\n            case IconNames.Butterfly: return images.createImage(`\n                                        # # . # #\n                                        # # # # #\n                                        . . # . .\n                                        # # # # #\n                                        # # . # #`);\n            case IconNames.StickFigure: return images.createImage(`\n                                        . . # . .\n                                        # # # # #\n                                        . . # . .\n                                        . # . # .\n                                        # . . . #`);\n            case IconNames.Ghost: return images.createImage(`\n                                        . # # # .\n                                        # . # . #\n                                        # # # # #\n                                        # # # # #\n                                        # . # . #`);\n            case IconNames.Sword: return images.createImage(`\n                                        . . # . .\n                                        . . # . .\n                                        . . # . .\n                                        . # # # .\n                                        . . # . .`);\n            case IconNames.Giraffe: return images.createImage(`\n                                        # # . . .\n                                        . # . . .\n                                        . # . . .\n                                        . # # # .\n                                        . # . # .`);\n            case IconNames.Skull: return images.createImage(`\n                                        . # # # .\n                                        # . # . #\n                                        # # # # #\n                                        . # # # .\n                                        . # # # .`);\n            case IconNames.Umbrella: return images.createImage(`\n                                        . # # # .\n                                        # # # # #\n                                        . . # . .\n                                        # . # . .\n                                        # # # . .`);\n            case IconNames.Snake: return images.createImage(`\n                                        # # . . .\n                                        # # . # #\n                                        . # . # .\n                                        . # # # .\n                                        . . . . .`);\n            // animals\n            case IconNames.Rabbit: return images.createImage(`\n                                        # . # . .\n                                        # . # . .\n                                        # # # # .\n                                        # # . # .\n                                        # # # # .`);\n            case IconNames.Cow: return images.createImage(`\n                                        # . . . #\n                                        # . . . #\n                                        # # # # #\n                                        . # # # .\n                                        . . # . .`);\n            // musical notes\n            case IconNames.QuarterNote: return images.createImage(`\n                                        . . # . .\n                                        . . # . .\n                                        . . # . .\n                                        # # # . .\n                                        # # # . .`);\n            case IconNames.EighthNote: return images.createImage(`\n                                        . . # . .\n                                        . . # # .\n                                        . . # . #\n                                        # # # . .\n                                        # # # . .`);\n            case IconNames.EigthNote: return images.createImage(`\n                                        . . # . .\n                                        . . # # .\n                                        . . # . #\n                                        # # # . .\n                                        # # # . .`);\n            // other icons\n            case IconNames.Pitchfork: return images.createImage(`\n                                        # . # . #\n                                        # . # . #\n                                        # # # # #\n                                        . . # . .\n                                        . . # . .`);\n            case IconNames.Target: return images.createImage(`\n                                        . . # . .\n                                        . # # # .\n                                        # # . # #\n                                        . # # # .\n                                        . . # . .`);\n            default: return images.createImage(`\n                                        . . . . .\n                                        . . . . .\n                                        . . . . .\n                                        . . . . .\n                                        . . . . .\n                                        `);\n        }\n    }\n\n    //% weight=50 blockGap=8\n    //% help=images/arrow-number\n    //% blockId=device_arrow block=\"%arrow\"\n    //% shim=TD_ID\n    export function arrowNumber(arrow: ArrowNames): number {\n        return arrow;\n    }\n}\n","images.cpp":"#include \"pxt.h\"\n\nPXT_VTABLE(RefMImage, ValType::Object)\n\nRefMImage::RefMImage(ImageData *d) : PXT_VTABLE_INIT(RefMImage), img(d) {\n    img->incr();\n}\n\nvoid RefMImage::destroy(RefMImage *t) {\n    t->img->decr();\n}\n\nvoid RefMImage::print(RefMImage *t) {\n    DMESG(\"RefMImage %p size=%d x %d\", t, t->img->width, t->img->height);\n}\n\nvoid RefMImage::makeWritable() {\n    if (img->isReadOnly()) {\n        MicroBitImage i(img);\n        img = i.clone().leakData();\n    }\n}\n\nvoid RefMImage::scan(RefMImage *t) {}\n\nunsigned RefMImage::gcsize(RefMImage *t) {\n    return (sizeof(*t) + 3) >> 2;\n}\n\n/**\n * Creation, manipulation and display of LED images.\n */\n//% color=#7600A8 weight=31 icon=\"\\uf03e\"\n//% advanced=true\nnamespace images {\n/**\n * Creates an image that fits on the LED screen.\n */\n//% weight=75 help=images/create-image\n//% blockId=device_build_image block=\"create image\"\n//% parts=\"ledmatrix\"\nImage createImage(ImageLiteral_ leds) {\n    return NEW_GC(RefMImage, imageBytes(leds));\n}\n\n/**\n * Creates an image with 2 frames.\n */\n//% weight=74 help=images/create-big-image\n//% blockId=device_build_big_image block=\"create big image\" imageLiteral=2\n//% parts=\"ledmatrix\"\nImage createBigImage(ImageLiteral_ leds) {\n    return createImage(leds);\n}\n\n//%\nBuffer charCodeBuffer(int charCode) {\n    if(charCode < MICROBIT_FONT_ASCII_START || charCode > MICROBIT_FONT_ASCII_END)\n        return NULL;\n#if MICROBIT_CODAL\n    auto font = codal::BitmapFont::getSystemFont();\n#else\n    auto font = MicroBitFont::getSystemFont();\n#endif\n    const int offset = (charCode - MICROBIT_FONT_ASCII_START) * 5;;\n    const uint8_t* charBuffer = font.characters + offset;\n    \n    return PXT_CREATE_BUFFER(charBuffer, 5);\n}\n\n} // namespace images\n\nnamespace ImageMethods {\n/**\n * Plots the image at a given column to the screen\n */\n//% help=images/plot-image\n//% parts=\"ledmatrix\"\nvoid plotImage(Image i, int xOffset = 0) {\n    uBit.display.print(MicroBitImage(i->img), -xOffset, 0, 0, 0);\n}\n\n/**\n * Shows an frame from the image at offset ``x offset``.\n * @param xOffset column index to start displaying the image\n * @param interval time in milliseconds to pause after drawing\n */\n//% help=images/show-image weight=80 blockNamespace=images\n//% blockId=device_show_image_offset block=\"show image %sprite(myImage)|at offset %offset ||and interval (ms) %interval\"\n//% interval.defl=400\n//% blockGap=8 parts=\"ledmatrix\" async\nvoid showImage(Image sprite, int xOffset, int interval = 400) {\n    uBit.display.print(MicroBitImage(sprite->img), -xOffset, 0, 0, interval);\n}\n\n/**\n * Draws the ``index``-th frame of the image on the screen.\n * @param xOffset column index to start displaying the image\n */\n//% help=images/plot-frame weight=80\n//% parts=\"ledmatrix\"\nvoid plotFrame(Image i, int xOffset) {\n    // TODO showImage() used in original implementation\n    plotImage(i, xOffset * i->img->height);\n}\n\n/**\n * Scrolls an image .\n * @param frameOffset x offset moved on each animation step, eg: 1, 2, 5\n * @param interval time between each animation step in milli seconds, eg: 200\n */\n//% help=images/scroll-image weight=79 async blockNamespace=images\n//% blockId=device_scroll_image\n//% block=\"scroll image %sprite(myImage)|with offset %frameoffset|and interval (ms) %delay\"\n//% blockGap=8 parts=\"ledmatrix\"\nvoid scrollImage(Image id, int frameOffset, int interval) {\n    MicroBitImage i(id->img);\n    uBit.display.animate(i, interval, frameOffset, MICROBIT_DISPLAY_ANIMATE_DEFAULT_POS, 0);\n}\n\n/**\n * Sets all pixels off.\n */\n//% help=images/clear\n//% parts=\"ledmatrix\"\nvoid clear(Image i) {\n    i->makeWritable();\n    MicroBitImage(i->img).clear();\n}\n\n/**\n * Sets a specific pixel brightness at a given position\n */\n//%\n//% parts=\"ledmatrix\"\nvoid setPixelBrightness(Image i, int x, int y, int value) {\n    i->makeWritable();\n    MicroBitImage(i->img).setPixelValue(x, y, value);\n}\n\n/**\n * Gets the pixel brightness ([0..255]) at a given position\n */\n//%\n//% parts=\"ledmatrix\"\nint pixelBrightness(Image i, int x, int y) {\n    int pix = MicroBitImage(i->img).getPixelValue(x, y);\n    if (pix < 0)\n        return 0;\n    return pix;\n}\n\n/**\n * Gets the width in columns\n */\n//% help=functions/width\nint width(Image i) {\n    return i->img->width;\n}\n\n/**\n * Gets the height in rows (always 5)\n */\n//%\nint height(Image i) {\n    return i->img->height;\n}\n\n/**\n * Set a pixel state at position ``(x,y)``\n * @param x pixel column\n * @param y pixel row\n * @param value pixel state\n */\n//% help=images/set-pixel\n//% parts=\"ledmatrix\"\nvoid setPixel(Image i, int x, int y, bool value) {\n    setPixelBrightness(i, x, y, value ? 255 : 0);\n}\n\n/**\n * Get the pixel state at position ``(x,y)``\n * @param x pixel column\n * @param y pixel row\n */\n//% help=images/pixel\n//% parts=\"ledmatrix\"\nbool pixel(Image i, int x, int y) {\n    return pixelBrightness(i, x, y) > 0;\n}\n\n/**\n * Show a particular frame of the image strip.\n * @param frame image frame to show\n */\n//% weight=70 help=images/show-frame\n//% parts=\"ledmatrix\"\nvoid showFrame(Image i, int frame, int interval = 400) {\n    showImage(i, frame * i->img->height, interval);\n}\n} // namespace ImageMethods","input.cpp":"#include \"pxt.h\"\n\nenum class Button {\n    A = MICROBIT_ID_BUTTON_A,\n    B = MICROBIT_ID_BUTTON_B,\n    //% block=\"A+B\"\n    AB = MICROBIT_ID_BUTTON_AB,\n};\n\nenum class Dimension {\n    //% block=x\n    X = 0,\n    //% block=y\n    Y = 1,\n    //% block=z\n    Z = 2,\n    //% block=strength\n    Strength = 3,\n};\n\nenum class Rotation {\n    //% block=pitch\n    Pitch = 0,\n    //% block=roll\n    Roll = 1,\n};\n\nenum class TouchPin {\n    P0 = MICROBIT_ID_IO_P0,\n    P1 = MICROBIT_ID_IO_P1,\n    P2 = MICROBIT_ID_IO_P2,\n};\n\nenum class AcceleratorRange {\n    /**\n     * The accelerator measures forces up to 1 gravity\n     */\n    //%  block=\"1g\"\n    OneG = 1,\n    /**\n     * The accelerator measures forces up to 2 gravity\n     */\n    //%  block=\"2g\"\n    TwoG = 2,\n    /**\n     * The accelerator measures forces up to 4 gravity\n     */\n    //% block=\"4g\"\n    FourG = 4,\n    /**\n     * The accelerator measures forces up to 8 gravity\n     */\n    //% block=\"8g\"\n    EightG = 8\n};\n\nenum class Gesture {\n    /**\n     * Raised when shaken\n     */\n    //% block=shake\n    //% jres=gestures.shake\n    Shake = MICROBIT_ACCELEROMETER_EVT_SHAKE,\n    /**\n     * Raised when the logo is upward and the screen is vertical\n     */\n    //% block=\"logo up\"\n    //% jres=gestures.tiltforward\n    LogoUp = MICROBIT_ACCELEROMETER_EVT_TILT_UP,\n    /**\n     * Raised when the logo is downward and the screen is vertical\n     */\n    //% block=\"logo down\"\n    //% jres=gestures.tiltbackwards\n    LogoDown = MICROBIT_ACCELEROMETER_EVT_TILT_DOWN,\n    /**\n     * Raised when the screen is pointing up and the board is horizontal\n     */\n    //% block=\"screen up\"\n    //% jres=gestures.frontsideup\n    ScreenUp = MICROBIT_ACCELEROMETER_EVT_FACE_UP,\n    /**\n     * Raised when the screen is pointing down and the board is horizontal\n     */\n    //% block=\"screen down\"\n    //% jres=gestures.backsideup\n    ScreenDown = MICROBIT_ACCELEROMETER_EVT_FACE_DOWN,\n    /**\n     * Raised when the screen is pointing left\n     */\n    //% block=\"tilt left\"\n    //% jres=gestures.tiltleft\n    TiltLeft = MICROBIT_ACCELEROMETER_EVT_TILT_LEFT,\n    /**\n     * Raised when the screen is pointing right\n     */\n    //% block=\"tilt right\"\n    //% jres=gestures.tiltright\n    TiltRight = MICROBIT_ACCELEROMETER_EVT_TILT_RIGHT,\n    /**\n     * Raised when the board is falling!\n     */\n    //% block=\"free fall\"\n    //% jres=gestures.freefall\n    FreeFall = MICROBIT_ACCELEROMETER_EVT_FREEFALL,\n    /**\n    * Raised when a 3G shock is detected\n    */\n    //% block=\"3g\"\n    //% jres=gestures.impact3g\n    ThreeG = MICROBIT_ACCELEROMETER_EVT_3G,\n    /**\n    * Raised when a 6G shock is detected\n    */\n    //% block=\"6g\"\n    //% jres=gestures.impact6g\n    SixG = MICROBIT_ACCELEROMETER_EVT_6G,\n    /**\n    * Raised when a 8G shock is detected\n    */\n    //% block=\"8g\"\n    //% jres=gestures.impact8g\n    EightG = MICROBIT_ACCELEROMETER_EVT_8G\n};\n\nenum class MesDpadButtonInfo {\n    //% block=\"A down\"\n    ADown = MES_DPAD_BUTTON_A_DOWN,\n    //% block=\"A up\"\n    AUp = MES_DPAD_BUTTON_A_UP,\n    //% block=\"B down\"\n    BDown = MES_DPAD_BUTTON_B_DOWN,\n    //% block=\"B up\"\n    BUp = MES_DPAD_BUTTON_B_UP,\n    //% block=\"C down\"\n    CDown = MES_DPAD_BUTTON_C_DOWN,\n    //% block=\"C up\"\n    CUp = MES_DPAD_BUTTON_C_UP,\n    //% block=\"D down\"\n    DDown = MES_DPAD_BUTTON_D_DOWN,\n    //% block=\"D up\"\n    DUp = MES_DPAD_BUTTON_D_UP,\n    //% block=\"1 down\"\n    _1Down = MES_DPAD_BUTTON_1_DOWN,\n    //% block=\"1 up\"\n    _1Up = MES_DPAD_BUTTON_1_UP,\n    //% block=\"2 down\"\n    _2Down = MES_DPAD_BUTTON_2_DOWN,\n    //% block=\"2 up\"\n    _2Up = MES_DPAD_BUTTON_2_UP,\n    //% block=\"3 down\"\n    _3Down = MES_DPAD_BUTTON_3_DOWN,\n    //% block=\"3 up\"\n    _3Up = MES_DPAD_BUTTON_3_UP,\n    //% block=\"4 down\"\n    _4Down = MES_DPAD_BUTTON_4_DOWN,\n    //% block=\"4 up\"\n    _4Up = MES_DPAD_BUTTON_4_UP,\n};\n\n//% color=#D400D4 weight=111 icon=\"\\uf192\"\nnamespace input {\n    /**\n     * Do something when a button (A, B or both A+B) is pushed down and released again.\n     * @param button the button that needs to be pressed\n     * @param body code to run when event is raised\n     */\n    //% help=input/on-button-pressed weight=85 blockGap=16\n    //% blockId=device_button_event block=\"on button|%NAME|pressed\"\n    //% parts=\"buttonpair\"\n    void onButtonPressed(Button button, Action body) {\n        registerWithDal((int)button, MICROBIT_BUTTON_EVT_CLICK, body);\n    }\n\n    /**\n     * Do something when when a gesture is done (like shaking the micro:bit).\n     * @param gesture the type of gesture to track, eg: Gesture.Shake\n     * @param body code to run when gesture is raised\n     */\n    //% help=input/on-gesture weight=84 blockGap=16\n    //% blockId=device_gesture_event block=\"on |%NAME\"\n    //% parts=\"accelerometer\"\n    //% NAME.fieldEditor=\"gestures\" NAME.fieldOptions.columns=4\n    void onGesture(Gesture gesture, Action body) {\n        int gi = (int)gesture;\n        if (gi == MICROBIT_ACCELEROMETER_EVT_3G && uBit.accelerometer.getRange() < 3)\n            uBit.accelerometer.setRange(4);\n        else if ((gi == MICROBIT_ACCELEROMETER_EVT_6G || gi == MICROBIT_ACCELEROMETER_EVT_8G) && uBit.accelerometer.getRange() < 6)\n            uBit.accelerometer.setRange(8);\n        registerWithDal(MICROBIT_ID_GESTURE, gi, body);\n    }\n\n    /**\n    * Tests if a gesture is currently detected.\n     * @param gesture the type of gesture to detect, eg: Gesture.Shake\n    */\n    //% help=input/is-gesture weight=10 blockGap=8\n    //% blockId=deviceisgesture block=\"is %gesture gesture\"\n    //% parts=\"accelerometer\"\n    //% gesture.fieldEditor=\"gestures\" gesture.fieldOptions.columns=4\n    bool isGesture(Gesture gesture) {\n        // turn on acceleration\n        uBit.accelerometer.getX();\n        int gi = (int)gesture;\n        return uBit.accelerometer.getGesture() == gi;\n    }\n\n     /**\n     * Do something when a pin is touched and released again (while also touching the GND pin).\n     * @param name the pin that needs to be pressed, eg: TouchPin.P0\n     * @param body the code to run when the pin is pressed\n     */\n    //% help=input/on-pin-pressed weight=83 blockGap=32\n    //% blockId=device_pin_event block=\"on pin %name|pressed\"\n    void onPinPressed(TouchPin name, Action body) {\n        auto pin = getPin((int)name);\n        if (!pin) return;\n\n        // Forces the PIN to switch to makey-makey style detection.\n        pin->isTouched();\n        registerWithDal((int)name, MICROBIT_BUTTON_EVT_CLICK, body);\n    }\n\n    /**\n     * Do something when a pin is released.\n     * @param name the pin that needs to be released, eg: TouchPin.P0\n     * @param body the code to run when the pin is released\n     */\n    //% help=input/on-pin-released weight=6 blockGap=16\n    //% blockId=device_pin_released block=\"on pin %NAME|released\"\n    //% advanced=true\n    void onPinReleased(TouchPin name, Action body) {\n        auto pin = getPin((int)name);\n        if (!pin) return;\n\n        // Forces the PIN to switch to makey-makey style detection.\n        pin->isTouched();\n        registerWithDal((int)name, MICROBIT_BUTTON_EVT_UP, body);\n    }\n\n    /**\n     * Get the button state (pressed or not) for ``A`` and ``B``.\n     * @param button the button to query the request, eg: Button.A\n     */\n    //% help=input/button-is-pressed weight=60\n    //% block=\"button|%NAME|is pressed\"\n    //% blockId=device_get_button2\n    //% icon=\"\\uf192\" blockGap=8\n    //% parts=\"buttonpair\"\n    bool buttonIsPressed(Button button) {\n      if (button == Button::A)\n        return uBit.buttonA.isPressed();\n      else if (button == Button::B)\n        return uBit.buttonB.isPressed();\n      else if (button == Button::AB)\n        return uBit.buttonAB.isPressed();\n      return false;\n    }\n\n    /**\n     * Get the pin state (pressed or not). Requires to hold the ground to close the circuit.\n     * @param name pin used to detect the touch, eg: TouchPin.P0\n     */\n    //% help=input/pin-is-pressed weight=58\n    //% blockId=\"device_pin_is_pressed\" block=\"pin %NAME|is pressed\"\n    //% blockGap=8\n    bool pinIsPressed(TouchPin name) {\n        auto pin = getPin((int)name);\n        return pin && pin->isTouched();\n    }\n\n    int getAccelerationStrength() {\n        double x = uBit.accelerometer.getX();\n        double y = uBit.accelerometer.getY();\n        double z = uBit.accelerometer.getZ();\n        return (int)sqrt(x*x+y*y+z*z);\n    }\n\n    /**\n     * Get the acceleration value in milli-gravitys (when the board is laying flat with the screen up, x=0, y=0 and z=-1024)\n     * @param dimension x, y, or z dimension, eg: Dimension.X\n     */\n    //% help=input/acceleration weight=58\n    //% blockId=device_acceleration block=\"acceleration (mg)|%NAME\" blockGap=8\n    //% parts=\"accelerometer\"\n    int acceleration(Dimension dimension) {\n      switch (dimension) {\n      case Dimension::X: return uBit.accelerometer.getX();\n      case Dimension::Y: return uBit.accelerometer.getY();\n      case Dimension::Z: return uBit.accelerometer.getZ();\n      case Dimension::Strength: return getAccelerationStrength();\n      }\n      return 0;\n    }\n\n    /**\n     * Reads the light level applied to the LED screen in a range from ``0`` (dark) to ``255`` bright.\n     */\n    //% help=input/light-level weight=57\n    //% blockId=device_get_light_level block=\"light level\" blockGap=8\n    //% parts=\"ledmatrix\"\n    int lightLevel() {\n        return uBit.display.readLightLevel();\n    }\n\n    /**\n     * Get the current compass heading in degrees.\n     */\n    //% help=input/compass-heading\n    //% weight=56\n    //% blockId=device_heading block=\"compass heading (°)\" blockGap=8\n    //% parts=\"compass\"\n    int compassHeading() {\n        return uBit.compass.heading();\n    }\n\n\n    /**\n     * Gets the temperature in Celsius degrees (°C).\n     */\n    //% weight=55\n    //% help=input/temperature\n    //% blockId=device_temperature block=\"temperature (°C)\" blockGap=8\n    //% parts=\"thermometer\"\n    int temperature() {\n        return uBit.thermometer.getTemperature();\n    }\n\n    /**\n     * The pitch or roll of the device, rotation along the ``x-axis`` or ``y-axis``, in degrees.\n     * @param kind pitch or roll\n     */\n    //% help=input/rotation weight=52\n    //% blockId=device_get_rotation block=\"rotation (°)|%NAME\" blockGap=8\n    //% parts=\"accelerometer\" advanced=true\n    int rotation(Rotation kind) {\n      switch (kind) {\n      case Rotation::Pitch: return uBit.accelerometer.getPitch();\n      case Rotation::Roll: return uBit.accelerometer.getRoll();\n      }\n      return 0;\n    }\n\n    /**\n     * Get the magnetic force value in ``micro-Teslas`` (``µT``). This function is not supported in the simulator.\n     * @param dimension the x, y, or z dimension, eg: Dimension.X\n     */\n    //% help=input/magnetic-force weight=54\n    //% blockId=device_get_magnetic_force block=\"magnetic force (µT)|%NAME\" blockGap=8\n    //% parts=\"compass\"\n    //% advanced=true\n    TNumber magneticForce(Dimension dimension) {\n        /* https://github.com/microsoft/pxt-microbit/issues/4995\n        if (!uBit.compass.isCalibrated())\n            uBit.compass.calibrate();\n        */\n        double d = 0;        \n        switch (dimension) {\n            case Dimension::X: d = uBit.compass.getX(); break;\n            case Dimension::Y: d = uBit.compass.getY(); break;\n            case Dimension::Z: d = uBit.compass.getZ(); break;\n            case Dimension::Strength: d = uBit.compass.getFieldStrength() ; break;\n        }\n        return fromDouble(d / 1000.0);\n    }\n\n    /**\n     * Obsolete, compass calibration is automatic.\n     */\n    //% help=input/calibrate-compass advanced=true\n    //% blockId=\"input_compass_calibrate\" block=\"calibrate compass\"\n    //% weight=55\n    void calibrateCompass() {\n        uBit.compass.calibrate();\n    }\n\n    /**\n     * Sets the accelerometer sample range in gravities.\n     * @param range a value describe the maximum strengh of acceleration measured\n     */\n    //% help=input/set-accelerometer-range\n    //% blockId=device_set_accelerometer_range block=\"set accelerometer|range %range\"\n    //% weight=5\n    //% parts=\"accelerometer\"\n    //% advanced=true\n    void setAccelerometerRange(AcceleratorRange range) {\n        uBit.accelerometer.setRange((int)range);\n    }\n}\n","input.ts":"/**\n * Events and data from sensors\n */\n//% color=#D400D4 weight=111 icon=\"\\uf192\"\nnamespace input {\n    /**\n     * Attaches code to run when the screen is facing up.\n     * @param body TODO\n     */\n    //% help=input/on-screen-up\n    export function onScreenUp(body: () => void): void {\n        onGesture(Gesture.ScreenUp, body);\n    }\n\n    /**\n     * Attaches code to run when the screen is facing down.\n     * @param body TODO\n     */\n    //% help=input/on-screen-down\n    export function onScreenDown(body: () => void): void {\n        onGesture(Gesture.ScreenDown, body);\n    }\n\n    /**\n     * Attaches code to run when the device is shaken.\n     * @param body TODO\n     */\n    //% deprecated=true\n    //% help=input/on-shake\n    export function onShake(body: () => void): void {\n        onGesture(Gesture.Shake, body);\n    }\n\n    /**\n     * Attaches code to run when the logo is oriented upwards and the board is vertical.\n     * @param body TODO\n     */\n    //% help=input/on-logo-up\n    export function onLogoUp(body: () => void): void {\n        onGesture(Gesture.LogoUp, body);\n    }\n\n    /**\n     * Attaches code to run when the logo is oriented downwards and the board is vertical.\n     * @param body TODO\n     */\n    //% help=input/on-logo-down\n    export function onLogoDown(body: () => void): void {\n        onGesture(Gesture.LogoDown, body);\n    }\n\n    /**\n     * Obsolete, use input.calibrateCompass instead.\n     */\n    //% weight=0 help=input/calibrate-compass\n    export function calibrate() {\n        input.calibrateCompass();\n    }\n\n\n    /**\n     * Gets the number of milliseconds elapsed since power on.\n     */\n    //% help=input/running-time weight=50 blockGap=8\n    //% blockId=device_get_running_time block=\"running time (ms)\"\n    //% advanced=true\n    export function runningTime() {\n        return control.millis();\n    }\n\n    /**\n     * Gets the number of microseconds elapsed since power on.\n     */\n    //% help=input/running-time-micros weight=49\n    //% blockId=device_get_running_time_micros block=\"running time (micros)\"\n    //% advanced=true\n    export function runningTimeMicros() {\n        return control.micros();\n    }\n}\n","interval.ts":"namespace control {\n    export enum IntervalMode {\n        Interval,\n        Timeout,\n        Immediate\n    }\n\n    let _intervals: Interval[] = undefined;\n    class Interval {\n\n        id: number;\n        func: () => void;\n        delay: number;\n        mode: IntervalMode;\n\n        constructor(func: () => void, delay: number, mode: IntervalMode) {\n            this.id = _intervals.length == 0\n                ? 1 : _intervals[_intervals.length - 1].id + 1;\n            this.func = func;\n            this.delay = delay;\n            this.mode = mode;\n            _intervals.push(this);\n\n            control.runInParallel(() => this.work());\n        }\n\n        work() {\n            // execute\n            switch (this.mode) {\n                case IntervalMode.Immediate:\n                case IntervalMode.Timeout:\n                    if (this.delay > 0)\n                        pause(this.delay); // timeout\n                    if (this.delay >= 0) // immediate, timeout\n                        this.func();\n                    break;\n                case IntervalMode.Interval:\n                    while (this.delay > 0) {\n                        pause(this.delay);\n                        // might have been cancelled during this duration\n                        if (this.delay > 0)\n                            this.func();\n                    }\n                    break;\n            }\n            // remove from interval array\n            _intervals.removeElement(this);\n        }\n\n        cancel() {\n            this.delay = -1;\n        }\n    }\n\n    export function setInterval(func: () => void, delay: number, mode: IntervalMode): number {\n        if (!func || delay < 0) return 0;\n        if (!_intervals) _intervals = [];\n        const interval = new Interval(func, delay, mode);\n        return interval.id;\n    }\n\n    export function clearInterval(intervalId: number, mode: IntervalMode): void {\n        if (!_intervals) return;\n        for (let i = 0; i < _intervals.length; ++i) {\n            const it = _intervals[i];\n            if (it.id == intervalId && it.mode == mode) {\n                it.cancel();\n                break;\n            }\n        }\n    }\n}","json.ts":"namespace JSON {\n    export function parseIntRadix(s: string, base?: number) {\n        if (base == null || base == 10) {\n            return parseFloat(s) | 0\n        }\n\n        let m = false\n        let r = 0\n        for (let i = 0; i < s.length; ++i) {\n            let c = s.charCodeAt(i)\n            if (c == 0x20 || c == 10 || c == 13 || c == 9)\n                continue\n            if (r == 0 && !m && c == 0x2d) {\n                m = true\n                continue\n            }\n\n            let v = -1\n            if (0x30 <= c && c <= 0x39)\n                v = c - 0x30\n            else {\n                c |= 0x20\n                if (0x61 <= c && c <= 0x7a)\n                    v = c - 0x61 + 10\n            }\n\n            if (0 <= v && v < base) {\n                r *= base\n                r += v\n            } else {\n                return undefined\n            }\n        }\n\n        return m ? -r : r\n    }\n\n\n    class Parser {\n        ptr: number\n        s: string\n        errorMsg: string\n\n        error(msg: string) {\n            if (!this.errorMsg) {\n                this.errorMsg = msg + \" at position \" + this.ptr\n                this.ptr = this.s.length\n            }\n        }\n\n        skipWS() {\n            for (; ;) {\n                const c = this.nextChar()\n                if (c == 0x20 || c == 0x0a || c == 0x0d || c == 0x09) {\n                    // OK\n                } else {\n                    this.ptr--\n                    return c\n                }\n            }\n        }\n\n        nextChar() {\n            if (this.ptr < this.s.length)\n                return this.s.charCodeAt(this.ptr++)\n            return 0\n        }\n\n        doString() {\n            let r = \"\"\n            this.ptr++\n            for (; ;) {\n                const c = this.s.charAt(this.ptr++)\n                if (c == \"\\\"\")\n                    return r\n                if (c == \"\\\\\") {\n                    let q = this.s.charAt(this.ptr++)\n                    if (q == \"b\") q = \"\\b\"\n                    else if (q == \"n\") q = \"\\n\"\n                    else if (q == \"r\") q = \"\\r\"\n                    else if (q == \"t\") q = \"\\t\"\n                    else if (q == \"u\") {\n                        q = String.fromCharCode(parseIntRadix(this.s.slice(this.ptr, this.ptr + 4), 16))\n                        this.ptr += 4\n                    }\n                    r += q\n                } else {\n                    r += c\n                }\n            }\n        }\n\n        doArray(): any[] {\n            const r = []\n            this.ptr++\n            for (; ;) {\n                let c = this.skipWS()\n                if (c == 0x5d) {\n                    this.ptr++\n                    return r\n                }\n                const v = this.value()\n                if (this.errorMsg)\n                    return null\n                r.push(v)\n                c = this.skipWS()\n                if (c == 0x2c) {\n                    this.ptr++\n                    continue\n                }\n                if (c == 0x5d)\n                    continue\n                this.error(\"expecting comma\")\n            }\n        }\n\n        doObject() {\n            const r: any = {}\n            this.ptr++\n            for (; ;) {\n                let c = this.skipWS()\n                if (c == 0x7d) {\n                    this.ptr++\n                    return r\n                }\n                if (c != 0x22) {\n                    this.error(\"expecting key\")\n                    return r\n                }\n                const k = this.doString()\n                c = this.skipWS()\n                if (c != 0x3a) {\n                    this.error(\"expecting colon\")\n                    return r\n                }\n                this.ptr++\n                const v = this.value()\n                if (this.errorMsg)\n                    return null\n                r[k] = v\n                c = this.skipWS()\n                if (c == 0x2c) {\n                    this.ptr++\n                    continue\n                }\n                if (c == 0x7d)\n                    continue\n                this.error(\"expecting comma, got \" + String.fromCharCode(c))\n            }\n        }\n\n        doNumber() {\n            const beg = this.ptr\n            for (; ;) {\n                const c = this.nextChar()\n                if ((0x30 <= c && c <= 0x39) || c == 0x2b || c == 0x2d || c == 0x2e || c == 0x45 || c == 0x65) {\n                    // one more\n                } else {\n                    this.ptr--\n                    break\n                }\n            }\n            const ss = this.s.slice(beg, this.ptr)\n            if (ss.length == 0) {\n                this.error(\"expecting number\")\n                return 0\n            }\n            return parseFloat(ss)\n        }\n\n        checkKw(k: string) {\n            if (this.s.slice(this.ptr, this.ptr + k.length) == k) {\n                this.ptr += k.length\n                return true\n            }\n            return false\n        }\n\n        value() {\n            if (this.errorMsg)\n                return null\n\n            const c = this.skipWS()\n            if (c == 0x7b)\n                return this.doObject()\n            else if (c == 0x5b)\n                return this.doArray()\n            else if ((0x30 <= c && c <= 0x39) || c == 0x2d)\n                return this.doNumber()\n            else if (c == 0x22)\n                return this.doString()\n            else if (c == 0x74 && this.checkKw(\"true\"))\n                return true\n            else if (c == 0x66 && this.checkKw(\"false\"))\n                return false\n            else if (c == 0x6e && this.checkKw(\"null\"))\n                return null\n\n            this.error(\"unexpected token\")\n            return null\n        }\n    }\n\n    class Stringifier {\n        currIndent: string\n        indentStep: string\n        indent: number\n\n        doString(s: string) {\n            let r = \"\\\"\"\n            for (let i = 0; i < s.length; ++i) {\n                let c = s[i]\n                if (c == \"\\n\") c = \"\\\\n\"\n                else if (c == \"\\r\") c = \"\\\\r\"\n                else if (c == \"\\t\") c = \"\\\\t\"\n                else if (c == \"\\b\") c = \"\\\\b\"\n                else if (c == \"\\\\\") c = \"\\\\\\\\\"\n                else if (c == \"\\\"\") c = \"\\\\\\\"\"\n                r += c\n            }\n            return r + \"\\\"\"\n        }\n\n        go(v: any) {\n            const t = typeof v\n            if (t == \"string\")\n                return this.doString(v)\n            else if (t == \"boolean\" || t == \"number\" || v == null)\n                return \"\" + v\n            else if (Array.isArray(v)) {\n                const arr = v as any[]\n                if (arr.length == 0)\n                    return \"[]\"\n                else {\n                    let r = \"[\"\n                    if (this.indent) {\n                        this.currIndent += this.indentStep\n                        r += \"\\n\"\n                    }\n                    for (let i = 0; i < arr.length; ++i) {\n                        r += this.currIndent + this.go(arr[i])\n                        if (i != arr.length - 1)\n                            r += \",\"\n                        if (this.indent)\n                            r += \"\\n\"\n                    }\n                    if (this.indent)\n                        this.currIndent = this.currIndent.slice(this.indent)\n                    r += this.currIndent + \"]\"\n                    return r\n                }\n            } else {\n                const keys = Object.keys(v)\n                if (keys.length == 0)\n                    return \"{}\"\n\n                let r = \"{\"\n                if (this.indent) {\n                    this.currIndent += this.indentStep\n                    r += \"\\n\"\n                }\n                for (let i = 0; i < keys.length; ++i) {\n                    const k = keys[i]\n                    r += this.currIndent + this.doString(k)\n                    if (this.indent)\n                        r += \": \"\n                    else\n                        r += \":\"\n                    r += this.go(v[k])\n                    if (i != keys.length - 1)\n                        r += \",\"\n                    if (this.indent)\n                        r += \"\\n\"\n                }\n                if (this.indent)\n                    this.currIndent = this.currIndent.slice(this.indent)\n                r += this.currIndent + \"}\"\n                return r\n            }\n        }\n    }\n\n    /**\n     * Converts a JavaScript value to a JavaScript Object Notation (JSON) string.\n     * @param value A JavaScript value, usually an object or array, to be converted.\n     * @param replacer Not supported; use null.\n     * @param indent Adds indentation, white space, and line break characters to the return-value JSON text to make it easier to read.\n     */\n    export function stringify(value: any, replacer: any = null, indent: number = 0) {\n        const ss = new Stringifier()\n        ss.currIndent = \"\"\n        indent |= 0\n        if (indent < 0) indent = 0\n        if (indent > 10) indent = 10\n        ss.indentStep = \"\"\n        ss.currIndent = \"\"\n        ss.indent = indent\n        while (indent-- > 0)\n            ss.indentStep += \" \"\n        return ss.go(value)\n    }\n\n\n    /**\n     * Converts a JavaScript Object Notation (JSON) string into an object.\n     * @param text A valid JSON string.\n     */\n    export function parse(s: string) {\n        const p = new Parser()\n        p.ptr = 0\n        p.s = s\n        const r = p.value()\n        if (p.skipWS()) {\n            p.error(\"excessive input\")\n        }\n        if (p.errorMsg) {\n            control.dmesg(\"Invalid JSON: \" + p.errorMsg)\n            return undefined\n        }\n        return r\n    }\n}\n","led.cpp":"#include \"pxt.h\"\n\nenum class DisplayMode_ {\n    //% block=\"black and white\"\n    BlackAndWhite = DISPLAY_MODE_BLACK_AND_WHITE,\n    //% blockHidden=true\n    BackAndWhite = DISPLAY_MODE_BLACK_AND_WHITE,\n    //% block=\"greyscale\"\n    Greyscale = DISPLAY_MODE_GREYSCALE,\n    // TODO DISPLAY_MODE_BLACK_AND_WHITE_LIGHT_SENSE\n};\n\n//% color=#7600A8 weight=101 icon=\"\\uf205\"\nnamespace led {\n\n    /**\n     * Turn on the specified LED using x, y coordinates (x is horizontal, y is vertical). (0,0) is upper left.\n     * @param x the horizontal coordinate of the LED starting at 0\n     * @param y the vertical coordinate of the LED starting at 0\n     */\n    //% help=led/plot weight=78\n    //% blockId=device_plot block=\"plot|x %x|y %y\" blockGap=8\n    //% parts=\"ledmatrix\"\n    //% x.min=0 x.max=4 y.min=0 y.max=4\n    //% x.fieldOptions.precision=1 y.fieldOptions.precision=1\n    void plot(int x, int y) {\n      uBit.display.image.setPixelValue(x, y, 0xff);\n    }\n\n    /**\n     * Turn on the specified LED with specific brightness using x, y coordinates (x is horizontal, y is vertical). (0,0) is upper left.\n     * @param x the horizontal coordinate of the LED starting at 0\n     * @param y the vertical coordinate of the LED starting at 0\n     * @param brightness the brightness from 0 (off) to 255 (bright), eg:255\n     */\n    //% help=led/plot-brightness weight=78\n    //% blockId=device_plot_brightness block=\"plot|x %x|y %y|brightness %brightness\" blockGap=8\n    //% parts=\"ledmatrix\"\n    //% x.min=0 x.max=4 y.min=0 y.max=4 brightness.min=0 brightness.max=255\n    //% x.fieldOptions.precision=1 y.fieldOptions.precision=1\n    //% advanced=true\n    void plotBrightness(int x, int y, int brightness) {\n        brightness = max(0, min(0xff, brightness));\n        // enable greyscale as needed\n        if (brightness != 0 && brightness != 0xff && uBit.display.getDisplayMode() != DISPLAY_MODE_GREYSCALE)\n            uBit.display.setDisplayMode(DISPLAY_MODE_GREYSCALE);\n        uBit.display.image.setPixelValue(x, y, brightness);\n    }\n\n    /**\n     * Turn off the specified LED using x, y coordinates (x is horizontal, y is vertical). (0,0) is upper left.\n     * @param x the horizontal coordinate of the LED\n     * @param y the vertical coordinate of the LED\n     */\n    //% help=led/unplot weight=77\n    //% blockId=device_unplot block=\"unplot|x %x|y %y\" blockGap=8\n    //% parts=\"ledmatrix\"\n    //% x.min=0 x.max=4 y.min=0 y.max=4\n    //% x.fieldOptions.precision=1 y.fieldOptions.precision=1\n    void unplot(int x, int y) {\n      uBit.display.image.setPixelValue(x, y, 0);\n    }\n\n    /**\n     * Get the brightness state of the specified LED using x, y coordinates. (0,0) is upper left.\n     * @param x the horizontal coordinate of the LED\n     * @param y the vertical coordinate of the LED\n     */\n    //% help=led/point-brightness weight=76\n    //% blockId=device_point_brightness block=\"point|x %x|y %y brightness\"\n    //% parts=\"ledmatrix\"\n    //% x.min=0 x.max=4 y.min=0 y.max=4\n    //% x.fieldOptions.precision=1 y.fieldOptions.precision=1\n    //% advanced=true\n    int pointBrightness(int x, int y) {\n      return uBit.display.image.getPixelValue(x, y);\n    }\n\n    /**\n     * Get the screen brightness from 0 (off) to 255 (full bright).\n     */\n    //% help=led/brightness weight=60\n    //% blockId=device_get_brightness block=\"brightness\" blockGap=8\n    //% parts=\"ledmatrix\"\n    //% advanced=true\n    int brightness() {\n      return uBit.display.getBrightness();\n    }\n\n    /**\n     * Set the screen brightness from 0 (off) to 255 (full bright).\n     * @param value the brightness value, eg:255, 127, 0\n     */\n    //% help=led/set-brightness weight=59\n    //% blockId=device_set_brightness block=\"set brightness %value\"\n    //% parts=\"ledmatrix\"\n    //% advanced=true\n    //% value.min=0 value.max=255\n    void setBrightness(int value) {\n       uBit.display.setBrightness(value);\n    }\n\n    /**\n     * Cancels the current animation and clears other pending animations.\n     */\n    //% weight=50 help=led/stop-animation\n    //% blockId=device_stop_animation block=\"stop animation\"\n    //% parts=\"ledmatrix\"\n    //% advanced=true\n    void stopAnimation() {\n       uBit.display.stopAnimation();\n    }\n\n    /**\n     * Sets the display mode between black and white and greyscale for rendering LEDs.\n     * @param mode mode the display mode in which the screen operates\n     */\n    //% weight=1 help=led/set-display-mode\n    //% parts=\"ledmatrix\" advanced=true weight=1\n    //% blockId=\"led_set_display_mode\" block=\"set display mode $mode\"\n    void setDisplayMode(DisplayMode_ mode) {\n        uBit.display.setDisplayMode((DisplayMode)mode);\n    }\n\n    /**\n    * Gets the current display mode\n    */\n    //% weight=1 parts=\"ledmatrix\" advanced=true\n    DisplayMode_ displayMode() {\n        return (DisplayMode_)uBit.display.getDisplayMode();\n    }\n\n    /**\n    * Turns on or off the display\n    */\n    //% help=led/enable blockId=device_led_enable block=\"led enable %on\"\n    //% advanced=true parts=\"ledmatrix\"\n    void enable(bool on) {\n        if (on) uBit.display.enable();\n        else uBit.display.disable();\n    }\n\n    /**\n     * Takes a screenshot of the LED screen and returns an image.\n     */\n    //% help=led/screenshot\n    //% parts=\"ledmatrix\"\n    Image screenshot() {\n        auto d = uBit.display.screenShot().leakData();\n        auto r = NEW_GC(RefMImage, d);\n        d->decr();\n        return r;\n        /*\n        let Image img;\n        img = image.createImage(\"\");\n        for (let i = 0; i < 5; i++) {\n            for (let j = 0; j < 5; j++) {\n                if (led.point(i, j)) {\n                    img.setPixel(i, j, true);\n                }\n            }\n        }\n        return img;\n        */\n    }\n}\n","led.ts":"/**\n * Control of the LED screen.\n */\n//% color=#5C2D91 weight=101 icon=\"\\uf205\"\nnamespace led {\n    /**\n     * Get the on/off state of the specified LED using x, y coordinates. (0,0) is upper left.\n     * @param x the horizontal coordinate of the LED\n     * @param y the vertical coordinate of the LED\n     */\n    //% help=led/point weight=76\n    //% blockId=device_point block=\"point|x %x|y %y\"\n    //% parts=\"ledmatrix\"\n    //% x.min=0 x.max=4 y.min=0 y.max=4\n    //% x.fieldOptions.precision=1 y.fieldOptions.precision=1\n    export function point(x: number, y: number): boolean {\n        return led.pointBrightness(x, y) > 0;\n    }\n\n    // what's the current high value\n    let barGraphHigh = 0;\n    // when was the current high value recorded\n    let barGraphHighLast = 0;\n\n    /**\n     * Controls where plotbargraph prints to the console\n     **/\n    export let barGraphToConsole = true\n\n    /**\n     * Displays a vertical bar graph based on the `value` and `high` value.\n     * If `high` is 0, the chart gets adjusted automatically.\n     * @param value current value to plot\n     * @param high maximum value. If 0, maximum value adjusted automatically, eg: 0\n     * @param valueToConsole if true, prints value to the serial port\n     */\n    //% help=led/plot-bar-graph weight=20\n    //% blockId=device_plot_bar_graph block=\"plot bar graph of $value up to $high|| serial write $valueToConsole\" icon=\"\\uf080\" blockExternalInputs=true\n    //% parts=\"ledmatrix\"\n    //% valueToConsole.shadow=toggleOnOff\n    //% valueToConsole.defl=true\n    export function plotBarGraph(value: number, high: number, valueToConsole?: boolean): void {\n        if (valueToConsole == undefined) {\n            valueToConsole = barGraphToConsole;\n        }\n        const now = input.runningTime();\n        if (valueToConsole)\n            console.logValue(\"\", value);\n        if (isNaN(value)) {\n            basic.clearScreen()\n            return\n        }\n        value = Math.abs(value);\n\n        // auto-scale \"high\" is not provided\n        if (high > 0) {\n            barGraphHigh = high;\n        } else if (value > barGraphHigh || now - barGraphHighLast > 10000) {\n            barGraphHigh = value;\n            barGraphHighLast = now;\n        }\n\n        // normalize lack of data to 0..1\n        if (barGraphHigh < 16 * Number.EPSILON)\n            barGraphHigh = 1;\n\n        // normalize value to 0..1\n        const v = value / barGraphHigh;\n        const dv = 1 / 16;\n        let k = 0;\n        for (let y = 4; y >= 0; --y) {\n            for (let x = 0; x < 3; ++x) {\n                if (k > v) {\n                    unplot(2 - x, y);\n                    unplot(2 + x, y);\n                } else {\n                    plot(2 - x, y);\n                    plot(2 + x, y);\n                }\n                k += dv;\n            }\n        }\n    }\n\n    /**\n     * Toggles a particular pixel\n     * @param x pixel column\n     * @param y pixel row\n     */\n    //% help=led/toggle weight=77\n    //% blockId=device_led_toggle block=\"toggle|x %x|y %y\" icon=\"\\uf204\" blockGap=8\n    //% parts=\"ledmatrix\"\n    //% x.min=0 x.max=4 y.min=0 y.max=4\n    //% x.fieldOptions.precision=1 y.fieldOptions.precision=1\n    export function toggle(x: number, y: number): void {\n        if (led.point(x, y)) {\n            led.unplot(x, y);\n        } else {\n            led.plot(x, y);\n        }\n    }\n\n    /**\n     * Turns all LEDS on\n     */\n    //% help=led/plot-all\n    //% parts=\"ledmatrix\"\n    export function plotAll(): void {\n        for (let i = 0; i < 5; i++) {\n            for (let j = 0; j < 5; j++) {\n                led.plot(i, j);\n            }\n        }\n    }\n\n    /**\n     * Inverts the current LED display\n     */\n    //% help=led/toggle-all\n    //% parts=\"ledmatrix\"\n    export function toggleAll(): void {\n        for (let i = 0; i < 5; i++) {\n            for (let j = 0; j < 5; j++) {\n                led.toggle(i, j);\n            }\n        }\n    }\n\n    /**\n     * Fades in the screen display.\n     * @param ms fade time in milliseconds\n     */\n    //% help=led/fade-in\n    //% parts=\"ledmatrix\"\n    export function fadeIn(ms: number = 700): void {\n        if (ms < 20) {\n            led.setBrightness(255);\n            return;\n        }\n        let dt = 50;\n        let brightness = led.brightness();\n        let start = input.runningTime();\n        let elapsed = 0;\n        while (elapsed < ms) {\n            led.setBrightness(brightness + ((255 - brightness) * elapsed) / ms);\n            basic.pause(dt);\n            elapsed = input.runningTime() - start;\n        }\n        led.setBrightness(255);\n    }\n\n    /**\n     * Fades out the screen brightness.\n     * @param ms fade time in milliseconds\n     */\n    //% help=led/fade-out\n    //% parts=\"ledmatrix\"\n    export function fadeOut(ms: number = 700): void {\n        if (ms < 20) {\n            led.setBrightness(0);\n            return;\n        }\n        let brightness = led.brightness();\n        let dt = 50;\n        let start = input.runningTime();\n        let elapsed = 0;\n        while (elapsed < ms) {\n            led.setBrightness(brightness - (brightness * elapsed) / ms);\n            basic.pause(dt);\n            elapsed = input.runningTime() - start;\n        }\n        led.setBrightness(0);\n    }\n}\n","light.cpp":"#include \"pxt.h\"\n\n#if MICROBIT_CODAL\n\n// WS2812B timings, datasheet v1\n// 0 - 0.25-0.55us hi 0.70-1.00us low\n// 1 - 0.65-0.95us hi 0.30-0.60us low\n// datasheet v5\n// 0 - 0.22-0.38us hi 0.58-1.00us low\n// 1 - 0.58-1.00us hi 0.58-1.00us low\n\n// nrf52 asm timings:\n// 0 0.34 - 0.78\n// 1 0.80 - 0.59\n\nextern \"C\" void __attribute__((long_call, section(\".data\")))\nneopixel_send_buffer_nrf52(void *port500, uint32_t pinbr, const uint8_t *ptr, int numBytes);\n\n__attribute__((noinline)) static void\nneopixel_send_buffer_brightness(DevicePin &pin, const uint8_t *ptr, int numBytes, uint32_t br) {\n    if (br > 0x100)\n        br = 0x100;\n\n    pin.setDigitalValue(0);\n    target_wait_us(300); // initial reset\n\n    auto port = pin.name < 32 ? NRF_P0 : NRF_P1;\n\n    __disable_irq();\n    neopixel_send_buffer_nrf52((uint8_t *)(void *)port + 0x500, (pin.name & 31) | (br << 20), ptr,\n                               numBytes);\n    __enable_irq();\n}\n\nstatic void neopixel_send_buffer(DevicePin &pin, const uint8_t *ptr, int numBytes) {\n    neopixel_send_buffer_brightness(pin, ptr, numBytes, 0x100);\n}\n\n#else\nextern \"C\" void neopixel_send_buffer_core(DevicePin *pin, const uint8_t *ptr, int numBytes);\n__attribute__((noinline)) static void neopixel_send_buffer(DevicePin &pin, const uint8_t *ptr,\n                                                           int numBytes) {\n\n    // setup pin as digital\n    pin.setDigitalValue(0);\n    wait_us(300); // initial reset\n    __disable_irq();\n    neopixel_send_buffer_core(&pin, ptr, numBytes);\n    __enable_irq();\n}\n\nextern \"C\" void neopixel_send_buffer_brightness_core(DevicePin *pin, const uint8_t *ptr,\n                                                     int numBytes, int br);\n__attribute__((noinline)) static void\nneopixel_send_buffer_brightness(DevicePin &pin, const uint8_t *ptr, int numBytes, int br) {\n\n    // setup pin as digital\n    pin.setDigitalValue(0);\n    wait_us(300); // initial reset\n    __disable_irq();\n    neopixel_send_buffer_brightness_core(&pin, ptr, numBytes, br);\n    __enable_irq();\n}\n#endif\n\nnamespace light {\n\n/**\n * Sends a color buffer to a light strip\n **/\n//% advanced=true\nvoid sendWS2812Buffer(Buffer buf, int pin) {\n    if (!buf || !buf->length)\n        return;\n    neopixel_send_buffer(*pxt::getPin(pin), buf->data, buf->length);\n}\n\n/**\n * Sends a color buffer to a light strip\n **/\n//% advanced=true\nvoid sendWS2812BufferWithBrightness(Buffer buf, int pin, int brightness) {\n    if (!buf || !buf->length)\n        return;\n\n    neopixel_send_buffer_brightness(*pxt::getPin(pin), buf->data, buf->length, brightness);\n}\n\n/**\n * Sets the light mode of a pin\n **/\n//% advanced=true\n//%\nvoid setMode(int pin, int mode) {}\n\n} // namespace light\n","logo.cpp":"#include \"pxt.h\"\n\n/**\n * An action on a touch button\n */\nenum TouchButtonEvent {\n    //% block=pressed\n    Pressed = MICROBIT_BUTTON_EVT_CLICK,\n    //% block=touched\n    Touched = MICROBIT_BUTTON_EVT_DOWN,\n    //% block=released\n    Released = MICROBIT_BUTTON_EVT_UP,\n    //% block=\"long pressed\"\n    LongPressed = MICROBIT_BUTTON_EVT_LONG_CLICK\n};\n\nnamespace input {\n    /**\n     * Do something when the logo is touched and released again.\n     * @param body the code to run when the logo is pressed\n     */\n    //% weight=83 blockGap=32\n    //% blockId=input_logo_event block=\"on logo $action\"\n    //% group=\"micro:bit (V2)\"\n    //% parts=\"logotouch\"\n    //% help=\"input/on-logo-event\"\n    void onLogoEvent(TouchButtonEvent action, Action body) {\n#if MICROBIT_CODAL\n        registerWithDal(uBit.io.logo.id, action, body);\n#else\n        target_panic(PANIC_VARIANT_NOT_SUPPORTED);\n#endif\n    }\n\n    /**\n     * Get the logo state (pressed or not).\n     */\n    //% weight=58\n    //% blockId=\"input_logo_is_pressed\" block=\"logo is pressed\"\n    //% blockGap=8\n    //% group=\"micro:bit (V2)\"\n    //% parts=\"logotouch\"\n    //% help=\"input/logo-is-pressed\"\n    bool logoIsPressed() {\n#if MICROBIT_CODAL\n        return uBit.io.logo.isTouched();\n#else\n        target_panic(PANIC_VARIANT_NOT_SUPPORTED);\n        return false;\n#endif\n    }\n}\n","loops.ts":"namespace loops {\n    /**\n     * Repeats the code forever in the background.\n     * After each iteration, allows other codes to run for a set duration\n     * so that it runs on a timer\n     * @param interval time (in ms) to wait between each iteration of the action.\n     * @param body code to execute\n     */\n    //% weight=45 blockAllowMultiple=1\n    //% interval.shadow=longTimePicker\n    //% afterOnStart=true help=loops/every-interval\n    //% blockId=every_interval block=\"every $interval ms\"\n    export function everyInterval(interval: number, a: () => void): void {\n        control.runInParallel(() => {\n            let start = 0;\n            while (true) {\n                start = control.millis();\n                a();\n                pause(Math.max(0, interval - (control.millis() - start)));\n            }\n        });\n    }\n\n    /**\n      * Get the time field editor\n      * @param ms time duration in milliseconds, eg: 500, 1000\n      */\n    //% blockId=longTimePicker block=\"%ms\"\n    //% blockHidden=true shim=TD_ID\n    //% colorSecondary=\"#FFFFFF\"\n    //% ms.fieldEditor=\"numberdropdown\" ms.fieldOptions.decompileLiterals=true\n    //% ms.fieldOptions.data='[[\"100 ms\", 100], [\"200 ms\", 200], [\"500 ms\", 500], [\"1 second\", 1000], [\"1 minute\", 60000], [\"1 hour\", 3600000]]'\n    export function __timePicker(ms: number): number {\n        return ms;\n    }\n}","math.ts":"namespace Math {\n    //% blockIdentity=\"Math._constant\"\n    //% block=\"π\"\n    export const PI = 3.141592653589793;\n    //% blockIdentity=\"Math._constant\"\n    //% block=\"e\"\n    export const E = 2.718281828459045;\n    //% blockIdentity=\"Math._constant\"\n    //% block=\"ln(2)\"\n    export const LN2 = 0.6931471805599453;\n    //% blockIdentity=\"Math._constant\"\n    //% block=\"ln(10)\"\n    export const LN10 = 2.302585092994046;\n    //% blockIdentity=\"Math._constant\"\n    //% block=\"log₂(e)\"\n    export const LOG2E = 1.4426950408889634;\n    //% blockIdentity=\"Math._constant\"\n    //% block=\"log₁₀(e)\"\n    export const LOG10E = 0.4342944819032518;\n    //% blockIdentity=\"Math._constant\"\n    //% block=\"√½\"\n    export const SQRT1_2 = 0.7071067811865476;\n    //% blockIdentity=\"Math._constant\"\n    //% block=\"√2\"\n    export const SQRT2 = 1.4142135623730951;\n\n    /**\n     * Re-maps a number from one range to another. That is, a value of ``from low`` would get mapped to ``to low``, a value of ``from high`` to ``to high``, values in-between to values in-between, etc.\n     * @param value value to map in ranges\n     * @param fromLow the lower bound of the value's current range\n     * @param fromHigh the upper bound of the value's current range, eg: 1023\n     * @param toLow the lower bound of the value's target range\n     * @param toHigh the upper bound of the value's target range, eg: 4\n     */\n    //% help=math/map weight=10 blockGap=8\n    //% blockId=math_map block=\"map %value|from low %fromLow|high %fromHigh|to low %toLow|high %toHigh\"\n    //% inlineInputMode=inline\n    export function map(value: number, fromLow: number, fromHigh: number, toLow: number, toHigh: number): number {\n        return ((value - fromLow) * (toHigh - toLow)) / (fromHigh - fromLow) + toLow;\n    }\n\n    /**\n     * Constrains a number to be within a range\n     * @param x the number to constrain, all data types\n     * @param y the lower end of the range, all data types\n     * @param z the upper end of the range, all data types\n     */\n    //% help=math/constrain weight=11 blockGap=8\n    //% blockId=\"math_constrain_value\" block=\"constrain %value|between %low|and %high\"\n    export function constrain(value: number, low: number, high: number): number {\n        return value < low ? low : value > high ? high : value;\n    }\n\n    const b_m16: number[] = [0, 49, 49, 41, 90, 27, 117, 10]\n    /**\n     * Returns the sine of an input angle. This is an 8-bit approximation.\n     * @param theta input angle from 0-255\n     */\n    //% help=math/isin weight=11 advanced=true blockGap=8\n    export function isin(theta: number) {\n        //reference: based on FASTLed's sin approximation method: [https://github.com/FastLED/FastLED](MIT)\n        let offset = theta;\n        if( theta & 0x40 ) {\n            offset = 255 - offset;\n        }\n        offset &= 0x3F; // 0..63\n\n        let secoffset  = offset & 0x0F; // 0..15\n        if( theta & 0x40) secoffset++;\n\n        let section = offset >> 4; // 0..3\n        let s2 = section * 2;\n\n        let b = b_m16[s2];\n        let m16 = b_m16[s2+1];\n        let mx = (m16 * secoffset) >> 4;\n\n        let y = mx + b;\n        if( theta & 0x80 ) y = -y;\n\n        y += 128;\n\n        return y;\n    }\n\n    /**\n     * Returns the cosine of an input angle. This is an 8-bit approximation.\n     * @param theta input angle from 0-255\n     */\n    //% help=math/icos weight=10 advanced=true blockGap=8\n    export function icos(theta: number) {\n        return isin(theta + 16384);\n    }\n\n    //% shim=TD_ID\n    //% block=\"$MEMBER\"\n    //% constantShim\n    //% weight=0\n    export function _constant(MEMBER: number): number {\n        return MEMBER;\n    }\n}\n\nnamespace Number {\n    export const EPSILON = 2.220446049250313e-16;\n}","melodies.ts":"/*\nThe MIT License (MIT)\n\nCopyright (c) 2013-2016 The MicroPython-on-micro:bit Developers, as listed\nin the accompanying AUTHORS file\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\nall 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\n// Melodies from file microbitmusictunes.c https://github.com/bbcmicrobit/MicroPython\n\nenum Melodies {\n    //% block=\"dadadum\" blockIdentity=music.builtInMelody\n    Dadadadum = 0,\n    //% block=\"entertainer\" blockIdentity=music.builtInMelody\n    Entertainer,\n    //% block=\"prelude\" blockIdentity=music.builtInMelody\n    Prelude,\n    //% block=\"ode\" blockIdentity=music.builtInMelody\n    Ode,\n    //% block=\"nyan\" blockIdentity=music.builtInMelody\n    Nyan,\n    //% block=\"ringtone\" blockIdentity=music.builtInMelody\n    Ringtone,\n    //% block=\"funk\" blockIdentity=music.builtInMelody\n    Funk,\n    //% block=\"blues\" blockIdentity=music.builtInMelody\n    Blues,\n    //% block=\"birthday\" blockIdentity=music.builtInMelody\n    Birthday,\n    //% block=\"wedding\" blockIdentity=music.builtInMelody\n    Wedding,\n    //% block=\"funeral\" blockIdentity=music.builtInMelody\n    Funeral,\n    //% block=\"punchline\" blockIdentity=music.builtInMelody\n    Punchline,\n    //% block=\"baddy\" blockIdentity=music.builtInMelody\n    Baddy,\n    //% block=\"chase\" blockIdentity=music.builtInMelody\n    Chase,\n    //% block=\"ba ding\" blockIdentity=music.builtInMelody\n    BaDing,\n    //% block=\"wawawawaa\" blockIdentity=music.builtInMelody\n    Wawawawaa,\n    //% block=\"jump up\" blockIdentity=music.builtInMelody\n    JumpUp,\n    //% block=\"jump down\" blockIdentity=music.builtInMelody\n    JumpDown,\n    //% block=\"power up\" blockIdentity=music.builtInMelody\n    PowerUp,\n    //% block=\"power down\" blockIdentity=music.builtInMelody\n    PowerDown,\n}\n\nnamespace music {\n    export function getMelody(melody: Melodies): string[] {\n        return _bufferToMelody(_getMelodyBuffer(melody));\n    }\n\n    // The buffer format is 2 bytes per note. First note byte is midi\n    // note number, second byte is duration in quarter beats. The note\n    // number 0 is reserved for rests\n    export function _getMelodyBuffer(melody: Melodies) {\n        switch (melody) {\n            case Melodies.Dadadadum:\n                return hex`00024f024f024f024b0800024d024d024d024a08`;\n            case Melodies.Entertainer:\n                return hex`4a014b014c0154024c0154024c0154035401560157015801540156015802530156025404`;\n            case Melodies.Prelude:\n                return hex`48014c014f01540158014f015401580148014c014f01540158014f015401580148014a014f01560159014f015601590148014a014f01560159014f015601590147014a014f01560159014f015601590147014a014f01560159014f015601590148014c014f01540158014f015401580148014c014f01540158014f0154015801`;\n            case Melodies.Ode:\n                return hex`4c044c044d044f044f044d044c044a04480448044a044c044c064a024a084c044c044d044f044f044d044c044a04480448044a044c044a0648024808`;\n            case Melodies.Nyan:\n                return hex`5a025c02550157025301560155015302530255025602560155015301550157015a015c0157015a015501560153015501530157025a025c0157015a0155015701530156015701560155015301550156025301550157015a01550156015501530155025302550253024e01500153024e01500153015501570153015801570158015a01530253024e01500153014e0158015701550153014e014b014c014e0153024e01500153024e015001530153015501570153014e0150014e0153025301520153014e01500153015801570158015a0153025502`;\n            case Melodies.Ringtone:\n                return hex`48014a014c024f024a014c014d0251024c014d014f0253025404`;\n            case Melodies.Funk:\n                return hex`300230023302300135023001350236023702300230023702300136023001360235023302`;\n            case Melodies.Blues:\n                return hex`30023402370239023a0239023702340230023402370239023a02390237023402350239023c023e023f023e023c02390230023402370239023a0239023702340237023b023e024102350239023c023f0230023402370234023702350234023202`;\n            case Melodies.Birthday:\n                return hex`480348014a0448044d044c08480348014a0448044f044d0848034801540451044d044c044a045203520151044d044f044d08`;\n            case Melodies.Wedding:\n                return hex`48044d034d014d0848044f034c014d0848044d035101540451034d014d044c034d014f08`;\n            case Melodies.Funeral:\n                return hex`3c043c033c013c043f033e013e033c013c033b013c04`;\n            case Melodies.Punchline:\n                return hex`480343014201430144034303000347034803`;\n            case Melodies.Baddy:\n                return hex`3c0300033e023f0200023c0200024208`;\n            case Melodies.Chase:\n                return hex`5101530154015301510200025101530154015301510200025102580257025802590258025702580253015401560154015302000253015401560154015302000253025802570258025902580257025802`;\n            case Melodies.BaDing:\n                return hex`5f016403`;\n            case Melodies.Wawawawaa:\n                return hex`400300013f0300013e0400013d08`;\n            case Melodies.JumpUp:\n                return hex`54015601580159015b01`;\n            case Melodies.JumpDown:\n                return hex`5b015901580156015401`;\n            case Melodies.PowerUp:\n                return hex`4f01540158015b0258015b03`;\n            case Melodies.PowerDown:\n                return hex`5b01570154014f0253015403`;\n\n            default: return undefined;\n        }\n    }\n}","music.cpp":"#include \"pxt.h\"\n\nnamespace pins {\n    void analogSetPitchVolume(int volume);\n    int analogPitchVolume();\n}\n\nnamespace music {\n/**\n * Set the default output volume of the sound synthesizer.\n * @param volume the volume 0...255\n */\n//% blockId=synth_set_volume block=\"set volume %volume\"\n//% volume.min=0 volume.max=255\n//% volume.defl=127\n//% help=music/set-volume\n//% weight=70\n//% group=\"Volume\"\n//% blockGap=8\nvoid setVolume(int volume) {\n#if MICROBIT_CODAL\n    uBit.audio.setVolume(max(0, min(255, volume)));\n#else\n    pins::analogSetPitchVolume(volume);\n#endif\n}\n\n/**\n * Returns the current output volume of the sound synthesizer.\n */\n//% blockId=synth_get_volume block=\"volume\"\n//% help=music/volume\n//% weight=69\n//% group=\"Volume\"\n//% blockGap=8\nint volume() {\n#if MICROBIT_CODAL\n    return uBit.audio.getVolume();\n#else\n    return pins::analogPitchVolume();\n#endif\n}\n\n/**\n* Turn the built-in speaker on or off.\n* Disabling the speaker resets the sound pin to the default of P0.\n* @param enabled whether the built-in speaker is enabled in addition to the sound pin\n*/\n//% blockId=music_set_built_in_speaker_enable block=\"set built-in speaker $enabled\"\n//% group=\"micro:bit (V2)\"\n//% parts=builtinspeaker\n//% help=music/set-built-in-speaker-enabled\n//% enabled.shadow=toggleOnOff\n//% weight=0\nvoid setBuiltInSpeakerEnabled(bool enabled) {\n#if MICROBIT_CODAL\n    uBit.audio.setSpeakerEnabled(enabled);\n#else\n    // don't crash if user asks to turn it off\n    if (enabled) {\n        target_panic(PANIC_VARIANT_NOT_SUPPORTED);\n    }\n#endif\n}\n\n/**\n* Check whether any sound is being played, no matter the source\n*/\n//% blockId=music_sound_is_playing block=\"sound is playing\"\n//% group=\"micro:bit (V2)\"\n//% help=music/is-sound-playing\n//% weight=0\nbool isSoundPlaying() {\n#if MICROBIT_CODAL\n    if (uBit.audio.mixer.getSilenceStartTime() == 0) {\n        return false;\n    } else {\n        return uBit.audio.isPlaying();\n    }\n\n#else\n    target_panic(PANIC_VARIANT_NOT_SUPPORTED);\n#endif\n}\n\n/**\n * Defines an optional sample level to generate during periods of silence.\n **/\n//% group=\"micro:bit (V2)\"\n//% help=music/set-silence-level\n//% level.min=0\n//% level.max=1024\n//% level.defl=0\n//% weight=1\nvoid setSilenceLevel(int level) {\n#if MICROBIT_CODAL\n    uBit.audio.mixer.setSilenceLevel(level);\n#else\n    // this is an optimization\n    // ignore in V1\n#endif\n}\n\n}","music.ts":"enum Note {\n    //% blockIdentity=music.noteFrequency enumval=262\n    C = 262,\n    //% block=C#\n    //% blockIdentity=music.noteFrequency enumval=277\n    CSharp = 277,\n    //% blockIdentity=music.noteFrequency enumval=294\n    D = 294,\n    //% blockIdentity=music.noteFrequency enumval=311\n    Eb = 311,\n    //% blockIdentity=music.noteFrequency enumval=330\n    E = 330,\n    //% blockIdentity=music.noteFrequency enumval=349\n    F = 349,\n    //% block=F#\n    //% blockIdentity=music.noteFrequency enumval=370\n    FSharp = 370,\n    //% blockIdentity=music.noteFrequency enumval=392\n    G = 392,\n    //% block=G#\n    //% blockIdentity=music.noteFrequency enumval=415\n    GSharp = 415,\n    //% blockIdentity=music.noteFrequency enumval=440\n    A = 440,\n    //% blockIdentity=music.noteFrequency enumval=466\n    Bb = 466,\n    //% blockIdentity=music.noteFrequency enumval=494\n    B = 494,\n    //% blockIdentity=music.noteFrequency enumval=131\n    C3 = 131,\n    //% block=C#3\n    //% blockIdentity=music.noteFrequency enumval=139\n    CSharp3 = 139,\n    //% blockIdentity=music.noteFrequency enumval=147\n    D3 = 147,\n    //% blockIdentity=music.noteFrequency enumval=156\n    Eb3 = 156,\n    //% blockIdentity=music.noteFrequency enumval=165\n    E3 = 165,\n    //% blockIdentity=music.noteFrequency enumval=175\n    F3 = 175,\n    //% block=F#3\n    //% blockIdentity=music.noteFrequency enumval=185\n    FSharp3 = 185,\n    //% blockIdentity=music.noteFrequency enumval=196\n    G3 = 196,\n    //% block=G#3\n    //% blockIdentity=music.noteFrequency enumval=208\n    GSharp3 = 208,\n    //% blockIdentity=music.noteFrequency enumval=220\n    A3 = 220,\n    //% blockIdentity=music.noteFrequency enumval=233\n    Bb3 = 233,\n    //% blockIdentity=music.noteFrequency enumval=247\n    B3 = 247,\n    //% blockIdentity=music.noteFrequency enumval=262\n    C4 = 262,\n    //% block=C#4\n    //% blockIdentity=music.noteFrequency enumval=277\n    CSharp4 = 277,\n    //% blockIdentity=music.noteFrequency enumval=294\n    D4 = 294,\n    //% blockIdentity=music.noteFrequency enumval=311\n    Eb4 = 311,\n    //% blockIdentity=music.noteFrequency enumval=330\n    E4 = 330,\n    //% blockIdentity=music.noteFrequency enumval=349\n    F4 = 349,\n    //% block=F#4\n    //% blockIdentity=music.noteFrequency enumval=370\n    FSharp4 = 370,\n    //% blockIdentity=music.noteFrequency enumval=392\n    G4 = 392,\n    //% block=G#4\n    //% blockIdentity=music.noteFrequency enumval=415\n    GSharp4 = 415,\n    //% blockIdentity=music.noteFrequency enumval=440\n    A4 = 440,\n    //% blockIdentity=music.noteFrequency enumval=466\n    Bb4 = 466,\n    //% blockIdentity=music.noteFrequency enumval=494\n    B4 = 494,\n    //% blockIdentity=music.noteFrequency enumval=523\n    C5 = 523,\n    //% block=C#5\n    //% blockIdentity=music.noteFrequency enumval=555\n    CSharp5 = 555,\n    //% blockIdentity=music.noteFrequency enumval=587\n    D5 = 587,\n    //% blockIdentity=music.noteFrequency enumval=622\n    Eb5 = 622,\n    //% blockIdentity=music.noteFrequency enumval=659\n    E5 = 659,\n    //% blockIdentity=music.noteFrequency enumval=698\n    F5 = 698,\n    //% block=F#5\n    //% blockIdentity=music.noteFrequency enumval=740\n    FSharp5 = 740,\n    //% blockIdentity=music.noteFrequency enumval=784\n    G5 = 784,\n    //% block=G#5\n    //% blockIdentity=music.noteFrequency enumval=831\n    GSharp5 = 831,\n    //% blockIdentity=music.noteFrequency enumval=880\n    A5 = 880,\n    //% blockIdentity=music.noteFrequency enumval=932\n    Bb5 = 932,\n    //% blockIdentity=music.noteFrequency enumval=988\n    B5 = 988,\n}\n\nenum BeatFraction {\n    //% block=1\n    Whole = 1,\n    //% block=\"1/2\"\n    Half = 2,\n    //% block=\"1/4\"\n    Quarter = 4,\n    //% block=\"1/8\"\n    Eighth = 8,\n    //% block=\"1/16\"\n    Sixteenth = 16,\n    //% block=\"2\"\n    Double = 32,\n    //% block=\"4\",\n    Breve = 64\n}\n\nenum MelodyOptions {\n    //% block=\"once\"\n    Once = 1,\n    //% block=\"forever\"\n    Forever = 2,\n    //% block=\"once in background\"\n    OnceInBackground = 4,\n    //% block=\"forever in background\"\n    ForeverInBackground = 8\n}\n\nenum MelodyStopOptions {\n    //% block=\"all\"\n    All = MelodyOptions.Once | MelodyOptions.OnceInBackground,\n    //% block=\"foreground\"\n    Foreground = MelodyOptions.Once,\n    //% block=\"background\"\n    Background = MelodyOptions.OnceInBackground\n}\n\nenum MusicEvent {\n    //% block=\"melody note played\"\n    MelodyNotePlayed = 1,\n    //% block=\"melody started\"\n    MelodyStarted = 2,\n    //% block=\"melody ended\"\n    MelodyEnded = 3,\n    //% block=\"melody repeated\"\n    MelodyRepeated = 4,\n    //% block=\"background melody note played\"\n    BackgroundMelodyNotePlayed = MelodyNotePlayed | 0xf0,\n    //% block=\"background melody started\"\n    BackgroundMelodyStarted = MelodyStarted | 0xf0,\n    //% block=\"background melody ended\"\n    BackgroundMelodyEnded = MelodyEnded | 0xf0,\n    //% block=\"background melody repeated\"\n    BackgroundMelodyRepeated = MelodyRepeated | 0xf0,\n    //% block=\"background melody paused\"\n    BackgroundMelodyPaused = 5 | 0xf0,\n    //% block=\"background melody resumed\"\n    BackgroundMelodyResumed = 6 | 0xf0\n}\n\n/**\n * Generation of music tones.\n */\n//% color=#E63022 weight=106 icon=\"\\uf025\"\n//% groups='[\"Melody\", \"Tone\", \"Volume\", \"Tempo\", \"Melody Advanced\"]'\nnamespace music {\n    const INTERNAL_MELODY_ENDED = 5;\n\n    let beatsPerMinute: number = 120;\n    let stopSoundHandlers: (() => void)[];\n    //% whenUsed\n    const freqs = hex`\n        1f00210023002500270029002c002e003100340037003a003e004100450049004e00520057005c00620068006e00\n        75007b0083008b0093009c00a500af00b900c400d000dc00e900f70006011501260137014a015d01720188019f01\n        b801d201ee010b022a024b026e029302ba02e40210033f037003a403dc03170455049704dd0427057505c8052006\n        7d06e0064907b8072d08a9082d09b9094d0aea0a900b400cfa0cc00d910e6f0f5a1053115b1272139a14d4152017\n        8018f519801b231dde1e`;\n    let _playTone: (frequency: number, duration: number) => void;\n    const MICROBIT_MELODY_ID = 2000;\n\n    /**\n     * Plays a tone through pin ``P0`` for the given duration.\n     * @param frequency pitch of the tone to play in Hertz (Hz), eg: Note.C\n     * @param ms tone duration in milliseconds (ms)\n     */\n    //% help=music/play-tone weight=90\n    //% blockId=device_play_note block=\"play|tone %note=device_note|for %duration=device_beat\" blockGap=8\n    //% parts=\"headphone\"\n    //% useEnumVal=1\n    //% group=\"Tone\"\n    //% deprecated=1\n    export function playTone(frequency: number, ms: number): void {\n        if (isNaN(frequency) || isNaN(ms)) return;\n        if (_playTone) _playTone(frequency, ms);\n        else pins.analogPitch(frequency, ms);\n    }\n\n    /**\n     * Plays a tone through pin ``P0``.\n     * @param frequency pitch of the tone to play in Hertz (Hz), eg: Note.C\n     */\n    //% help=music/ring-tone weight=80\n    //% blockId=device_ring block=\"ring tone (Hz)|%note=device_note\" blockGap=8\n    //% parts=\"headphone\"\n    //% useEnumVal=1\n    //% group=\"Tone\"\n    export function ringTone(frequency: number): void {\n        playTone(frequency, 0);\n    }\n\n    /**\n     * Rests (plays nothing) for a specified time through pin ``P0``.\n     * @param ms rest duration in milliseconds (ms)\n     */\n    //% help=music/rest weight=79\n    //% blockId=device_rest block=\"rest for |%duration=device_beat\"\n    //% parts=\"headphone\"\n    //% group=\"Tone\"\n    export function rest(ms: number): void {\n        playTone(0, ms);\n    }\n\n\n    /**\n     * Gets the frequency of a note.\n     * @param name the note name\n     */\n    //% weight=50 help=music/note-frequency\n    //% blockId=device_note block=\"%name\"\n    //% shim=TD_ID color=\"#FFFFFF\" colorSecondary=\"#FFFFFF\"\n    //% name.fieldEditor=\"note\" name.defl=\"262\"\n    //% name.fieldOptions.decompileLiterals=true\n    //% useEnumVal=1\n    //% group=\"Tone\"\n    //% blockGap=8\n    export function noteFrequency(name: Note): number {\n        return name;\n    }\n\n    function init() {\n        if (beatsPerMinute <= 0) beatsPerMinute = 120;\n    }\n\n    /**\n     * Returns the duration of a beat in milli-seconds\n     */\n    //% help=music/beat weight=49\n    //% blockId=device_beat block=\"%fraction|beat\"\n    //% group=\"Tempo\"\n    //% blockGap=8\n    export function beat(fraction?: BeatFraction): number {\n        init();\n        if (fraction == null) fraction = BeatFraction.Whole;\n        let beat = Math.idiv(60000, beatsPerMinute);\n        switch (fraction) {\n            case BeatFraction.Half: return beat >> 1;\n            case BeatFraction.Quarter: return beat >> 2;\n            case BeatFraction.Eighth: return beat >> 3;\n            case BeatFraction.Sixteenth: return beat >> 4;\n            case BeatFraction.Double: return beat << 1;\n            case BeatFraction.Breve: return beat << 2;\n            default: return beat;\n        }\n    }\n\n    /**\n     * Returns the tempo in beats per minute. Tempo is the speed (bpm = beats per minute) at which notes play. The larger the tempo value, the faster the notes will play.\n     */\n    //% help=music/tempo weight=40\n    //% blockId=device_tempo block=\"tempo (bpm)\" blockGap=8\n    //% group=\"Tempo\"\n    export function tempo(): number {\n        init();\n        return beatsPerMinute;\n    }\n\n    /**\n     * Change the tempo by the specified amount\n     * @param bpm The change in beats per minute to the tempo, eg: 20\n     */\n    //% help=music/change-tempo-by weight=39\n    //% blockId=device_change_tempo block=\"change tempo by (bpm)|%value\" blockGap=8\n    //% group=\"Tempo\"\n    //% weight=100\n    export function changeTempoBy(bpm: number): void {\n        init();\n        if (isNaN(bpm)) return;\n        setTempo(beatsPerMinute + bpm);\n    }\n\n    /**\n     * Sets the tempo to the specified amount\n     * @param bpm The new tempo in beats per minute, eg: 120\n     */\n    //% help=music/set-tempo weight=38\n    //% blockId=device_set_tempo block=\"set tempo to (bpm)|%value\"\n    //% bpm.min=40 bpm.max=500\n    //% group=\"Tempo\"\n    //% weight=99\n    export function setTempo(bpm: number): void {\n        init();\n        if (isNaN(bpm)) return;\n        if (bpm > 0) {\n            beatsPerMinute = Math.max(1, bpm);\n        }\n    }\n\n    let currentMelody: Melody;\n    let currentBackgroundMelody: Melody;\n\n    /**\n     * Gets the melody array of a built-in melody.\n     * @param name the note name, eg: Note.C\n     */\n    //% weight=50 help=music/built-in-melody\n    //% blockId=device_builtin_melody block=\"%melody\"\n    //% blockHidden=true\n    //% group=\"Melody Advanced\"\n    //% deprecated=1\n    export function builtInMelody(melody: Melodies): string[] {\n        return getMelody(melody);\n    }\n\n    /**\n     * Gets the melody array of a built-in melody.\n     * @param melody the melody name\n     */\n    //% weight=60 help=music/built-in-playable-melody\n    //% blockId=device_builtin_melody_playable block=\"melody $melody\"\n    //% toolboxParent=music_playable_play_default_bkg\n    //% toolboxParentArgument=toPlay\n    //% duplicateShadowOnDrag\n    //% group=\"Melody Advanced\"\n    export function builtInPlayableMelody(melody: Melodies): StringArrayPlayable {\n        return new StringArrayPlayable(getMelody(melody), undefined);\n    }\n\n    /**\n     * Registers code to run on various melody events\n     */\n    //% blockId=melody_on_event block=\"music on %value\"\n    //% help=music/on-event weight=59 blockGap=32\n    //% group=\"Melody Advanced\"\n    export function onEvent(value: MusicEvent, handler: () => void) {\n        control.onEvent(MICROBIT_MELODY_ID, value, handler);\n    }\n\n    /**\n     * Use startMelody instead\n     */\n    //% hidden=1 deprecated=1\n    //% parts=\"headphone\"\n    //% group=\"Melody Advanced\"\n    export function beginMelody(melodyArray: string[], options: MelodyOptions = 1) {\n        return startMelodyInternal(melodyArray, options);\n    }\n\n    /**\n     * Starts playing a melody.\n     * Notes are expressed as a string of characters with this format: NOTE[octave][:duration]\n     * @param melodyArray the melody array to play\n     * @param options melody options, once / forever, in the foreground / background\n     */\n    //% help=music/begin-melody weight=60 blockGap=16\n    //% blockId=device_start_melody block=\"start melody %melody=device_builtin_melody| repeating %options\"\n    //% parts=\"headphone\"\n    //% group=\"Melody Advanced\"\n    //% deprecated=1\n    export function startMelody(melodyArray: string[], options: MelodyOptions = 1) {\n        return startMelodyInternal(melodyArray, options);\n    }\n\n    /**\n     * Play a melody from the melody editor.\n     * @param melody string of up to eight notes [C D E F G A B C5] or rests [-] separated by spaces, which will be played one at a time, ex: \"E D G F B A C5 B \"\n     * @param tempo number in beats per minute (bpm), dictating how long each note will play for\n     */\n    //% block=\"play melody $melody at tempo $tempo|(bpm)\" blockId=playMelody\n    //% weight=85 blockGap=8 help=music/play-melody\n    //% melody.shadow=\"melody_editor\"\n    //% tempo.min=40 tempo.max=500\n    //% tempo.defl=120\n    //% parts=headphone\n    //% group=\"Melody\"\n    //% deprecated=1\n    export function playMelody(melody: string, tempo: number) {\n        melody = melody || \"\";\n        setTempo(tempo);\n        let notes = getMelodyNotes(melody);\n\n        music.startMelodyInternal(notes, MelodyOptions.Once)\n        waitForMelodyEnd();\n    }\n\n    // Shared code between begin, start, and play Melody blocks (all deprecated), plus StringPlayable.play (NOT deprecated).\n    export function startMelodyInternal(melodyArray: string[], options: MelodyOptions) {\n        init();\n        const isBackground = options & (MelodyOptions.OnceInBackground | MelodyOptions.ForeverInBackground);\n        if (currentMelody != undefined) {\n            if (!isBackground && currentMelody.background) {\n                currentBackgroundMelody = currentMelody;\n                currentMelody = null;\n                control.raiseEvent(MICROBIT_MELODY_ID, MusicEvent.BackgroundMelodyPaused);\n            }\n            if (currentMelody)\n                control.raiseEvent(MICROBIT_MELODY_ID, currentMelody.background | MusicEvent.MelodyEnded);\n            currentMelody = new Melody(melodyArray, options);\n            control.raiseEvent(MICROBIT_MELODY_ID, currentMelody.background | MusicEvent.MelodyStarted);\n        } else {\n            currentMelody = new Melody(melodyArray, options);\n            control.raiseEvent(MICROBIT_MELODY_ID, currentMelody.background | MusicEvent.MelodyStarted);\n            // Only start the fiber once\n            control.inBackground(() => {\n                while (currentMelody.hasNextNote()) {\n                    playNextNote(currentMelody);\n                    if (!currentMelody.hasNextNote() && currentBackgroundMelody) {\n                        // Swap the background melody back\n                        currentMelody = currentBackgroundMelody;\n                        currentBackgroundMelody = null;\n                        control.raiseEvent(MICROBIT_MELODY_ID, MusicEvent.MelodyEnded);\n                        control.raiseEvent(MICROBIT_MELODY_ID, MusicEvent.BackgroundMelodyResumed);\n                        control.raiseEvent(MICROBIT_MELODY_ID, INTERNAL_MELODY_ENDED);\n                    }\n                }\n                control.raiseEvent(MICROBIT_MELODY_ID, currentMelody.background | MusicEvent.MelodyEnded);\n                if (!currentMelody.background)\n                    control.raiseEvent(MICROBIT_MELODY_ID, INTERNAL_MELODY_ENDED);\n                currentMelody = null;\n            })\n        }\n    }\n\n    export function waitForMelodyEnd() {\n        control.waitForEvent(MICROBIT_MELODY_ID, INTERNAL_MELODY_ENDED);\n    }\n\n    export function getMelodyNotes(melody: string) {\n        let notes: string[] = melody.split(\" \").filter(n => !!n);\n        let newOctave = false;\n\n        // build melody string, replace '-' with 'R' and add tempo\n        // creates format like \"C5-174 B4 A G F E D C \"\n        for (let i = 0; i < notes.length; i++) {\n            if (notes[i] === \"-\") {\n                notes[i] = \"R\";\n            } else if (notes[i] === \"C5\") {\n                newOctave = true;\n            } else if (newOctave) { // change the octave if necesary\n                notes[i] += \"4\";\n                newOctave = false;\n            }\n        }\n\n        // Switch back to octave 4 on first note if repeating and final note is octave 5.\n        // Otherwise the higher octave will persist.\n        if (notes[notes.length - 1] === \"C5\" && notes[0] != \"C5\") {\n            notes[0] += \"4\";\n        }\n\n        return notes;\n    }\n\n    /**\n     * Create a melody with the melody editor.\n     * @param melody\n     */\n    //% block=\"$melody\" blockId=melody_editor\n    //% blockHidden = true\n    //% weight=85 blockGap=8\n    //% duplicateShadowOnDrag\n    //% melody.fieldEditor=\"melody\"\n    //% melody.fieldOptions.decompileLiterals=true\n    //% melody.fieldOptions.decompileIndirectFixedInstances=\"true\"\n    //% melody.fieldOptions.onParentBlock=\"true\"\n    //% shim=TD_ID\n    //% group=\"Melody\"\n    export function melodyEditor(melody: string): string {\n        return melody;\n    }\n\n    /**\n     * Stops the melodies\n     * @param options which melody to stop\n     */\n    //% help=music/stop-melody weight=59 blockGap=16\n    //% blockId=device_stop_melody block=\"stop melody $options\"\n    //% parts=\"headphone\"\n    //% group=\"Melody Advanced\"\n    export function stopMelody(options: MelodyStopOptions) {\n        if (options & MelodyStopOptions.Background)\n            startMelody([], MelodyOptions.OnceInBackground);\n        if (options & MelodyStopOptions.Foreground)\n            startMelody([], MelodyOptions.Once);\n    }\n\n    export function _onStopSound(handler: () => void) {\n        if (!stopSoundHandlers) {\n            stopSoundHandlers = [];\n        }\n        stopSoundHandlers.push(handler);\n    }\n\n    /**\n     * Stop all sounds and melodies currently playing.\n     */\n    //% help=music/stop-all-sounds\n    //% blockId=music_stop_all_sounds block=\"stop all sounds\"\n    //% weight=10\n    //% group=\"Volume\"\n    export function stopAllSounds() {\n        rest(0);\n        stopMelody(MelodyStopOptions.All);\n        music.__stopSoundExpressions();\n        _stopPlayables();\n        if (stopSoundHandlers) {\n            for (const handler of stopSoundHandlers) {\n                handler()\n            }\n        }\n    }\n\n\n    /**\n     * Sets a custom playTone function for playing melodies\n     */\n    //% help=music/set-play-tone\n    //% advanced=true\n    //% group=\"Tone\"\n    export function setPlayTone(f: (frequency: number, duration: number) => void) {\n        _playTone = f;\n    }\n\n    /**\n     * Converts an octave and note offset into an integer frequency.\n     * Returns 0 if the note is out of range.\n     *\n     * @param octave    The octave of the note (1 - 8)\n     * @param note      The offset of the note within the octave\n     * @returns         A frequency in HZ or 0 if out of range\n     */\n    export function getFrequencyForNote(octave: number, note: number) {\n        return freqs.getNumber(NumberFormat.UInt16LE, (note + (12 * (octave - 1))) * 2) || 0;\n    }\n\n    /*\n     * Converts a simple positive string to an integer.\n     * Pxt-common's parseInt is more robust, but it has a fairly large code size footprint.\n     * When we know the provided string will be a simple number, we can use this instead,\n     * which takes some shortcuts but does not use nearly as much space.\n     */\n    function parseIntSimple(text: string) {\n        let result = 0;\n        for (let i = 0; i < text.length; ++i) {\n            const c = text.charCodeAt(i) - 48;\n            if (c < 0 || c > 9) return NaN;\n            result = result * 10 + c;\n        }\n        return result;\n    }\n\n    function playNextNote(melody: Melody): void {\n        // cache elements\n        let currNote = melody.nextNote();\n        let currentPos = melody.currentPos;\n        let currentDuration = melody.currentDuration;\n        let currentOctave = melody.currentOctave;\n\n        let note: number;\n        let isrest: boolean = false;\n        let beatPos: number;\n        let parsingOctave: boolean = true;\n        let prevNote: boolean = false;\n\n        for (let pos = 0; pos < currNote.length; pos++) {\n            let noteChar = currNote.charAt(pos);\n            switch (noteChar) {\n                case 'c': case 'C': note = 1; prevNote = true; break;\n                case 'd': case 'D': note = 3; prevNote = true; break;\n                case 'e': case 'E': note = 5; prevNote = true; break;\n                case 'f': case 'F': note = 6; prevNote = true; break;\n                case 'g': case 'G': note = 8; prevNote = true; break;\n                case 'a': case 'A': note = 10; prevNote = true; break;\n                case 'B': note = 12; prevNote = true; break;\n                case 'r': case 'R': isrest = true; prevNote = false; break;\n                case '#': note++; prevNote = false; break;\n                case 'b': if (prevNote) note--; else { note = 12; prevNote = true; } break;\n                case ':': parsingOctave = false; beatPos = pos; prevNote = false; break;\n                default: prevNote = false; if (parsingOctave) currentOctave = parseIntSimple(noteChar);\n            }\n        }\n        if (!parsingOctave) {\n            currentDuration = parseIntSimple(currNote.substr(beatPos + 1, currNote.length - beatPos));\n        }\n        let beat = Math.idiv(60000, beatsPerMinute) >> 2;\n        if (isrest) {\n            music.rest(currentDuration * beat)\n        } else {\n            music.playTone(getFrequencyForNote(currentOctave, note), currentDuration * beat);\n        }\n        melody.currentDuration = currentDuration;\n        melody.currentOctave = currentOctave;\n        const repeating = melody.repeating && currentPos == melody.melodyArray.length - 1;\n        melody.currentPos = repeating ? 0 : currentPos + 1;\n\n        control.raiseEvent(MICROBIT_MELODY_ID, melody.background | MusicEvent.MelodyNotePlayed);\n        if (repeating)\n            control.raiseEvent(MICROBIT_MELODY_ID, melody.background | MusicEvent.MelodyRepeated);\n    }\n\n    class Melody {\n        public melodyArray: string[];\n        public currentDuration: number;\n        public currentOctave: number;\n        public currentPos: number;\n        public repeating: boolean;\n\n        // This is bitwise or'd with the events. 0 is not in background, 0xf0 if in background\n        public background: number;\n\n        constructor(melodyArray: string[], options: MelodyOptions) {\n            this.melodyArray = melodyArray;\n            this.repeating = !!(options & (MelodyOptions.Forever | MelodyOptions.ForeverInBackground));\n            this.background = (options & (MelodyOptions.OnceInBackground | MelodyOptions.ForeverInBackground)) ? 0xf0 : 0;\n            this.currentDuration = 4; //Default duration (Crotchet)\n            this.currentOctave = 4; //Middle octave\n            this.currentPos = 0;\n        }\n\n        hasNextNote() {\n            return this.repeating || this.currentPos < this.melodyArray.length;\n        }\n\n        nextNote(): string {\n            const currentNote = this.melodyArray[this.currentPos];\n            return currentNote;\n        }\n    }\n\n    export function _bufferToMelody(melody: Buffer) {\n        if (!melody) return [];\n\n        let currentDuration = 4;\n        let currentOctave = -1;\n        const out: string[] = [];\n\n        const notes = \"c#d#ef#g#a#b\"\n        let current = \"\";\n\n        // The buffer format is 2 bytes per note. First note byte is midi\n        // note number, second byte is duration in quarter beats. The note\n        // number 0 is reserved for rests\n        for (let i = 0; i < melody.length; i += 2) {\n            let octave = 4;\n            const note = melody[i] % 12;\n            if (melody[i] === 0) {\n                current = \"r\"\n            }\n            else {\n                current = notes.charAt(note);\n                if (current === \"#\") current = notes.charAt(note - 1) + current\n\n                octave = Math.idiv((melody[i] - 24), 12)\n            }\n\n            const duration = melody[i + 1];\n\n            if (octave !== currentOctave) {\n                current += octave\n                currentOctave = octave;\n            }\n\n            if (duration !== currentDuration) {\n                current += \":\" + duration;\n                currentDuration = duration;\n            }\n\n            out.push(current);\n        }\n\n        return out;\n    }\n}\n","parts/headphone.svg":"<svg xmlns=\"http://www.w3.org/2000/svg\" width=\"142\" height=\"180\" viewBox=\"0 0 142 180\"><rect ry=\".3\" rx=\"1\" y=\"58.615\" x=\"-8.878\" height=\"23.571\" width=\"17.143\" transform=\"rotate(-45)\" fill=\"#b3b3b3\"/><rect ry=\".3\" rx=\"1\" y=\"32.043\" x=\"-8.878\" height=\"23.571\" width=\"17.143\" transform=\"rotate(-45)\" fill=\"#b3b3b3\"/><path d=\"M.346 7.296c-.394.39-.31 4.797-.18 4.898l13.404 10.18c.117.12.337 4.76.73 4.368l5.506-5.56.01.01 6.51-6.444c.39-.392-4.25-.614-4.366-.73L11.777.612c-.1-.132-4.51-.215-4.898.18L4.087 3.636l-.01-.01-3.73 3.67z\" fill=\"#b3b3b3\"/><rect ry=\"6.85\" rx=\"4.571\" y=\"84.758\" x=\"-20.128\" height=\"75.571\" width=\"39.643\" transform=\"rotate(-45)\"/><rect ry=\".374\" rx=\"1.038\" y=\"29.442\" x=\"-8.925\" height=\"2.228\" width=\"17.238\" transform=\"rotate(-45)\" fill=\"#fff\"/><rect ry=\".374\" rx=\"1.038\" y=\"55.939\" x=\"-8.925\" height=\"2.228\" width=\"17.238\" transform=\"rotate(-45)\" fill=\"#fff\"/><rect ry=\".374\" rx=\"1.038\" y=\"82.392\" x=\"-8.925\" height=\"2.228\" width=\"17.238\" transform=\"rotate(-45)\" fill=\"#fff\"/><rect ry=\"2.317\" rx=\"2.183\" y=\"158.876\" x=\"-9.774\" height=\"25.568\" width=\"18.935\" transform=\"rotate(-45)\"/><path d=\"M128.588 128.82s14.97 11.165 7.547 26.35c-8.426 17.24-25.57 20.653-25.57 20.653\" fill=\"none\" stroke=\"#000\" stroke-width=\"6.6\" stroke-linecap=\"round\" stroke-linejoin=\"round\"/></svg>","parts/speaker.svg":"<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<svg viewBox=\"0 0 500 500\" xmlns=\"http://www.w3.org/2000/svg\">\n  <g transform=\"matrix(1, 0, 0, 1, -0.00023, -58.230297)\">\n    <ellipse style=\"fill: rgb(70, 70, 70);\" cx=\"250.58\" cy=\"308.81\" rx=\"215\" ry=\"215\"/>\n    <ellipse style=\"fill: rgb(0, 0, 0);\" transform=\"matrix(1, 0, 0, 1.000001, -232.069031, 248.780606)\" cx=\"482.069\" cy=\"198.188\" rx=\"23.028\" ry=\"23.028\"/>\n    <ellipse style=\"fill: rgb(0, 0, 0);\" transform=\"matrix(1, 0, 0, 0.999999, -232.067871, 110.041956)\" cx=\"482.067\" cy=\"198.188\" rx=\"23.028\" ry=\"23.028\"/>\n    <ellipse style=\"fill: rgb(0, 0, 0);\" cx=\"389.12\" cy=\"308.23\" rx=\"23.028\" ry=\"23.028\"/>\n    <ellipse style=\"fill: rgb(0, 0, 0);\" cx=\"110.88\" cy=\"308.23\" rx=\"23.028\" ry=\"23.028\"/>\n    <ellipse style=\"fill: rgb(0, 0, 0);\" cx=\"250\" cy=\"169.393\" rx=\"23.028\" ry=\"23.028\"/>\n    <g transform=\"matrix(1, 0, 0, 1, -0.000009, 0.000015)\">\n      <ellipse style=\"fill: rgb(0, 0, 0);\" cx=\"250\" cy=\"238.513\" rx=\"23.028\" ry=\"23.028\" transform=\"matrix(1.000001, 0, 0, 0.999999, 69.996739, 69.71816)\"/>\n      <ellipse style=\"fill: rgb(0, 0, 0);\" transform=\"matrix(1, 0, 0, 0.999999, -302.064453, 110.043115)\" cx=\"482.064\" cy=\"198.188\" rx=\"23.028\" ry=\"23.028\"/>\n    </g>\n    <g transform=\"matrix(0.866026, 0.5, -0.5, 0.866026, 7.386552, -105.261086)\">\n      <ellipse style=\"fill: rgb(0, 0, 0);\" transform=\"matrix(0.999999, 0, 0, 0.999999, -65.212313, 177.387415)\" cx=\"482.068\" cy=\"198.188\" rx=\"23.028\" ry=\"23.028\"/>\n      <ellipse style=\"fill: rgb(0, 0, 0);\" cx=\"555.975\" cy=\"236.836\" rx=\"23.028\" ry=\"23.028\"/>\n      <ellipse style=\"fill: rgb(0, 0, 0);\" cx=\"277.735\" cy=\"236.836\" rx=\"23.028\" ry=\"23.028\"/>\n      <ellipse style=\"fill: rgb(0, 0, 0);\" cx=\"416.855\" cy=\"97.999\" rx=\"23.028\" ry=\"23.028\"/>\n    </g>\n    <g transform=\"matrix(0.5, 0.866026, -0.866026, 0.5, 246.635941, -171.170502)\">\n      <ellipse style=\"fill: rgb(0, 0, 0);\" transform=\"matrix(0.999999, 0, 0, 0.999999, -65.212313, 177.387415)\" cx=\"482.068\" cy=\"198.188\" rx=\"23.028\" ry=\"23.028\"/>\n      <ellipse style=\"fill: rgb(0, 0, 0);\" cx=\"555.975\" cy=\"236.836\" rx=\"23.028\" ry=\"23.028\"/>\n      <ellipse style=\"fill: rgb(0, 0, 0);\" cx=\"277.735\" cy=\"236.836\" rx=\"23.028\" ry=\"23.028\"/>\n      <ellipse style=\"fill: rgb(0, 0, 0);\" cx=\"416.855\" cy=\"97.999\" rx=\"23.028\" ry=\"23.028\"/>\n    </g>\n    <g transform=\"matrix(-0.5, 0.866026, -0.866026, -0.5, 641.934998, 245.84082)\">\n      <ellipse style=\"fill: rgb(0, 0, 0);\" cx=\"250\" cy=\"238.513\" rx=\"23.028\" ry=\"23.028\" transform=\"matrix(1.000001, 0, 0, 0.999999, 69.996739, 69.71816)\"/>\n      <ellipse style=\"fill: rgb(0, 0, 0);\" transform=\"matrix(1, 0, 0, 0.999999, -302.064453, 110.043115)\" cx=\"482.064\" cy=\"198.188\" rx=\"23.028\" ry=\"23.028\"/>\n    </g>\n    <g transform=\"matrix(-0.500001, -0.866026, 0.866026, -0.500001, 108.063393, 678.85083)\">\n      <ellipse style=\"fill: rgb(0, 0, 0);\" cx=\"250\" cy=\"238.513\" rx=\"23.028\" ry=\"23.028\" transform=\"matrix(1.000001, 0, 0, 0.999999, 69.996739, 69.71816)\"/>\n      <ellipse style=\"fill: rgb(0, 0, 0);\" transform=\"matrix(1, 0, 0, 0.999999, -302.064453, 110.043115)\" cx=\"482.064\" cy=\"198.188\" rx=\"23.028\" ry=\"23.028\"/>\n    </g>\n  </g>\n</svg>","perfcounters.ts":"namespace control {\n    /**\n     * Enable profiling for current function.\n     */\n    //% shim=TD_NOOP shimArgument=perfCounter\n    export function enablePerfCounter(name?: string) { }\n\n    /**\n     * Dump values of profiling performance counters.\n     */\n    //% shim=pxt::dumpPerfCounters\n    export function dmesgPerfCounters() { }\n}\n","pins.cpp":"#include \"pxt.h\"\n\n#if MICROBIT_CODAL\n#include \"Pin.h\"\n#define PinCompat codal::Pin\n#undef Button               // need to get codal Button back in scope here\n#include \"MicroBitButton.h\" // this include is missing in MicroBit.h from codal-microbit-v2 when DEVICE_BLE=0\n#else\n#define PinCompat MicroBitPin\n#endif\n\nenum class DigitalPin {\n    //% blockIdentity=\"pins._digitalPin\"\n    P0 = MICROBIT_ID_IO_P0,\n    //% blockIdentity=\"pins._digitalPin\"\n    P1 = MICROBIT_ID_IO_P1,\n    //% blockIdentity=\"pins._digitalPin\"\n    P2 = MICROBIT_ID_IO_P2,\n    //% blockIdentity=\"pins._digitalPin\"\n    P3 = MICROBIT_ID_IO_P3,\n    //% blockIdentity=\"pins._digitalPin\"\n    P4 = MICROBIT_ID_IO_P4,\n    //% blockIdentity=\"pins._digitalPin\"\n    P5 = MICROBIT_ID_IO_P5,\n    //% blockIdentity=\"pins._digitalPin\"\n    P6 = MICROBIT_ID_IO_P6,\n    //% blockIdentity=\"pins._digitalPin\"\n    P7 = MICROBIT_ID_IO_P7,\n    //% blockIdentity=\"pins._digitalPin\"\n    P8 = MICROBIT_ID_IO_P8,\n    //% blockIdentity=\"pins._digitalPin\"\n    P9 = MICROBIT_ID_IO_P9,\n    //% blockIdentity=\"pins._digitalPin\"\n    P10 = MICROBIT_ID_IO_P10,\n    //% blockIdentity=\"pins._digitalPin\"\n    P11 = MICROBIT_ID_IO_P11,\n    //% blockIdentity=\"pins._digitalPin\"\n    P12 = MICROBIT_ID_IO_P12,\n    //% blockIdentity=\"pins._digitalPin\"\n    P13 = MICROBIT_ID_IO_P13,\n    //% blockIdentity=\"pins._digitalPin\"\n    P14 = MICROBIT_ID_IO_P14,\n    //% blockIdentity=\"pins._digitalPin\"\n    P15 = MICROBIT_ID_IO_P15,\n    //% blockIdentity=\"pins._digitalPin\"\n    P16 = MICROBIT_ID_IO_P16,\n    //% blockIdentity=\"pins._digitalPin\"\n    //% blockHidden=1\n    P19 = MICROBIT_ID_IO_P19,\n    //% blockIdentity=\"pins._digitalPin\"\n    //% blockHidden=1\n    P20 = MICROBIT_ID_IO_P20,\n};\n\nenum class AnalogPin {\n    //% blockIdentity=\"pins._analogPin\"\n    P0 = MICROBIT_ID_IO_P0,\n    //% blockIdentity=\"pins._analogPin\"\n    P1 = MICROBIT_ID_IO_P1,\n    //% blockIdentity=\"pins._analogPin\"\n    P2 = MICROBIT_ID_IO_P2,\n    //% blockIdentity=\"pins._analogPin\"\n    P3 = MICROBIT_ID_IO_P3,\n    //% blockIdentity=\"pins._analogPin\"\n    P4 = MICROBIT_ID_IO_P4,\n    //% blockIdentity=\"pins._analogPin\"\n    P5 = MICROBIT_ID_IO_P5,\n    //% blockIdentity=\"pins._analogPin\"\n    P6 = MICROBIT_ID_IO_P6,\n    //% blockIdentity=\"pins._analogPin\"\n    P7 = MICROBIT_ID_IO_P7,\n    //% blockIdentity=\"pins._analogPin\"\n    P8 = MICROBIT_ID_IO_P8,\n    //% blockIdentity=\"pins._analogPin\"\n    P9 = MICROBIT_ID_IO_P9,\n    //% blockIdentity=\"pins._analogPin\"\n    P10 = MICROBIT_ID_IO_P10,\n    //% blockIdentity=\"pins._analogPin\"\n    P11 = MICROBIT_ID_IO_P11,\n    //% blockIdentity=\"pins._analogPin\"\n    P12 = MICROBIT_ID_IO_P12,\n    //% blockIdentity=\"pins._analogPin\"\n    P13 = MICROBIT_ID_IO_P13,\n    //% blockIdentity=\"pins._analogPin\"\n    P14 = MICROBIT_ID_IO_P14,\n    //% blockIdentity=\"pins._analogPin\"\n    P15 = MICROBIT_ID_IO_P15,\n    //% blockIdentity=\"pins._analogPin\"\n    P16 = MICROBIT_ID_IO_P16,\n    //% blockIdentity=\"pins._analogPin\"\n    //% blockHidden=1\n    P19 = MICROBIT_ID_IO_P19,\n    //% blockIdentity=\"pins._analogPin\"\n    //% blockHidden=1\n    P20 = MICROBIT_ID_IO_P20\n};\n\nenum class PulseValue {\n    //% block=high\n    High = MICROBIT_PIN_EVT_PULSE_HI,\n    //% block=low\n    Low = MICROBIT_PIN_EVT_PULSE_LO\n};\n\nenum class PinPullMode {\n    //% block=\"down\"\n    PullDown = 0,\n    //% block=\"up\"\n    PullUp = 1,\n    //% block=\"none\"\n    PullNone = 2\n};\n\nenum class PinEventType {\n    //% block=\"edge\"\n    Edge = MICROBIT_PIN_EVENT_ON_EDGE,\n    //% block=\"pulse\"\n    Pulse = MICROBIT_PIN_EVENT_ON_PULSE,\n    //% block=\"touch\"\n    Touch = MICROBIT_PIN_EVENT_ON_TOUCH,\n    //% block=\"none\"\n    None = MICROBIT_PIN_EVENT_NONE\n};\n\n\nnamespace pxt\n{\nMicroBitPin *getPin(int id) {\n    switch (id) {\n        case MICROBIT_ID_IO_P0: return &uBit.io.P0;\n        case MICROBIT_ID_IO_P1: return &uBit.io.P1;\n        case MICROBIT_ID_IO_P2: return &uBit.io.P2;\n        case MICROBIT_ID_IO_P3: return &uBit.io.P3;\n        case MICROBIT_ID_IO_P4: return &uBit.io.P4;\n        case MICROBIT_ID_IO_P5: return &uBit.io.P5;\n        case MICROBIT_ID_IO_P6: return &uBit.io.P6;\n        case MICROBIT_ID_IO_P7: return &uBit.io.P7;\n        case MICROBIT_ID_IO_P8: return &uBit.io.P8;\n        case MICROBIT_ID_IO_P9: return &uBit.io.P9;\n        case MICROBIT_ID_IO_P10: return &uBit.io.P10;\n        case MICROBIT_ID_IO_P11: return &uBit.io.P11;\n        case MICROBIT_ID_IO_P12: return &uBit.io.P12;\n        case MICROBIT_ID_IO_P13: return &uBit.io.P13;\n        case MICROBIT_ID_IO_P14: return &uBit.io.P14;\n        case MICROBIT_ID_IO_P15: return &uBit.io.P15;\n        case MICROBIT_ID_IO_P16: return &uBit.io.P16;\n        case MICROBIT_ID_IO_P19: return &uBit.io.P19;\n        case MICROBIT_ID_IO_P20: return &uBit.io.P20;\n#if MICROBIT_CODAL\n        case 1001: return &uBit.io.usbTx;\n        case 1002: return &uBit.io.usbRx;\n#endif\n        default: return NULL;\n    }\n}\n\n} // pxt\n\nnamespace pins {\n    #define PINOP(op) \\\n      MicroBitPin *pin = getPin((int)name); \\\n      if (!pin) return; \\\n      pin->op\n\n    #define PINREAD(op) \\\n      MicroBitPin *pin = getPin((int)name); \\\n      if (!pin) return 0; \\\n      return pin->op\n\n\n    //%\n    MicroBitPin *getPinAddress(int id) {\n        return getPin(id);\n    }\n\n    /**\n     * Read the specified pin or connector as either 0 or 1\n     * @param name pin to read from, eg: DigitalPin.P0\n     */\n    //% help=pins/digital-read-pin weight=30\n    //% blockId=device_get_digital_pin block=\"digital read|pin %name\" blockGap=8\n    //% name.shadow=digital_pin_shadow\n    int digitalReadPin(int name) {\n        PINREAD(getDigitalValue());\n    }\n\n    /**\n      * Set a pin or connector value to either 0 or 1.\n      * @param name pin to write to, eg: DigitalPin.P0\n      * @param value value to set on the pin, 1 eg,0\n      */\n    //% help=pins/digital-write-pin weight=29\n    //% blockId=device_set_digital_pin block=\"digital write|pin %name|to %value\"\n    //% value.min=0 value.max=1\n    //% name.shadow=digital_pin_shadow\n    void digitalWritePin(int name, int value) {\n        PINOP(setDigitalValue(value));\n    }\n\n    /**\n     * Read the connector value as analog, that is, as a value comprised between 0 and 1023.\n     * @param name pin to write to, eg: AnalogPin.P0\n     */\n    //% help=pins/analog-read-pin weight=25\n    //% blockId=device_get_analog_pin block=\"analog read|pin %name\" blockGap=\"8\"\n    //% name.shadow=analog_read_write_pin_shadow\n    int analogReadPin(int name) {\n        PINREAD(getAnalogValue());\n    }\n\n    /**\n     * Set the connector value as analog. Value must be comprised between 0 and 1023.\n     * @param name pin name to write to, eg: AnalogPin.P0\n     * @param value value to write to the pin between ``0`` and ``1023``. eg:1023,0\n     */\n    //% help=pins/analog-write-pin weight=24\n    //% blockId=device_set_analog_pin block=\"analog write|pin %name|to %value\" blockGap=8\n    //% value.min=0 value.max=1023\n    //% name.shadow=analog_pin_shadow\n    void analogWritePin(int name, int value) {\n        PINOP(setAnalogValue(value));\n    }\n\n    /**\n     * Configure the pulse-width modulation (PWM) period of the analog output in microseconds.\n     * If this pin is not configured as an analog output (using `analog write pin`), the operation has no effect.\n     * @param name analog pin to set period to, eg: AnalogPin.P0\n     * @param micros period in microseconds. eg:20000\n     */\n    //% help=pins/analog-set-period weight=23 blockGap=8\n    //% blockId=device_set_analog_period block=\"analog set period|pin %pin|to (µs)%micros\"\n    //% pin.shadow=analog_pin_shadow\n    void analogSetPeriod(int name, int micros) {\n        PINOP(setAnalogPeriodUs(micros));\n    }\n\n    /**\n    * Configure the pin as a digital input and generate an event when the pin is pulsed either high or low.\n    * @param name digital pin to register to, eg: DigitalPin.P0\n    * @param pulse the value of the pulse, eg: PulseValue.High\n    */\n    //% help=pins/on-pulsed advanced=true\n    //% blockId=pins_on_pulsed block=\"on|pin %pin|pulsed %pulse\"\n    //% pin.fieldEditor=\"gridpicker\" pin.fieldOptions.columns=4\n    //% pin.fieldOptions.tooltips=\"false\" pin.fieldOptions.width=\"250\"\n    //% group=\"Pulse\"\n    //% weight=25\n    //% blockGap=8\n    void onPulsed(DigitalPin name, PulseValue pulse, Action body) {\n        MicroBitPin* pin = getPin((int)name);\n        if (!pin) return;\n\n        pin->eventOn(MICROBIT_PIN_EVENT_ON_PULSE);\n        registerWithDal((int)name, (int)pulse, body);\n    }\n\n    /**\n    * Get the duration of the last pulse in microseconds. This function should be called from a ``onPulsed`` handler.\n    */\n    //% help=pins/pulse-duration advanced=true\n    //% blockId=pins_pulse_duration block=\"pulse duration (µs)\"\n    //% group=\"Pulse\"\n    //% weight=24\n    //% blockGap=8\n    int pulseDuration() {\n        return pxt::lastEvent.timestamp;\n    }\n\n    /**\n    * Return the duration of a pulse at a pin in microseconds.\n    * @param name the pin which measures the pulse, eg: DigitalPin.P0\n    * @param value the value of the pulse, eg: PulseValue.High\n    * @param maximum duration in microseconds\n    */\n    //% blockId=\"pins_pulse_in\" block=\"pulse in (µs)|pin %name|pulsed %value\"\n    //% advanced=true\n    //% help=pins/pulse-in\n    //% name.shadow=digital_pin_shadow\n    //% group=\"Pulse\"\n    //% weight=23\n    //% blockGap=8\n    int pulseIn(int name, PulseValue value, int maxDuration = 2000000) {\n        MicroBitPin* pin = getPin((int)name);\n        if (!pin) return 0;\n\n#if MICROBIT_CODAL\n        // set polarity\n        pin->setPolarity(PulseValue::High == value ? 1 : 0);\n        // record pulse\n        int period = pin->getPulseUs(maxDuration);\n        // timeout\n        if (DEVICE_CANCELLED == period)\n            return 0;\n        // success!\n        return period;\n#else\n        int pulse = value == PulseValue::High ? 1 : 0;\n        uint64_t tick =  system_timer_current_time_us();\n        uint64_t maxd = (uint64_t)maxDuration;\n        while(pin->getDigitalValue() != pulse) {\n            if(system_timer_current_time_us() - tick > maxd)\n                return 0;\n        }\n\n        uint64_t start =  system_timer_current_time_us();\n        while(pin->getDigitalValue() == pulse) {\n            if(system_timer_current_time_us() - tick > maxd)\n                return 0;\n        }\n        uint64_t end =  system_timer_current_time_us();\n        return end - start;\n#endif\n    }\n\n    /**\n     * Write a value to the servo, controlling the shaft accordingly. On a standard servo, this will set the angle of the shaft (in degrees), moving the shaft to that orientation. On a continuous rotation servo, this will set the speed of the servo (with ``0`` being full-speed in one direction, ``180`` being full speed in the other, and a value near ``90`` being no movement).\n     * @param name pin to write to, eg: AnalogPin.P0\n     * @param value angle or rotation speed, eg:180,90,0\n     */\n    //% help=pins/servo-write-pin weight=20\n    //% blockId=device_set_servo_pin block=\"servo write|pin %name|to %value\" blockGap=8\n    //% parts=microservo trackArgs=0\n    //% value.min=0 value.max=180\n    //% name.shadow=analog_pin_shadow\n    //% group=\"Servo\"\n    void servoWritePin(int name, int value) {\n        PINOP(setServoValue(value));\n    }\n\n    /**\n    * Specifies that a continuous servo is connected.\n    */\n    //%\n    void servoSetContinuous(int name, bool value) {\n        // handled in simulator\n    }\n\n    /**\n     * Configure the IO pin as an analog/pwm output and set a pulse width. The period is 20 ms period and the pulse width is set based on the value given in **microseconds** or `1/1000` milliseconds.\n     * @param name pin name\n     * @param micros pulse duration in microseconds, eg:1500\n     */\n    //% help=pins/servo-set-pulse weight=19\n    //% blockId=device_set_servo_pulse block=\"servo set pulse|pin %value|to (µs) %micros\"\n    //% value.shadow=analog_pin_shadow\n    //% group=\"Servo\"\n    void servoSetPulse(int name, int micros) {\n        PINOP(setServoPulseUs(micros));\n    }\n\n\n    PinCompat* pitchPin = NULL;\n    uint8_t pitchVolume = 0xff;\n    bool analogTonePlaying = false;\n    bool edgeConnectorSoundDisabled = false;\n\n    /**\n     * Set the pin used when using analog pitch or music.\n     * @param name pin to modulate pitch from\n     */\n    //% blockId=device_analog_set_pitch_pin block=\"analog set pitch pin %name\"\n    //% help=pins/analog-set-pitch-pin advanced=true\n    //% name.shadow=analog_pin_shadow\n    //% group=\"Pins\"\n    //% weight=12\n    //% blockGap=8\n    void analogSetPitchPin(int name) {\n        pitchPin = getPin((int)name);\n    }\n\n    void pinAnalogSetPitch(PinCompat* pin, int frequency, int ms) {\n      if (frequency <= 0 || pitchVolume == 0) {\n        pin->setAnalogValue(0);\n      } else {\n        int v = 1 << (pitchVolume >> 5);\n        pin->setAnalogValue(v);\n        pin->setAnalogPeriodUs(1000000/frequency);\n      }\n    }\n\n    /**\n    * Sets the volume on the pitch pin\n    * @param volume the intensity of the sound from 0..255\n    */\n    //% blockId=device_analog_set_pitch_volume block=\"analog set pitch volume $volume\"\n    //% help=pins/analog-set-pitch-volume weight=3 advanced=true\n    //% volume.min=0 volume.max=255\n    //% deprecated\n    void analogSetPitchVolume(int volume) {\n        pitchVolume = max(0, min(0xff, volume));\n\n        if (analogTonePlaying) {\n            int v = pitchVolume == 0 ? 0 : 1 << (pitchVolume >> 5);\n            if (NULL != pitchPin && !edgeConnectorSoundDisabled)\n                pitchPin->setAnalogValue(v);\n        }\n    }\n\n    /**\n    * Gets the volume the pitch pin from 0..255\n    */\n    //% blockId=device_analog_pitch_volume block=\"analog pitch volume\"\n    //% help=pins/analog-pitch-volume weight=3 advanced=true\n    //% deprecated\n    int analogPitchVolume() {\n        return pitchVolume;\n    }\n\n    /**\n     * Send a pulse-width modulation (PWM) signal to the current pitch pin. Use `analog set pitch pin` to define the pitch pin.\n     * @param frequency frequency to modulate in Hz.\n     * @param ms duration of the pitch in milliseconds.\n     */\n    //% blockId=device_analog_pitch block=\"analog pitch %frequency|for (ms) %ms\"\n    //% help=pins/analog-pitch async advanced=true\n    //% group=\"Pins\"\n    //% weight=14\n    //% blockGap=8\n    void analogPitch(int frequency, int ms) {\n        // init pins if needed\n        if (NULL == pitchPin) {\n#if MICROBIT_CODAL\n            pitchPin = &uBit.audio.virtualOutputPin;\n#else\n            pitchPin = getPin((int)AnalogPin::P0);\n#endif\n        }\n        // set pitch\n        analogTonePlaying = true;\n\n#if MICROBIT_CODAL\n        if (NULL != pitchPin)\n            pinAnalogSetPitch(pitchPin, frequency, ms);\n        // clear pitch\n        if (ms > 0) {\n            fiber_sleep(ms);\n            if (NULL != pitchPin)\n                pitchPin->setAnalogValue(0);\n            analogTonePlaying = false;\n            // causes issues with v2 DMA.\n            // fiber_sleep(5);\n        }\n#else\n        if (NULL != pitchPin && !edgeConnectorSoundDisabled)\n            pinAnalogSetPitch(pitchPin, frequency, ms);\n        // clear pitch\n        if (ms > 0) {\n            fiber_sleep(ms);\n            if (NULL != pitchPin && !edgeConnectorSoundDisabled)\n                pitchPin->setAnalogValue(0);\n            analogTonePlaying = false;\n            // causes issues with v2 DMA.\n            // fiber_sleep(5);\n        }\n#endif\n    }\n\n\n    /**\n    * Configure the pull direction of of a pin.\n    * @param name pin to set the pull mode on, eg: DigitalPin.P0\n    * @param pull one of the mbed pull configurations, eg: PinPullMode.PullUp\n    */\n    //% help=pins/set-pull advanced=true\n    //% blockId=device_set_pull block=\"set pull|pin %pin|to %pull\"\n    //% pin.shadow=digital_pin_shadow\n    //% group=\"Pins\"\n    //% weight=15\n    //% blockGap=8\n    void setPull(int name, PinPullMode pull) {\n#if MICROBIT_CODAL\n        codal::PullMode m = pull == PinPullMode::PullDown\n            ? codal::PullMode::Down\n            : pull == PinPullMode::PullUp ? codal::PullMode::Up\n            : codal::PullMode::None;\n        PINOP(setPull(m));\n#else\n        PinMode m = pull == PinPullMode::PullDown\n            ? PinMode::PullDown\n            : pull == PinPullMode::PullUp ? PinMode::PullUp\n            : PinMode::PullNone;\n        PINOP(setPull(m));\n#endif\n    }\n\n    /**\n    * Configure the events emitted by this pin. Events can be subscribed to\n    * using ``control.onEvent()``.\n    * @param name pin to set the event mode on, eg: DigitalPin.P0\n    * @param type the type of events for this pin to emit, eg: PinEventType.Edge\n    */\n    //% help=pins/set-events advanced=true\n    //% blockId=device_set_pin_events block=\"set pin %pin|to emit %type|events\"\n    //% pin.shadow=digital_pin_shadow\n    //% group=\"Pins\"\n    //% weight=13\n    //% blockGap=8\n    void setEvents(int name, PinEventType type) {\n        getPin((int)name)->eventOn((int)type);\n    }\n\n    /**\n     * Create a new zero-initialized buffer.\n     * @param size number of bytes in the buffer\n     */\n    //%\n    Buffer createBuffer(int size)\n    {\n        return mkBuffer(NULL, size);\n    }\n\n\n    /**\n     * Set the matrix width for Neopixel strip (already assigned to a pin).\n     * Should be used in conjunction with `set matrix width` from Neopixel package.\n     * @param name pin of Neopixel strip, eg: DigitalPin.P1\n     * @param value width of matrix (at least ``2``)\n     */\n    //% help=pins/neopixel-matrix-width advanced=true\n    //% blockId=pin_neopixel_matrix_width block=\"neopixel matrix width|pin %pin %width\"\n    //% pin.shadow=digital_pin_shadow\n    //% width.defl=5 width.min=2\n    //% group=\"Pins\"\n    //% weight=11\n    //% blockGap=8\n    void setMatrixWidth(int pin, int width) {}\n\n#if MICROBIT_CODAL\n#define BUFFER_TYPE uint8_t*\n#else\n#define BUFFER_TYPE char*\n#endif\n\n    /**\n     * Read `size` bytes from a 7-bit I2C `address`.\n     */\n    //%\n    Buffer i2cReadBuffer(int address, int size, bool repeat = false)\n    {\n      Buffer buf = createBuffer(size);\n      uBit.i2c.read(address << 1, (BUFFER_TYPE)buf->data, size, repeat);\n      return buf;\n    }\n\n    /**\n     * Write bytes to a 7-bit I2C `address`.\n     */\n    //%\n    int i2cWriteBuffer(int address, Buffer buf, bool repeat = false)\n    {\n      return uBit.i2c.write(address << 1, (BUFFER_TYPE)buf->data, buf->length, repeat);\n    }\n\n    SPI* spi = NULL;\n    SPI* allocSPI() {\n        if (NULL == spi)\n            spi = new SPI(MOSI, MISO, SCK);\n        return spi;\n    }\n\n    /**\n    * Write to the SPI slave and return the response\n    * @param value Data to be sent to the SPI slave\n    */\n    //% help=pins/spi-write advanced=true\n    //% blockId=spi_write block=\"spi write %value\"\n    //% group=\"SPI\"\n    //% blockGap=8\n    //% weight=53\n    int spiWrite(int value) {\n        auto p = allocSPI();\n        return p->write(value);\n    }\n\n    /**\n    * Write to and read from the SPI slave at the same time\n    * @param command Data to be sent to the SPI slave (can be null)\n    * @param response Data received from the SPI slave (can be null)\n    */\n    //% help=pins/spi-transfer argsNullable\n    void spiTransfer(Buffer command, Buffer response) {\n        if (!command && !response)\n            target_panic(PANIC_INVALID_ARGUMENT);\n        if (command && response && command->length != response->length)\n            target_panic(PANIC_INVALID_ARGUMENT);\n        auto p = allocSPI();\n        unsigned len = command ? command->length : response->length;\n#if MICROBIT_CODAL\n        p->transfer(command ? command->data : NULL, command ? len : 0,\n                    response ? response->data : NULL, response ? len : 0);\n#else\n        for (unsigned i = 0; i < len; ++i) {\n            int v = p->write(command ? command->data[i] : 0);\n            if (response) response->data[i] = v;\n        }\n#endif\n    }\n\n    /**\n    * Set the SPI frequency\n    * @param frequency the clock frequency, eg: 1000000\n    */\n    //% help=pins/spi-frequency advanced=true\n    //% blockId=spi_frequency block=\"spi frequency %frequency\"\n    //% group=\"SPI\"\n    //% blockGap=8\n    //% weight=55\n    void spiFrequency(int frequency) {\n        auto p = allocSPI();\n        p->frequency(frequency);\n    }\n\n    /**\n    * Set the SPI bits and mode\n    * @param bits the number of bits, eg: 8\n    * @param mode the mode, eg: 3\n    */\n    //% help=pins/spi-format advanced=true\n    //% blockId=spi_format block=\"spi format|bits %bits|mode %mode\"\n    //% group=\"SPI\"\n    //% blockGap=8\n    //% weight=54\n    void spiFormat(int bits, int mode) {\n        auto p = allocSPI();\n        p->format(bits, mode);\n    }\n\n#if MICROBIT_CODAL\n#define PIN_ARG(pin) *(getPin((int)(pin)))\n#else\n#define PIN_ARG(pin) (getPin((int)(pin)))->name\n#endif\n\n    /**\n    * Set the MOSI, MISO, SCK pins used by the SPI connection\n    *\n    */\n    //% help=pins/spi-pins advanced=true\n    //% blockId=spi_pins block=\"spi set pins|MOSI %mosi|MISO %miso|SCK %sck\"\n    //% mosi.shadow=digital_pin_shadow\n    //% miso.shadow=digital_pin_shadow\n    //% sck.shadow=digital_pin_shadow\n    //% group=\"SPI\"\n    //% blockGap=8\n    //% weight=51\n    void spiPins(int mosi, int miso, int sck) {\n        if (NULL != spi) {\n            delete spi;\n            spi = NULL;\n        }\n        spi = new SPI(PIN_ARG(mosi), PIN_ARG(miso), PIN_ARG(sck));\n    }\n\n    /**\n    * Mounts a push button on the given pin\n    */\n    //% help=pins/push-button advanced=true\n    void pushButton(int pin) {\n        new MicroBitButton((PinName)getPin((int)(pin))->name, (int)pin, MICROBIT_BUTTON_ALL_EVENTS, PinMode::PullUp);\n    }\n\n    /**\n    * Set the pin used when producing sounds and melodies. Default is P0.\n    * @param name pin to modulate pitch from\n    */\n    //% blockId=pin_set_audio_pin block=\"set audio pin $name\"\n    //% help=pins/set-audio-pin\n    //% name.shadow=digital_pin_shadow\n    //% weight=1\n    //% blockGap=8\n    void setAudioPin(int name) {\n#if MICROBIT_CODAL\n        uBit.audio.setPin(*getPin((int)name));\n        uBit.audio.setPinEnabled(!edgeConnectorSoundDisabled);\n#else\n        // v1 behavior\n        pins::analogSetPitchPin(name);\n#endif\n    }\n\n    /**\n    * Sets whether or not audio will be output using a pin on the edge\n    * connector.\n    */\n    //% blockId=pin_set_audio_pin_enabled\n    //% block=\"set audio pin enabled $enabled\"\n    //% weight=0 help=pins/set-audio-pin-enabled\n    void setAudioPinEnabled(bool enabled) {\n        edgeConnectorSoundDisabled = !enabled;\n#if MICROBIT_CODAL\n        uBit.audio.setPinEnabled(enabled);\n#endif\n    }\n}\n","pins.ts":"/**\n * Control currents in Pins for analog/digital signals, servos, i2c, ...\n */\n//% color=#B22222 weight=30 icon=\"\\uf140\"\n//% advanced=true\n//% groups='[\"Pins\", \"Pulse\", \"I2C\", \"SPI\", \"micro:bit (V2)\"]'\nnamespace pins {\n    /**\n     * Returns the value of a C++ runtime constant\n     */\n    //% help=pins/digital-pin\n    //% shim=TD_ID\n    //% blockId=digital_pin\n    //% block=\"digital pin $pin\"\n    //% pin.fieldEditor=pinpicker\n    //% pin.fieldOptions.columns=4\n    //% pin.fieldOptions.tooltips=\"false\"\n    //% group=\"Pins\"\n    //% weight=17\n    //% blockGap=8\n    //% advanced=true\n    //% decompilerShadowAlias=digital_pin_shadow\n    export function _digitalPin(pin: DigitalPin): number {\n        return pin;\n    }\n\n    /**\n     * Returns the value of a C++ runtime constant\n     */\n    //% help=pins/analog-pin\n    //% shim=TD_ID\n    //% blockId=analog_pin\n    //% block=\"analog pin $pin\"\n    //% pin.fieldEditor=pinpicker\n    //% pin.fieldOptions.columns=4\n    //% pin.fieldOptions.tooltips=\"false\"\n    //% group=\"Pins\"\n    //% weight=16\n    //% blockGap=8\n    //% advanced=true\n    //% decompilerShadowAlias=analog_pin_shadow\n    export function _analogPin(pin: AnalogPin): number {\n        return pin;\n    }\n\n    /**\n     * Returns the value of a C++ runtime constant\n     */\n    //% help=pins/digital-pin\n    //% shim=TD_ID\n    //% blockId=digital_pin_shadow\n    //% block=\"$pin\"\n    //% pin.fieldEditor=pinpicker\n    //% pin.fieldOptions.columns=4\n    //% pin.fieldOptions.tooltips=\"false\"\n    //% blockHidden=1\n    export function _digitalPinShadow(pin: DigitalPin): number {\n        return pin;\n    }\n\n    /**\n     * Returns the value of a C++ runtime constant\n     */\n    //% help=pins/analog-pin\n    //% shim=TD_ID\n    //% blockId=analog_pin_shadow\n    //% block=\"$pin\"\n    //% pin.fieldEditor=pinpicker\n    //% pin.fieldOptions.columns=4\n    //% pin.fieldOptions.tooltips=\"false\"\n    //% blockHidden=1\n    export function _analogPinShadow(pin: AnalogPin): number {\n        return pin;\n    }\n\n    /**\n     * Returns the value of a C++ runtime constant\n     */\n    //% help=pins/analog-pin\n    //% shim=TD_ID\n    //% blockId=analog_read_write_pin_shadow\n    //% block=\"$pin\"\n    //% pin.fieldEditor=pinpicker\n    //% pin.fieldOptions.columns=4\n    //% pin.fieldOptions.tooltips=\"false\"\n    //% blockHidden=1\n    export function _analogReadWritePinShadow(pin: AnalogReadWritePin): number {\n        return pin;\n    }\n\n    /**\n     * Map a number from one range to another. That is, a value of ``from low`` would get mapped to ``to low``, a value of ``from high`` to ``to high``, values in-between to values in-between, etc.\n     * @param value value to map in ranges\n     * @param fromLow the lower bound of the value's current range\n     * @param fromHigh the upper bound of the value's current range, eg: 1023\n     * @param toLow the lower bound of the value's target range\n     * @param toHigh the upper bound of the value's target range, eg: 4\n     */\n    //% help=pins/map weight=23\n    //% blockId=pin_map block=\"map %value|from low %fromLow|from high %fromHigh|to low %toLow|to high %toHigh\"\n    export function map(value: number, fromLow: number, fromHigh: number, toLow: number, toHigh: number): number {\n        return ((value - fromLow) * (toHigh - toLow)) / (fromHigh - fromLow) + toLow;\n    }\n\n    /**\n     * Read one number from 7-bit I2C address.\n     */\n    //% help=pins/i2c-read-number blockGap=8 advanced=true\n    //% blockId=pins_i2c_readnumber block=\"i2c read number|at address %address|of format %format|repeated %repeat\" weight=7\n    //% group=\"I2C\"\n    //% weight=45\n    export function i2cReadNumber(address: number, format: NumberFormat, repeated?: boolean): number {\n        let buf = pins.i2cReadBuffer(address, pins.sizeOf(format), repeated)\n        return buf.getNumber(format, 0)\n    }\n\n    /**\n     * Write one number to a 7-bit I2C address.\n     */\n    //% help=pins/i2c-write-number blockGap=8 advanced=true\n    //% blockId=i2c_writenumber block=\"i2c write number|at address %address|with value %value|of format %format|repeated %repeat\" weight=6\n    //% group=\"I2C\"\n    //% weight=44\n    export function i2cWriteNumber(address: number, value: number, format: NumberFormat, repeated?: boolean): void {\n        let buf = createBuffer(pins.sizeOf(format))\n        buf.setNumber(format, 0, value)\n        pins.i2cWriteBuffer(address, buf, repeated)\n    }\n}\n","pinscompat.ts":"enum PinEvent {\n    //% block=\"pulse high\"\n    PulseHigh = DAL.MICROBIT_PIN_EVT_PULSE_HI,  // DEVICE_PIN_EVT_PULSE_HI\n    //% block=\"pulse low\"\n    PulseLow = DAL.MICROBIT_PIN_EVT_PULSE_LO,  // DEVICE_PIN_EVT_PULSE_LO\n    //% block=\"rise\"\n    Rise = DAL.MICROBIT_PIN_EVT_RISE,  // DEVICE_PIN_EVT_RISE\n    //% block=\"fall\"\n    Fall = DAL.MICROBIT_PIN_EVT_FALL,  // DEVICE_PIN_EVT_FALL\n}\n\nenum AnalogReadWritePin {\n    //% blockIdentity=\"pins._analogReadWritePinShadow\"\n    P0 = AnalogPin.P0,\n    //% blockIdentity=\"pins._analogReadWritePinShadow\"\n    P1 = AnalogPin.P1,\n    //% blockIdentity=\"pins._analogReadWritePinShadow\"\n    P2 = AnalogPin.P2,\n    //% blockIdentity=\"pins._analogReadWritePinShadow\"\n    P3 = AnalogPin.P3,\n    //% blockIdentity=\"pins._analogReadWritePinShadow\"\n    P4 = AnalogPin.P4,\n    //% blockIdentity=\"pins._analogReadWritePinShadow\"\n    P10 = AnalogPin.P10,\n}\n\n//% noRefCounting fixedInstances\ninterface DigitalInOutPin {\n    digitalRead(): boolean;\n\n    digitalWrite(value: boolean): void;\n\n    onPulsed(pulse: PulseValue, body: () => void): void;\n\n    onEvent(event: PinEvent, body: () => void): void;\n\n    pulseIn(value: PulseValue, maxDuration?: number): number;\n\n    setPull(pull: PinPullMode): void;\n}\n\n//% noRefCounting fixedInstances\ninterface AnalogInPin extends DigitalInOutPin {\n    analogRead(): number;\n}\n\n//% noRefCounting fixedInstances\ninterface AnalogOutPin extends DigitalInOutPin {\n    analogWrite(value: number): void;\n}\n\n//% noRefCounting fixedInstances\ninterface AnalogInOutPin extends AnalogInPin, AnalogOutPin {\n}\n\n//% noRefCounting fixedInstances\ninterface PwmOnlyPin extends DigitalInOutPin, AnalogOutPin {\n    //% parts=microservo trackArgs=0\n    analogSetPeriod(period: number): void;\n\n    //% parts=microservo trackArgs=0\n    servoWrite(value: number): void;\n\n    //% parts=microservo trackArgs=0\n    servoSetPulse(duration: number): void;\n\n    //% parts=microservo tracArgs=0\n    servoSetContinuous(value: boolean): void;\n}\n\n//% noRefCounting fixedInstances\ninterface PwmPin extends PwmOnlyPin, DigitalInOutPin, AnalogInPin {\n}\n\n//% noRefCounting fixedInstances\nclass MicrobitPin implements AnalogInPin, AnalogOutPin, AnalogInOutPin, PwmOnlyPin {\n    public id: number;\n    constructor(id: number) {\n        this.id = id;\n    }\n\n    protected digitalId(): DigitalPin {\n        return <DigitalPin>this.id;\n    }\n\n    protected analogId(): AnalogPin {\n        return <AnalogPin>this.id;\n    }\n\n    digitalRead(): boolean {\n        return pins.digitalReadPin(this.digitalId()) != 0;\n    }\n\n    digitalWrite(value: boolean): void {\n        pins.digitalWritePin(this.digitalId(), value ? 1 : 0);\n    }\n\n    onPulsed(pulse: PulseValue, body: () => void): void {\n        pins.onPulsed(this.digitalId(), pulse, body);\n    }\n\n    onEvent(event: PinEvent, body: () => void): void {\n        // TODO\n    }\n\n    pulseIn(value: PulseValue, maxDuration?: number): number {\n        return pins.pulseIn(this.digitalId(), value, maxDuration);\n    }\n\n    setPull(pull: PinPullMode): void {\n        pins.setPull(this.digitalId(), pull);\n    }\n\n    analogRead(): number {\n        return pins.analogReadPin(this.analogId());\n    }\n\n    analogWrite(value: number): void {\n        pins.analogWritePin(this.analogId(), value);\n    }\n\n    analogSetPeriod(period: number): void {\n        pins.analogSetPeriod(this.analogId(), period);\n    }\n\n    servoWrite(value: number): void {\n        pins.servoWritePin(this.analogId(), value);\n    }\n\n    servoSetContinuous(value: boolean): void {\n        pins.servoSetContinuous(this.analogId(), value);\n    }\n\n    servoSetPulse(duration: number): void {\n        pins.servoSetPulse(this.analogId(), duration);\n    }\n}\n\nnamespace pins {\n    /**\n     * Pin P0\n     */\n    //% fixedInstance whenUsed\n    export const P0: PwmPin = new MicrobitPin(DigitalPin.P0);\n\n    /**\n     * Pin P1\n     */\n    //% fixedInstance whenUsed\n    export const P1: PwmPin = new MicrobitPin(DigitalPin.P1);\n\n    /**\n     * Pin P2\n     */\n    //% fixedInstance whenUsed\n    export const P2: PwmPin = new MicrobitPin(DigitalPin.P2);\n\n    /**\n     * Pin P3\n     */\n    //% fixedInstance whenUsed\n    export const P3: AnalogInPin = new MicrobitPin(DigitalPin.P3);\n\n    /**\n     * Pin P4\n     */\n    //% fixedInstance whenUsed\n    export const P4: AnalogInPin = new MicrobitPin(DigitalPin.P4);\n\n    /**\n     * Pin P5\n     */\n    //% fixedInstance whenUsed\n    export const P5: DigitalInOutPin = new MicrobitPin(DigitalPin.P5);\n\n    /**\n     * Pin P6\n     */\n    //% fixedInstance whenUsed\n    export const P6: DigitalInOutPin = new MicrobitPin(DigitalPin.P6);\n\n    /**\n     * Pin P7\n     */\n    //% fixedInstance whenUsed\n    export const P7: DigitalInOutPin = new MicrobitPin(DigitalPin.P7);\n\n    /**\n     * Pin P8\n     */\n    //% fixedInstance whenUsed\n    export const P8: DigitalInOutPin = new MicrobitPin(DigitalPin.P8);\n\n    /**\n     * Pin P9\n     */\n    //% fixedInstance whenUsed\n    export const P9: DigitalInOutPin = new MicrobitPin(DigitalPin.P9);\n\n    /**\n     * Pin P10\n     */\n    //% fixedInstance whenUsed\n    export const P10: AnalogInPin = new MicrobitPin(DigitalPin.P10);\n\n    /**\n     * Pin P3\n     */\n    //% fixedInstance whenUsed\n    export const P11: DigitalInOutPin = new MicrobitPin(DigitalPin.P11);\n\n    /**\n     * Pin P12\n     */\n    //% fixedInstance whenUsed\n    export const P12: DigitalInOutPin = new MicrobitPin(DigitalPin.P12);\n\n    /**\n     * Pin P13\n     */\n    //% fixedInstance whenUsed\n    export const P13: DigitalInOutPin = new MicrobitPin(DigitalPin.P13);\n\n    /**\n     * Pin P14\n     */\n    //% fixedInstance whenUsed\n    export const P14: DigitalInOutPin = new MicrobitPin(DigitalPin.P14);\n\n    /**\n     * Pin P15\n     */\n    //% fixedInstance whenUsed\n    export const P15: DigitalInOutPin = new MicrobitPin(DigitalPin.P15);\n\n    /**\n     * Pin P16\n     */\n    //% fixedInstance whenUsed\n    export const P16: DigitalInOutPin = new MicrobitPin(DigitalPin.P16);\n\n    /**\n     * Pin P19\n     */\n    //% fixedInstance whenUsed\n    export const P19: DigitalInOutPin = new MicrobitPin(DigitalPin.P19);\n\n    /**\n     * Pin P19\n     */\n    //% fixedInstance whenUsed\n    export const P20: DigitalInOutPin = new MicrobitPin(DigitalPin.P20);\n}\n","platform.h":"#include \"nrf.h\"\n\n// helpful define to handle C++ differences in package\n#define PXT_MICROBIT_TAGGED_INT 1\n#define PXT_POWI 1\n","playable.ts":"namespace music {\n    export enum PlaybackMode {\n        //% block=\"until done\"\n        UntilDone,\n        //% block=\"in background\"\n        InBackground,\n        //% block=\"looping in background\"\n        LoopingInBackground\n    }\n\n    let looping: Playable[];\n\n    export class Playable {\n        stopped: boolean;\n        constructor() {\n\n        }\n\n        _play(playbackMode: PlaybackMode) {\n            // subclass\n        }\n\n        loop() {\n            if (!looping) {\n                looping = [];\n            }\n\n            looping.push(this);\n            this.stopped = false;\n\n            control.runInParallel(() => {\n                while (!this.stopped) {\n                    this._play(PlaybackMode.UntilDone);\n                }\n            });\n        }\n    }\n\n    export class StringArrayPlayable extends Playable {\n        constructor(private notes: string[], private tempo: number) {\n            super();\n        }\n\n        _play(playbackMode: PlaybackMode) {\n            if(this.tempo) {\n                music.setTempo(this.tempo);\n            }\n            if (playbackMode == PlaybackMode.InBackground) {\n                startMelodyInternal(this.notes, MelodyOptions.OnceInBackground);\n            }\n            else if (playbackMode == PlaybackMode.LoopingInBackground) {\n                startMelodyInternal(this.notes, MelodyOptions.ForeverInBackground);\n            }\n            else {\n                startMelodyInternal(this.notes, MelodyOptions.Once);\n                waitForMelodyEnd();\n            }\n        }\n    }\n\n    export class TonePlayable extends Playable {\n        constructor(public pitch: number, public duration: number) {\n            super();\n        }\n\n        _play(playbackMode: PlaybackMode) {\n            if (playbackMode === PlaybackMode.InBackground) {\n                control.runInParallel(() => music.playTone(this.pitch, this.duration));\n            }\n            else if (playbackMode === PlaybackMode.UntilDone) {\n                music.playTone(this.pitch, this.duration);\n            }\n            else {\n                this.loop();\n            }\n        }\n    }\n\n    /**\n     * Play a song, melody, or other sound. The music plays until finished or can play as a\n     * background task.\n     * @param toPlay the song or melody to play\n     * @param playbackMode play the song or melody until it's finished or as background task\n     */\n    //% blockId=\"music_playable_play\"\n    //% block=\"play $toPlay $playbackMode\"\n    //% toPlay.shadow=music_string_playable\n    //% group=\"Melody\"\n    //% help=\"music/play\"\n    //% blockHidden\n    export function play(toPlay: Playable, playbackMode: PlaybackMode) {\n        toPlay._play(playbackMode);\n    }\n\n    //% blockId=\"music_playable_play_default_bkg\"\n    //% block=\"play $toPlay $playbackMode\"\n    //% toPlay.shadow=music_string_playable\n    //% playbackMode.defl=music.PlaybackMode.InBackground\n    //% group=\"Melody\"\n    //% help=\"music/play\"\n    //% blockHidden\n    export function _playDefaultBackground(toPlay: Playable, playbackMode: PlaybackMode) {\n        return play(toPlay, playbackMode);\n    }\n\n    /**\n     * Play a melody from the melody editor\n     * @param melody string of up to eight notes [C D E F G A B C5] or rests [-] separated by spaces, which will be played one at a time, ex: \"E D G F B A C5 B \"\n     * @param bpm number in beats per minute dictating how long each note will play\n     */\n    //% blockId=\"music_string_playable\"\n    //% block=\"melody $melody at tempo $bpm|(bpm)\"\n    //% weight=85 blockGap=8\n    //% help=music/string-playable\n    //% group=\"Melody\"\n    //% toolboxParent=music_playable_play\n    //% toolboxParentArgument=toPlay\n    //% duplicateShadowOnDrag\n    //% melody.shadow=melody_editor\n    //% bpm.min=40 bpm.max=500\n    //% bpm.defl=120\n    export function stringPlayable(melody: string, bpm: number): Playable {\n        return new StringArrayPlayable(music.getMelodyNotes(melody), bpm);\n    }\n\n    /**\n     * Plays a tone through pin ``P0`` for the given duration.\n     * @param note pitch of the tone to play in Hertz (Hz).\n     * @param duration tone duration in milliseconds (ms)\n     */\n    //% blockId=\"music_tone_playable\"\n    //% block=\"tone $note for $duration\"\n    //% toolboxParent=music_playable_play\n    //% toolboxParentArgument=toPlay\n    //% group=\"Tone\"\n    //% weight=85\n    //% duplicateShadowOnDrag\n    //% note.shadow=device_note\n    //% duration.shadow=device_beat\n    //% parts=\"headphone\"\n    //% help=music/tone-playable\n    export function tonePlayable(note: number, duration: number): Playable {\n        return new TonePlayable(note, duration);\n    }\n\n    export function _stopPlayables() {\n        if (!looping) return;\n\n        for (const p of looping) {\n            p.stopped = true;\n        }\n        looping = undefined;\n    }\n}","poll.ts":"namespace control {\n    class PollEvent {\n        public eid: number;\n        public vid: number;\n        public start: number;\n        public timeOut: number;\n        public condition: () => boolean;\n        public once: boolean;\n        constructor(eid: number, vid: number, start: number, timeOut: number, condition: () => boolean, once: boolean) {\n            this.eid = eid;\n            this.vid = vid;\n            this.start = start;\n            this.timeOut = timeOut;\n            this.condition = condition;\n            this.once = once;\n        }\n    }\n\n    let _pollEventQueue: PollEvent[] = undefined;\n\n    function pollEvents() {\n        while (_pollEventQueue.length > 0) {\n            const now = control.millis();\n            for (let i = 0; i < _pollEventQueue.length; ++i) {\n                const ev = _pollEventQueue[i];\n                if (ev.condition() || (ev.timeOut > 0 && now - ev.start > ev.timeOut)) {\n                    control.raiseEvent(ev.eid, ev.vid);\n                    if (ev.once) {\n                        _pollEventQueue.splice(i, 1);\n                        --i;\n                    }\n                }\n            }\n            pause(50);\n        }\n        // release fiber\n        _pollEventQueue = undefined;\n    }\n\n    export function __queuePollEvent(timeOut: number, condition: () => boolean, handler: () => void) {\n        const ev = new PollEvent(\n            DAL.DEVICE_ID_NOTIFY,\n            control.allocateNotifyEvent(),\n            control.millis(),\n            timeOut,\n            condition,\n            !handler\n        );\n\n        // start polling fiber if needed\n        if (!_pollEventQueue) {\n            _pollEventQueue = [ev];\n            control.runInParallel(pollEvents);\n        }\n        else {\n            // add to the queue\n            _pollEventQueue.push(ev)\n        }\n\n        // register event\n        if (handler)\n            control.onEvent(ev.eid, ev.vid, handler);\n        else // or wait\n            control.waitForEvent(ev.eid, ev.vid);\n    }    \n}\n\n/**\n * Busy wait for a condition to be true\n * @param condition condition to test for\n * @param timeOut if positive, maximum duration to wait for in milliseconds\n */\n//% blockId=\"pxt_pause_until\"\nfunction pauseUntil(condition: () => boolean, timeOut?: number): void {\n    if (!condition || condition()) return; // optimistic path\n    if (!timeOut) timeOut = 0;\n    control.__queuePollEvent(timeOut, condition, undefined);\n}\n","pxt-core.d.ts":"/// <reference no-default-lib=\"true\"/>\n\ninterface Array<T> {\n    /**\n      * Get or set the length of an array. This number is one more than the index of the last element the array.\n      */\n    //% shim=Array_::length weight=84\n    //% blockId=\"lists_length\" block=\"length of %VALUE\" blockBuiltin=true blockNamespace=\"arrays\"\n    length: number;\n\n    /**\n      * Append a new element to an array.\n      * @param items New elements of the Array.\n      */\n    //% help=arrays/push\n    //% shim=Array_::push weight=50\n    //% blockId=\"array_push\" block=\"%list| add value %value| to end\" blockNamespace=\"arrays\"\n    //% group=\"Modify\"\n    push(item: T): void;\n\n    /**\n      * Concatenates the values with another array.\n      * @param arr The other array that is being concatenated with\n      */\n    //% helper=arrayConcat weight=40\n    concat(arr: T[]): T[];\n\n    /**\n      * Remove the last element from an array and return it.\n      */\n    //% help=arrays/pop\n    //% shim=Array_::pop weight=45\n    //% blockId=\"array_pop\" block=\"get and remove last value from %list\" blockNamespace=\"arrays\"\n    //% group=\"Read\"\n    pop(): T;\n\n    /**\n      * Reverse the elements in an array. The first array element becomes the last, and the last array element becomes the first.\n      */\n    //% help=arrays/reverse\n    //% helper=arrayReverse weight=10\n    //% blockId=\"array_reverse\" block=\"reverse %list\" blockNamespace=\"arrays\"\n    //% group=\"Operations\"\n    reverse(): void;\n\n    /**\n      * Remove the first element from an array and return it. This method changes the length of the array.\n      */\n    //% help=arrays/shift\n    //% helper=arrayShift weight=30\n    //% blockId=\"array_shift\" block=\"get and remove first value from %list\" blockNamespace=\"arrays\"\n    //% group=\"Read\"\n    shift(): T;\n\n    /**\n      * Add one element to the beginning of an array and return the new length of the array.\n      * @param element to insert at the start of the Array.\n      */\n    //% help=arrays/unshift\n    //% helper=arrayUnshift weight=25\n    //% blockId=\"array_unshift\" block=\"%list| insert %value| at beginning\" blockNamespace=\"arrays\"\n    //% group=\"Modify\"\n    //unshift(...values:T[]): number; //rest is not supported in our compiler yet.\n    unshift(value: T): number;\n\n    /**\n      * Return a section of an array.\n      * @param start The beginning of the specified portion of the array. eg: 0\n      * @param end The end of the specified portion of the array. eg: 0\n      */\n    //% help=arrays/slice\n    //% helper=arraySlice weight=41 blockNamespace=\"arrays\"\n    slice(start?: number, end?: number): T[];\n\n    /**\n      * Remove elements from an array.\n      * @param start The zero-based location in the array from which to start removing elements. eg: 0\n      * @param deleteCount The number of elements to remove. eg: 0\n      */\n    //% helper=arraySplice weight=40\n    splice(start: number, deleteCount: number): void;\n\n    /**\n      * joins all elements of an array into a string and returns this string.\n      * @param sep the string separator\n      */\n    //% helper=arrayJoin weight=40\n    join(sep?: string): string;\n\n    /**\n      * Tests whether at least one element in the array passes the test implemented by the provided function.\n      * @param callbackfn A function that accepts up to two arguments. The some method calls the callbackfn function one time for each element in the array.\n      */\n    //% helper=arraySome weight=40\n    some(callbackfn: (value: T, index: number) => boolean): boolean;\n\n    /**\n      * Tests whether all elements in the array pass the test implemented by the provided function.\n      * @param callbackfn A function that accepts up to two arguments. The every method calls the callbackfn function one time for each element in the array.\n      */\n    //% helper=arrayEvery weight=40\n    every(callbackfn: (value: T, index: number) => boolean): boolean;\n\n    /**\n      * Sort the elements of an array in place and returns the array. The sort is not necessarily stable.\n      * @param specifies a function that defines the sort order. If omitted, the array is sorted according to the prmitive type\n      */\n    //% helper=arraySort weight=40\n    sort(callbackfn?: (value1: T, value2: T) => number): T[];\n\n    /**\n      * Call a defined callback function on each element of an array, and return an array containing the results.\n      * @param callbackfn A function that accepts up to two arguments. The map method calls the callbackfn function one time for each element in the array.\n      */\n    //% helper=arrayMap weight=40\n    map<U>(callbackfn: (value: T, index: number) => U): U[];\n\n    /**\n      * Call a defined callback function on each element of an array.\n      * @param callbackfn A function that accepts up to two arguments. The forEach method calls the callbackfn function one time for each element in the array.\n      */\n    //% helper=arrayForEach weight=40\n    forEach(callbackfn: (value: T, index: number) => void): void;\n\n    /**\n      * Return the elements of an array that meet the condition specified in a callback function.\n      * @param callbackfn A function that accepts up to two arguments. The filter method calls the callbackfn function one time for each element in the array.\n      */\n    //% helper=arrayFilter weight=40\n    filter(callbackfn: (value: T, index: number) => boolean): T[];\n\n    /**\n      * Fills all the elements of an array from a start index to an end index with a static value. The end index is not included.\n      */\n    //% helper=arrayFill weight=39\n    fill(value: T, start?: number, end?: number): T[];\n\n    /**\n     * Returns the value of the first element in the array that satisfies the provided testing function. Otherwise undefined is returned.\n     * @param callbackfn\n     */\n    //% helper=arrayFind weight=40\n    find(callbackfn: (value: T, index: number) => boolean): T;\n\n    /**\n      * Call the specified callback function for all the elements in an array. The return value of the callback function is the accumulated result, and is provided as an argument in the next call to the callback function.\n      * @param callbackfn A function that accepts up to three arguments. The reduce method calls the callbackfn function one time for each element in the array.\n      * @param initialValue Initial value to start the accumulation. The first call to the callbackfn function provides this value as an argument instead of an array value.\n      */\n    //% helper=arrayReduce weight=40\n    reduce<U>(callbackfn: (previousValue: U, currentValue: T, currentIndex: number) => U, initialValue: U): U;\n\n\n    /** Remove the first occurrence of an object. Returns true if removed. */\n    //% shim=Array_::removeElement weight=48\n    removeElement(element: T): boolean;\n\n    /** Remove and return the element at a certain index. */\n    //% help=arrays/remove-at\n    //% shim=Array_::removeAt weight=47\n    //% blockId=\"array_removeat\" block=\"%list| get and remove value at %index\" blockNamespace=\"arrays\"\n    //% group=\"Read\"\n    removeAt(index: number): T;\n\n    /**\n     * Insert the value at a particular index, increases length by 1\n     * @param index the zero-based position in the list to insert the value, eg: 0\n     * @param the value to insert, eg: 0\n     */\n    //% help=arrays/insert-at\n    //% shim=Array_::insertAt weight=20\n    //% blockId=\"array_insertAt\" block=\"%list| insert at %index| value %value\" blockNamespace=\"arrays\"\n    //% group=\"Modify\"\n    insertAt(index: number, value: T): void;\n\n    /**\n      * Return the index of the first occurrence of a value in an array.\n      * @param item The value to locate in the array.\n      * @param fromIndex The array index at which to begin the search. If fromIndex is omitted, the search starts at index 0.\n      */\n    //% help=arrays/index-of\n    //% shim=Array_::indexOf weight=40\n    //% blockId=\"array_indexof\" block=\"%list| find index of %value\" blockNamespace=\"arrays\"\n    //% group=\"Operations\"\n    indexOf(item: T, fromIndex?: number): number;\n\n    /**\n     * Get the value at a particular index\n     * @param index the zero-based position in the list of the item, eg: 0\n     */\n    //% help=arrays/get\n    //% shim=Array_::getAt weight=85\n    get(index: number): T;\n\n    /**\n     * Store a value at a particular index\n     * @param index the zero-based position in the list to store the value, eg: 0\n     * @param value the value to insert, eg: 0\n     */\n    //% help=arrays/set\n    //% shim=Array_::setAt weight=84\n    set(index: number, value: T): void;\n\n    /**\n     * Return a random value from the array\n     */\n    //% help=arrays/pick-random\n    //% helper=arrayPickRandom weight=25\n    //% blockId=\"array_pickRandom\" block=\"get random value from %list\"\n    //% blockNamespace=\"arrays\"\n    //% group=\"Read\"\n    _pickRandom(): T;\n\n    [n: number]: T;\n\n    /**\n      * Add one element to the beginning of an array and return the new length of the array.\n      * @param element to insert at the start of the Array.\n      */\n    //% help=arrays/unshift\n    //% helper=arrayUnshift weight=24\n    //% blockId=\"array_unshift_statement\" block=\"%list| insert %value| at beginning\" blockNamespace=\"arrays\"\n    //% blockAliasFor=\"Array.unshift\"\n    //% group=\"Modify\"\n    _unshiftStatement(value: T): void;\n\n    /**\n      * Remove the last element from an array and return it.\n      */\n    //% help=arrays/pop\n    //% shim=Array_::pop weight=44\n    //% blockId=\"array_pop_statement\" block=\"remove last value from %list\" blockNamespace=\"arrays\"\n    //% blockAliasFor=\"Array.pop\"\n    //% group=\"Modify\"\n    _popStatement(): void;\n\n    /**\n      * Remove the first element from an array and return it. This method changes the length of the array.\n      */\n    //% help=arrays/shift\n    //% helper=arrayShift weight=29\n    //% blockId=\"array_shift_statement\" block=\"remove first value from %list\" blockNamespace=\"arrays\"\n    //% blockAliasFor=\"Array.shift\"\n    //% group=\"Modify\"\n    _shiftStatement(): void;\n\n    /** Remove the element at a certain index. */\n    //% help=arrays/remove-at-statement\n    //% shim=Array_::removeAt weight=14\n    //% blockId=\"array_removeat_statement\" block=\"%list| remove value at %index\" blockNamespace=\"arrays\"\n    //% blockAliasFor=\"Array.removeAt\"\n    //% group=\"Modify\"\n    _removeAtStatement(index: number): void;\n}\n\ndeclare interface String {\n    // This block is currently disabled in favor of the built-in Blockly \"Create text with\" block, which compiles to \"\" + \"\"\n    // Add % sign back to the block annotation to re-enable\n    /**\n     * Returns a string that contains the concatenation of two or more strings.\n     * @param other The string to append to the end of the string.\n     */\n    //% shim=String_::concat weight=49\n    //% blockId=\"string_concat\" blockNamespace=\"text\"\n    // block=\"join %list=text|%other\"\n    concat(other: string): string;\n\n    /**\n     * Return the character at the specified index.\n     * @param index The zero-based index of the desired character.\n     */\n    //% shim=String_::charAt weight=48\n    //% help=text/char-at\n    //% blockId=\"string_get\" block=\"char from %this=text|at %pos\" blockNamespace=\"text\"\n    //% this.defl=\"this\"\n    charAt(index: number): string;\n\n    /** Returns the length of a String object. */\n    //% property shim=String_::length weight=47\n    //% blockId=\"text_length\" block=\"length of %VALUE\" blockBuiltin=true blockNamespace=\"text\"\n    length: number;\n\n    /**\n     * Return the Unicode value of the character at the specified location.\n     * @param index The zero-based index of the desired character. If there is no character at the specified index, NaN is returned.\n     */\n    //% shim=String_::charCodeAt weight=46\n    //% help=text/char-code-at\n    //% blockId=\"string_charcode_at\" block=\"char code from $this=text|at $index\" blockNamespace=\"text\"\n    //% this.defl=\"this\"\n    charCodeAt(index: number): number;\n\n    /**\n     * See how the order of characters in two strings is different (in ASCII encoding).\n     * @param that String to compare to target string\n     */\n    //% shim=String_::compare\n    //% help=text/compare\n    //% blockId=\"string_compare\" block=\"compare %this=text| to %that\" blockNamespace=\"text\"\n    //% this.defl=\"this\"\n    compare(that: string): number;\n\n    /**\n     * Return a substring of the current string.\n     * @param start first character index; can be negative from counting from the end, eg:0\n     * @param length number of characters to extract, eg: 10\n     */\n    //% helper=stringSubstr\n    //% help=text/substr\n    //% blockId=string_substr_new\n    //% block=\"substring of $this|from $start||of length $length\"\n    //% this.shadow=\"text\"\n    //% this.defl=\"this\"\n    //% blockNamespace=\"text\"\n    //% expandArgumentsInToolbox\n    substr(start: number, length?: number): string;\n\n    /**\n     * Return the current string with the first occurrence of toReplace\n     * replaced with the replacer\n     * @param toReplace the substring to replace in the current string\n     * @param replacer either the string that replaces toReplace in the current string,\n     *                or a function that accepts the substring and returns the replacement string.\n     */\n    //% helper=stringReplace\n    replace(toReplace: string, replacer: string | ((sub: string) => string)): string;\n\n    /**\n     * Return the current string with each occurrence of toReplace\n     * replaced with the replacer\n     * @param toReplace the substring to replace in the current string\n     * @param replacer either the string that replaces toReplace in the current string,\n     *                or a function that accepts the substring and returns the replacement string.\n     */\n    //% helper=stringReplaceAll\n    replaceAll(toReplace: string, replacer: string | ((sub: string) => string)): string;\n\n    /**\n     * Return a substring of the current string.\n     * @param start first character index; can be negative from counting from the end, eg:0\n     * @param end one-past-last character index\n     */\n    //% helper=stringSlice\n    slice(start: number, end?: number): string;\n\n    /** Returns a value indicating if the string is empty */\n    //% helper=stringEmpty\n    //% help=text/is-empty\n    //% blockId=\"string_isempty\" blockNamespace=\"text\"\n    //% block=\"%this=text| is empty\"\n    //% this.defl=\"this\"\n    isEmpty(): boolean;\n\n    /**\n     * Returns the position of the first occurrence of a specified value in a string.\n     * @param searchValue the text to find\n     * @param start optional start index for the search\n     */\n    //% shim=String_::indexOf\n    //% help=text/index-of\n    //% blockId=\"string_indexof\" blockNamespace=\"text\"\n    //% block=\"%this=text|find index of %searchValue\"\n    //% this.defl=\"this\"\n    indexOf(searchValue: string, start?: number): number;\n\n    /**\n     * Determines whether a string contains the characters of a specified string.\n     * @param searchValue the text to find\n     * @param start optional start index for the search\n     */\n    //% shim=String_::includes\n    //% help=text/includes\n    //% blockId=\"string_includes\" blockNamespace=\"text\"\n    //% block=\"%this=text|includes %searchValue\"\n    //% this.defl=\"this\"\n    includes(searchValue: string, start?: number): boolean;\n\n    /**\n     * Splits the string according to the separators\n     * @param separator\n     * @param limit\n     */\n    //% helper=stringSplit\n    //% help=text/split\n    //% blockId=\"string_split\" blockNamespace=\"text\"\n    //% block=\"split %this=text|at %separator\"\n    //% this.defl=\"this\"\n    split(separator?: string, limit?: number): string[];\n\n    /**\n     * Return a substring of the current string with whitespace removed from both ends\n     */\n    //% helper=stringTrim\n    trim(): string;\n\n    /**\n     * Converts the string to upper case characters.\n     */\n    //% helper=stringToUpperCase\n    //% help=text/to-upper-case\n    toUpperCase(): string;\n\n    /**\n     * Converts the string to lower case characters.\n     */\n    //% helper=stringToLowerCase\n    //% help=text/to-lower-case\n    toLowerCase(): string;\n\n    /**\n     * Return a substring of the current string.\n     * @param start first character index; can be negative from counting from the end, eg:0\n     * @param length number of characters to extract, eg: 10\n     */\n    //% helper=stringSubstr\n    //% help=text/substr\n    //% blockId=\"string_substr\" block=\"substring of %this=text|from %start|of length %length\" blockNamespace=\"text\"\n    //% this.defl=\"this\"\n    //% blockAliasFor=\"String.substr\"\n    //% deprecated\n    __substr(start: number, length?: number): string;\n\n    [index: number]: string;\n}\n\n/**\n  * Convert a string to a number.\n  * @param s A string to convert into a number. eg: 123\n  */\n//% shim=String_::toNumber\n//% help=text/parse-float\n//% blockId=\"string_parsefloat\" block=\"parse to number %text\" blockNamespace=\"text\"\n//% text.defl=\"123\"\ndeclare function parseFloat(text: string): number;\n\n/**\n * Returns a pseudorandom number between min and max included.\n * If both numbers are integral, the result is integral.\n * @param min the lower inclusive bound, eg: 0\n * @param max the upper inclusive bound, eg: 10\n */\n//% blockId=\"device_random\" block=\"pick random %min|to %limit\"\n//% blockNamespace=\"Math\"\n//% help=math/randint\n//% shim=Math_::randomRange\ndeclare function randint(min: number, max: number): number;\n\ninterface Object { }\ninterface Function {\n  __assignableToFunction: Function;\n}\ninterface IArguments {\n  __assignableToIArguments: IArguments;\n}\ninterface RegExp {\n  __assignableToRegExp: RegExp;\n}\ntype TemplateStringsArray = Array<string>;\n\ntype uint8 = number;\ntype uint16 = number;\ntype uint32 = number;\ntype int8 = number;\ntype int16 = number;\ntype int32 = number;\n\n\ndeclare interface Boolean {\n    /**\n     * Returns a string representation of an object.\n     */\n    //% shim=numops::toString\n    toString(): string;\n}\n\n/**\n * Combine, split, and search text strings.\n*/\n//% blockNamespace=\"text\"\ndeclare namespace String {\n\n    /**\n     * Make a string from the given ASCII character code.\n     */\n    //% help=math/from-char-code\n    //% shim=String_::fromCharCode weight=1\n    //% blockNamespace=\"text\" blockId=\"stringFromCharCode\" block=\"text from char code %code\"\n    function fromCharCode(code: number): string;\n}\n\ndeclare interface Number {\n    /**\n     * Returns a string representation of a number.\n     */\n    //% shim=numops::toString\n    toString(): string;\n}\n\n/**\n * Add, remove, and replace items in lists.\n*/\n//% blockNamespace=\"Arrays\"\ndeclare namespace Array {\n    /**\n     * Check if a given object is an array.\n     */\n    //% shim=Array_::isArray\n    function isArray(obj: any): boolean;\n}\n\ndeclare namespace Object {\n    /**\n     * Return the field names in an object.\n     */\n    //% shim=pxtrt::keysOf\n    function keys(obj: any): string[];\n}\n\n/**\n * More complex operations with numbers.\n*/\ndeclare namespace Math {\n    /**\n     * Returns the value of a base expression taken to a specified power.\n     * @param x The base value of the expression.\n     * @param y The exponent value of the expression.\n     */\n    //% shim=Math_::pow\n    function pow(x: number, y: number): number;\n\n    /**\n     * Returns a pseudorandom number between 0 and 1.\n     */\n    //% shim=Math_::random\n    //% help=math/random\n    function random(): number;\n\n    /**\n     * Returns a pseudorandom number between min and max included.\n     * If both numbers are integral, the result is integral.\n     * @param min the lower inclusive bound, eg: 0\n     * @param max the upper inclusive bound, eg: 10\n     */\n    //% blockId=\"device_random_deprecated\" block=\"pick random %min|to %limit\"\n    //% help=math/random-range deprecated\n    //% shim=Math_::randomRange\n    function randomRange(min: number, max: number): number;\n\n    /**\n     * Returns the natural logarithm (base e) of a number.\n     * @param x A number\n     */\n    //% shim=Math_::log\n    //% help=math\n    function log(x: number): number;\n\n    /**\n     * Returns returns ``e^x``.\n     * @param x A number\n     */\n    //% shim=Math_::exp\n    //% help=math\n    function exp(x: number): number;\n\n    /**\n     * Returns the sine of a number.\n     * @param x An angle in radians\n     */\n    //% shim=Math_::sin\n    //% help=math/trigonometry\n    function sin(x: number): number;\n\n    /**\n     * Returns the cosine of a number.\n     * @param x An angle in radians\n     */\n    //% shim=Math_::cos\n    //% help=math/trigonometry\n    function cos(x: number): number;\n\n    /**\n     * Returns the tangent of a number.\n     * @param x An angle in radians\n     */\n    //% shim=Math_::tan\n    //% help=math/trigonometry\n    function tan(x: number): number;\n\n    /**\n     * Returns the arcsine (in radians) of a number\n     * @param x A number\n     */\n    //% shim=Math_::asin\n    //% help=math/trigonometry\n    function asin(x: number): number;\n\n    /**\n     * Returns the arccosine (in radians) of a number\n     * @param x A number\n     */\n    //% shim=Math_::acos\n    //% help=math/trigonometry\n    function acos(x: number): number;\n\n    /**\n     * Returns the arctangent (in radians) of a number\n     * @param x A number\n     */\n    //% shim=Math_::atan\n    //% help=math/trigonometry\n    function atan(x: number): number;\n\n    /**\n     * Returns the arctangent of the quotient of its arguments.\n     * @param y A number\n     * @param x A number\n     */\n    //% shim=Math_::atan2\n    //% help=math/trigonometry\n    function atan2(y: number, x: number): number;\n\n    /**\n     * Returns the square root of a number.\n     * @param x A numeric expression.\n     */\n    //% shim=Math_::sqrt\n    //% help=math\n    function sqrt(x: number): number;\n\n    /**\n     * Returns the smallest number greater than or equal to its numeric argument.\n     * @param x A numeric expression.\n     */\n    //% shim=Math_::ceil\n      //% help=math\n    function ceil(x: number): number;\n\n    /**\n      * Returns the greatest number less than or equal to its numeric argument.\n      * @param x A numeric expression.\n      */\n    //% shim=Math_::floor\n      //% help=math\n    function floor(x: number): number;\n\n    /**\n      * Returns the number with the decimal part truncated.\n      * @param x A numeric expression.\n      */\n    //% shim=Math_::trunc\n    //% help=math\n    function trunc(x: number): number;\n\n    /**\n      * Returns a supplied numeric expression rounded to the nearest number.\n      * @param x The value to be rounded to the nearest number.\n      */\n    //% shim=Math_::round\n    //% help=math\n    function round(x: number): number;\n\n    /**\n     * Returns the value of integer signed 32 bit multiplication of two numbers.\n     * @param x The first number\n     * @param y The second number\n     */\n    //% shim=Math_::imul\n    //% help=math\n    function imul(x: number, y: number): number;\n\n    /**\n     * Returns the value of integer signed 32 bit division of two numbers.\n     * @param x The first number\n     * @param y The second number\n     */\n    //% shim=Math_::idiv\n    //% help=math\n    function idiv(x: number, y: number): number;\n}\n\ndeclare namespace control {\n    //% shim=_control::_onCodeStart\n    export function _onCodeStart(arg: any): void;\n\n    //% shim=_control::_onCodeStop\n    export function _onCodeStop(arg: any): void;\n}","pxt-helpers.ts":"type Action = () => void;\n\n/**\n * Constant representing Not-A-Number.\n */\nconst NaN = 0 / 0\n\n/**\n * Constant representing positive infinity.\n */\nconst Infinity = 1 / 0\n\nfunction isNaN(x: number) {\n    x = +x // convert to number\n    return x !== x\n}\n\nnamespace Number {\n    /**\n     * Check if a given value is of type Number and it is a NaN.\n     */\n    export function isNaN(x: any): boolean {\n        return typeof x == \"number\" && x !== x\n    }\n}\n\n/**\n * A dictionary from string key to string values\n */\ninterface StringMap {\n    [index: string]: string;\n}\n\n/**\n  * Convert a string to an integer.\n  * @param text A string to convert into an integral number. eg: \"123\"\n  * @param radix optional A value between 2 and 36 that specifies the base of the number in text.\n  * If this argument is not supplied, strings with a prefix of '0x' are considered hexadecimal.\n  * All other strings are considered decimal.\n  */\n//% help=text/parse-int\n//% blockId=\"string_parseint\" block=\"parse to integer %text\" blockNamespace=\"text\"\n//% text.defl=\"123\"\n//% blockHidden=1\nfunction parseInt(text: string, radix?: number): number {\n    // roughly based on https://www.ecma-international.org/ecma-262/5.1/#sec-15.1.2.2\n    // with some consideration for avoiding unnecessary slices where easy\n    if (!text || (radix != null && (radix < 2 || radix > 36)))\n        return NaN;\n\n    let start = 0;\n    while (start < text.length && helpers.isWhitespace(text.charCodeAt(start)))\n        ++start;\n\n    if (start === text.length)\n        return NaN;\n\n    const numberOffset = 48; // 0\n    const numCount = 10;\n    const letterOffset = 97; // a\n    const letterCount = 26;\n    const lowerCaseMask = 0x20;\n\n    let sign = 1;\n    switch (text.charAt(start)) {\n        case \"-\":\n            sign = -1;\n            // fallthrough\n        case \"+\":\n            ++start;\n    }\n\n    if ((!radix || radix == 16)\n            && \"0\" === text[start]\n            && (\"x\" === text[start + 1] || \"X\" === text[start + 1])) {\n        radix = 16;\n        start += 2;\n    } else if (!radix) {\n        radix = 10;\n    }\n\n    let output = 0;\n    let hasDigit = false;\n    for (let i = start; i < text.length; ++i) {\n        const code = text.charCodeAt(i) | lowerCaseMask;\n        let val: number = undefined;\n\n        if (code >= numberOffset && code < numberOffset + numCount)\n            val = code - numberOffset;\n        else if (code >= letterOffset && code < letterOffset + letterCount)\n            val = numCount + code - letterOffset;\n\n        if (val == undefined || val >= radix) {\n            if (!hasDigit) {\n                return NaN;\n            }\n            break;\n        }\n        hasDigit = true;\n        output = output * radix + val;\n    }\n\n    return sign * output;\n}\n\nnamespace helpers {\n    export function arrayFill<T>(O: T[], value: T, start?: number, end?: number) {\n        // https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/fill\n        // Steps 3-5.\n        const len = O.length >>> 0;\n\n        // Steps 6-7.\n        const relativeStart = start === undefined ? 0 : start >> 0;\n\n        // Step 8.\n        let k = relativeStart < 0 ?\n            Math.max(len + relativeStart, 0) :\n            Math.min(relativeStart, len);\n\n        // Steps 9-10.\n        const relativeEnd = end === undefined ? len : end >> 0;\n\n        // Step 11.\n        const final = relativeEnd < 0 ?\n            Math.max(len + relativeEnd, 0) :\n            Math.min(relativeEnd, len);\n\n        // Step 12.\n        while (k < final) {\n            O[k] = value;\n            k++;\n        }\n\n        // Step 13.\n        return O;\n    }\n\n    export function arraySplice<T>(arr: T[], start: number, len: number) {\n        if (start < 0) {\n            return;\n        }\n        for (let i = 0; i < len; ++i) {\n            arr.removeAt(start)\n        }\n    }\n\n    export function arrayReverse<T>(arr: T[]): void {\n        let len = arr.length;\n        for (let i = 0; i < len / 2; i++) {\n            swap(arr, i, len - i - 1);\n        }\n    }\n\n    export function arrayShift<T>(arr: T[]): T {\n        return arr.removeAt(0);\n    }\n\n    export function arrayJoin<T>(arr: T[], sep?: string): string {\n        if (sep === undefined || sep === null) {\n            sep = \",\";\n        }\n\n        let r = \"\";\n        let len = arr.length // caching this seems to match V8\n        for (let i = 0; i < len; ++i) {\n            if (i > 0 && sep)\n                r += sep;\n            r += (arr[i] === undefined || arr[i] === null) ? \"\" : arr[i];\n        }\n        return r;\n    }\n\n    /*TODO: Enable this multiple value unshift, after rest is enabled in our compiler.\n        export function arrayUnshift<T>(arr: T[], ...values: T[]) : number {\n            for(let i = values.length; i > 0; --i) {\n                arr.insertAt(0, values[i - 1]);\n            }\n            return arr.length;\n        }\n    */\n    export function arrayUnshift<T>(arr: T[], value: T): number {\n        arr.insertAt(0, value);\n        return arr.length;\n    }\n\n    function swap<T>(arr: T[], i: number, j: number): void {\n        let temp: T = arr[i];\n        arr[i] = arr[j];\n        arr[j] = temp;\n    }\n\n    function sortHelper<T>(arr: T[], callbackfn?: (value1: T, value2: T) => number): T[] {\n        if (arr.length <= 0 || !callbackfn) {\n            return arr;\n        }\n        let len = arr.length;\n        // simple selection sort.\n        for (let i = 0; i < len - 1; ++i) {\n            for (let j = i + 1; j < len; ++j) {\n                if (callbackfn(arr[i], arr[j]) > 0) {\n                    swap(arr, i, j);\n                }\n            }\n        }\n        return arr;\n    }\n\n    export function arraySort<T>(arr: T[], callbackfn?: (value1: T, value2: T) => number): T[] {\n        if (!callbackfn && arr.length > 1) {\n            callbackfn = (a, b) => {\n                // default is sort as if the element were a string, with null < undefined\n                const aIsUndef = a === undefined;\n                const bIsUndef = b === undefined;\n                if (aIsUndef && bIsUndef) return 0;\n                else if (aIsUndef) return 1;\n                else if (bIsUndef) return -1;\n\n                const aIsNull = a === null;\n                const bIsNull = b === null;\n                if (aIsNull && bIsNull) return 0;\n                else if (aIsNull) return 1;\n                else if (bIsNull) return -1;\n\n                return (a + \"\").compare(b + \"\");\n            }\n        }\n        return sortHelper(arr, callbackfn);\n    }\n\n    export function arrayMap<T, U>(arr: T[], callbackfn: (value: T, index: number) => U): U[] {\n        let res: U[] = []\n        let len = arr.length // caching this seems to match V8\n        for (let i = 0; i < len; ++i) {\n            res.push(callbackfn(arr[i], i))\n        }\n        return res\n    }\n\n    export function arraySome<T>(arr: T[], callbackfn: (value: T, index: number) => boolean): boolean {\n        let len = arr.length // caching this seems to match V8\n        for (let i = 0; i < len; ++i)\n            if (callbackfn(arr[i], i))\n                return true;\n        return false;\n    }\n\n    export function arrayEvery<T>(arr: T[], callbackfn: (value: T, index: number) => boolean): boolean {\n        let len = arr.length // caching this seems to match V8\n        for (let i = 0; i < len; ++i)\n            if (!callbackfn(arr[i], i))\n                return false;\n        return true;\n    }\n\n    export function arrayForEach<T>(arr: T[], callbackfn: (value: T, index: number) => void): void {\n        let len = arr.length // caching this seems to match V8\n        for (let i = 0; i < len; ++i) {\n            callbackfn(arr[i], i);\n        }\n    }\n\n    export function arrayFilter<T>(arr: T[], callbackfn: (value: T, index: number) => boolean): T[] {\n        let res: T[] = []\n        let len = arr.length\n        for (let i = 0; i < len; ++i) {\n            let v = arr[i] // need to cache\n            if (callbackfn(v, i)) res.push(v)\n        }\n        return res\n    }\n\n    export function arrayFind<T>(arr: T[], callbackfn: (value: T, index: number) => boolean): T {\n        let len = arr.length\n        for (let i = 0; i < len; ++i) {\n            let v = arr[i] // need to cache\n            if (callbackfn(v, i)) return v;\n        }\n        return undefined;\n    }\n\n    export function arrayReduce<T, U>(arr: T[], callbackfn: (previousValue: U, currentValue: T, currentIndex: number) => U, initialValue: U): U {\n        let len = arr.length\n        for (let i = 0; i < len; ++i) {\n            initialValue = callbackfn(initialValue, arr[i], i)\n        }\n        return initialValue\n    }\n\n    export function arrayConcat<T>(arr: T[], otherArr: T[]): T[] {\n        let out: T[] = [];\n        for (let value of arr) {\n            out.push(value);\n        }\n        for (let value of otherArr) {\n            out.push(value);\n        }\n        return out;\n    }\n\n    export function arrayPickRandom<T>(arr: T[]): T {\n        return arr[Math.randomRange(0, arr.length - 1)];\n    }\n\n    export function arraySlice<T>(arr: T[], start?: number, end?: number): T[] {\n        // https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/slice\n        const res: T[] = [];\n        const len = arr.length;\n\n        if (start === undefined)\n            start = 0;\n        else if (start < 0)\n            start = Math.max(len + start, 0);\n\n        if (start > len)\n            return res;\n\n        if (end === undefined)\n            end = len;\n        else if (end < 0)\n            end = len + end;\n\n        if (end > len)\n            end = len;\n\n        for (let i = start; i < end; ++i) {\n            res.push(arr[i]);\n        }\n        return res;\n    }\n\n    export function stringReplace(s: string, toReplace: string, replacer: string | ((sub: string) => string)) {\n        toReplace = toReplace + \"\";\n        const ind = s.indexOf(toReplace);\n        if (ind == -1)\n            return s;\n\n        const begin = s.slice(0, ind);\n        const end = s.slice(ind + toReplace.length);\n\n        if (typeof replacer == \"string\" || !replacer) {\n            return begin + replacer + end;\n        } else {\n            return begin + replacer(toReplace) + end;\n        }\n    }\n\n    export function stringReplaceAll(s: string, toReplace: string, replacer: string | ((sub: string) => string)) {\n        toReplace = toReplace + \"\";\n        const split = s.split(toReplace);\n        const empty = toReplace.isEmpty();\n\n        let output = (empty ? applyReplace(toReplace, replacer) : \"\");\n\n        if (split.length) {\n            output += split[0];\n        }\n\n        for (let i = 1; i < split.length; ++i) {\n            output += applyReplace(toReplace, replacer) + split[i];\n        }\n\n        if (!s.isEmpty() && empty) {\n            output += applyReplace(toReplace, replacer);\n        }\n\n        return output;\n\n        function applyReplace(r: string, replacer: string | ((sub: string) => string)): string {\n            if (typeof replacer == \"string\" || !replacer) {\n                return replacer as string;\n            } else {\n                return replacer(r);\n            }\n        }\n    }\n\n    //% shim=String_::substr\n    declare function stringSubstrHelper(s: string, start: number, length?: number): string;\n\n    export function stringSubstr(s: string, start: number, length?: number): string {\n        length = length === undefined ? s.length : length || 0;\n        return stringSubstrHelper(s, start, length);\n    }\n\n    export function stringSlice(s: string, start: number, end?: number): string {\n        const len = s.length;\n\n        if (start < 0) {\n            start = Math.max(len + start, 0);\n        }\n\n        if (end === undefined) {\n            end = len;\n        } else if (end === null) {\n            end = 0;\n        }\n\n        if (end < 0) {\n            end = len + end;\n        }\n\n        return stringSubstrHelper(s, start, end - start);\n    }\n\n    // also note this doesn't handle unicode, but neither does JS (there's toLocaleUpperCase())\n    export function stringToUpperCase(s: string): string {\n        let r = \"\"\n        let prev = 0\n        for (let i = 0; i < s.length; i++) {\n            const c = s.charCodeAt(i)\n            if (97 <= c && c <= 122) {\n                r += s.slice(prev, i) + String.fromCharCode(c - 32)\n                prev = i + 1\n            }\n        }\n        r += s.slice(prev)\n        return r\n    }\n\n    // also note this doesn't handle unicode, but neither does JS (there's toLocaleLowerCase())\n    export function stringToLowerCase(s: string): string {\n        let r = \"\"\n        let prev = 0\n        for (let i = 0; i < s.length; i++) {\n            const c = s.charCodeAt(i)\n            if (65 <= c && c <= 90) {\n                r += s.slice(prev, i) + String.fromCharCode(c + 32)\n                prev = i + 1\n            }\n        }\n        r += s.slice(prev)\n        return r\n    }\n\n    export function stringSplit(S: string, separator?: string, limit?: number): string[] {\n        // https://www.ecma-international.org/ecma-262/6.0/#sec-string.prototype.split\n        const A: string[] = [];\n        let lim = 0;\n        if (limit === undefined)\n            lim = (1 << 29) - 1; // spec says 1 << 53, leaving it at 29 for constant folding\n        else if (limit < 0)\n            lim = 0;\n        else\n            lim = limit | 0;\n        const s = S.length;\n        let p = 0;\n        const R = separator;\n        if (lim == 0)\n            return A;\n        if (separator === undefined) {\n            A[0] = S;\n            return A;\n        }\n        if (s == 0) {\n            let z = splitMatch(S, 0, R);\n            if (z > -1) return A;\n            A[0] = S;\n            return A;\n        }\n        let T: string;\n        let q = p;\n        while (q != s) {\n            let e = splitMatch(S, q, R);\n            if (e < 0) q++;\n            else {\n                if (e == p) q++;\n                else {\n                    T = stringSlice(S, p, q);\n                    A.push(T);\n                    if (A.length == lim) return A;\n                    p = e;\n                    q = p;\n                }\n            }\n        }\n        T = stringSlice(S, p, q);\n        A.push(T);\n        return A;\n    }\n\n    function splitMatch(S: string, q: number, R: string): number {\n        const r = R.length;\n        const s = S.length;\n        if (q + r > s) return -1;\n        for (let i = 0; i < r; ++i) {\n            if (S[q + i] != R[i])\n                return -1;\n        }\n        return q + r;\n    }\n\n    export function stringTrim(s: string): string {\n        let start = 0;\n        let end = s.length - 1;\n\n        while (start <= end && isWhitespace(s.charCodeAt(start)))\n            ++start;\n\n        while (end > start && isWhitespace(s.charCodeAt(end)))\n            --end;\n        return s.slice(start, end + 1);\n    }\n\n    export function isWhitespace(c: number): boolean {\n        // https://www.ecma-international.org/ecma-262/6.0/#sec-white-space\n        switch (c) {\n            case 0x0009:  // character tab\n            case 0x000B:  // line tab\n            case 0x000C:  // form feed\n            case 0x0020:  // space\n            case 0x00A0:  // no-break space\n            case 0xFEFF:  // zero width no break space\n            case 0x000A:  // line feed\n            case 0x000D:  // carriage return\n            case 0x2028:  // line separator\n            case 0x2029:  // paragraph separator\n                return true;\n            default:\n                return false;\n        }\n    }\n\n    export function stringEmpty(S: string): boolean {\n        return !S;\n    }\n}\n\nnamespace Math {\n    export function clamp(min: number, max: number, value: number): number {\n        return Math.min(max, Math.max(min, value));\n    }\n\n    /**\n      * Returns the absolute value of a number (the value without regard to whether it is positive or negative).\n      * For example, the absolute value of -5 is the same as the absolute value of 5.\n      * @param x A numeric expression for which the absolute value is needed.\n      */\n    //% blockId=math_op3\n    //% help=math/abs\n    export function abs(x: number): number {\n        return x < 0 ? -x : x;\n    }\n\n    /**\n      * Returns the sign of the x, indicating whether x is positive, negative or zero.\n      * @param x The numeric expression to test\n      */\n    export function sign(x: number): number {\n        if (x == 0) return 0;\n        if (x > 0) return 1;\n        return -1;\n    }\n\n    /**\n      * Returns the larger of two supplied numeric expressions.\n      */\n    //% blockId=math_op2\n    //% help=math/max\n    export function max(a: number, b: number): number {\n        if (a >= b) return a;\n        return b;\n    }\n\n    /**\n      * Returns the smaller of two supplied numeric expressions.\n      */\n    //% blockId=math_op2\n    //% help=math/min\n    export function min(a: number, b: number): number {\n        if (a <= b) return a;\n        return b;\n    }\n\n    /**\n     * Rounds ``x`` to a number with the given number of ``digits``\n     * @param x the number to round\n     * @param digits the number of resulting digits\n     */\n    //%\n    export function roundWithPrecision(x: number, digits: number): number {\n        digits = digits | 0;\n        // invalid digits input\n        if (digits <= 0) return Math.round(x);\n        if (x == 0) return 0;\n        let r = 0;\n        do {\n            const d = Math.pow(10, digits);\n            r = Math.round(x * d) / d;\n            digits++;\n        } while (r == 0 && digits < 21);\n        return r;\n    }\n}\n\n\n//% blockHidden=1\nnamespace __internal {\n    /**\n     * A shim to render a boolean as a down/up toggle\n     */\n    //% shim=TD_ID blockHidden=1\n    //% blockId=toggleDownUp block=\"%down\"\n    //% down.fieldEditor=toggledownup\n    //% down.fieldOptions.decompileLiterals=true\n    export function __downUp(down: boolean): boolean {\n        return down;\n    }\n\n    /**\n     * A shim to render a boolean as a up/down toggle\n     */\n    //% shim=TD_ID blockHidden=1\n    //% blockId=toggleUpDown block=\"%up\"\n    //% up.fieldEditor=toggleupdown\n    //% up.fieldOptions.decompileLiterals=true\n    export function __upDown(up: boolean): boolean {\n        return up;\n    }\n\n    /**\n     * A shim to render a boolean as a high/low toggle\n     */\n    //% shim=TD_ID blockHidden=1\n    //% blockId=toggleHighLow block=\"%high\"\n    //% high.fieldEditor=togglehighlow\n    //% high.fieldOptions.decompileLiterals=true\n    export function __highLow(high: boolean): boolean {\n        return high;\n    }\n\n    /**\n     * A shim to render a boolean as a on/off toggle\n     */\n    //% shim=TD_ID blockHidden=1\n    //% blockId=toggleOnOff block=\"%on\"\n    //% on.fieldEditor=toggleonoff\n    //% on.fieldOptions.decompileLiterals=true\n    export function __onOff(on: boolean): boolean {\n        return on;\n    }\n\n    /**\n     * A shim to render a boolean as a yes/no toggle\n     */\n    //% shim=TD_ID blockHidden=1\n    //% blockId=toggleYesNo block=\"%yes\"\n    //% yes.fieldEditor=toggleyesno\n    //% yes.fieldOptions.decompileLiterals=true\n    export function __yesNo(yes: boolean): boolean {\n        return yes;\n    }\n\n    /**\n     * A shim to render a boolean as a win/lose toggle\n     */\n    //% shim=TD_ID blockHidden=1\n    //% blockId=toggleWinLose block=\"%win\"\n    //% win.fieldEditor=togglewinlose\n    //% win.fieldOptions.decompileLiterals=true\n    export function __winLose(win: boolean): boolean {\n        return win;\n    }\n\n    /**\n     * Get the color wheel field editor\n     * @param color color\n     */\n    //% blockId=colorNumberPicker block=\"%value\"\n    //% blockHidden=true\n    //% shim=TD_ID colorSecondary=\"#FFFFFF\"\n    //% value.fieldEditor=\"colornumber\" value.fieldOptions.decompileLiterals=true\n    //% value.defl='0xff0000'\n    //% value.fieldOptions.colours='[\"#ff0000\",\"#ff8000\",\"#ffff00\",\"#ff9da5\",\"#00ff00\",\"#b09eff\",\"#00ffff\",\"#007fff\",\"#65471f\",\"#0000ff\",\"#7f00ff\",\"#ff0080\",\"#ff00ff\",\"#ffffff\",\"#999999\",\"#000000\"]'\n    //% value.fieldOptions.columns=4 value.fieldOptions.className='rgbColorPicker'\n    export function __colorNumberPicker(value: number) {\n        return value;\n    }\n\n    /**\n     * Get the color wheel field editor\n     * @param value value between 0 to 255 to get a color value, eg: 10\n     */\n    //% blockId=colorWheelPicker block=\"%value\"\n    //% blockHidden=true\n    //% shim=TD_ID colorSecondary=\"#FFFFFF\"\n    //% value.fieldEditor=\"colorwheel\" value.fieldOptions.decompileLiterals=true\n    //% value.fieldOptions.sliderWidth='200'\n    //% value.fieldOptions.min=0 value.fieldOptions.max=255\n    export function __colorWheelPicker(value: number) {\n        return value;\n    }\n\n    /**\n    * Get the color wheel field editor using HSV values\n    * @param value value between 0 to 255 to get a color value, eg: 10\n    */\n    //% blockId=colorWheelHsvPicker block=\"%value\"\n    //% blockHidden=true\n    //% shim=TD_ID colorSecondary=\"#FFFFFF\"\n    //% value.fieldEditor=\"colorwheel\" value.fieldOptions.decompileLiterals=true\n    //% value.fieldOptions.sliderWidth='200'\n    //% value.fieldOptions.min=0 value.fieldOptions.max=255\n    //% value.fieldOptions.channel=hsvfast\n    export function __colorWheelHsvPicker(value: number) {\n        return value;\n    }\n\n    /**\n     * A speed picker\n     * @param speed the speed, eg: 50\n     */\n    //% blockId=speedPicker block=\"%speed\" shim=TD_ID\n    //% speed.fieldEditor=\"speed\" colorSecondary=\"#FFFFFF\"\n    //% weight=0 blockHidden=1 speed.fieldOptions.decompileLiterals=1\n    export function __speedPicker(speed: number): number {\n        return speed;\n    }\n\n    /**\n     * A turn ratio picker\n     * @param turnratio the turn ratio, eg: 0\n     */\n    //% blockId=turnRatioPicker block=\"%turnratio\" shim=TD_ID\n    //% turnratio.fieldEditor=\"turnratio\" colorSecondary=\"#FFFFFF\"\n    //% weight=0 blockHidden=1 turnRatio.fieldOptions.decompileLiterals=1\n    export function __turnRatioPicker(turnratio: number): number {\n        return turnratio;\n    }\n\n    /**\n     * A field editor that displays a protractor\n     */\n    //% blockId=protractorPicker block=\"%angle\"\n    //% shim=TD_ID\n    //% angle.fieldEditor=protractor\n    //% angle.fieldOptions.decompileLiterals=1\n    //% colorSecondary=\"#FFFFFF\"\n    //% blockHidden=1\n    export function __protractor(angle: number) {\n        return angle;\n    }\n\n    /**\n      * Get the time field editor\n      * @param ms time duration in milliseconds, eg: 500, 1000\n      */\n    //% blockId=timePicker block=\"%ms\"\n    //% blockHidden=true shim=TD_ID\n    //% colorSecondary=\"#FFFFFF\"\n    //% ms.fieldEditor=\"numberdropdown\" ms.fieldOptions.decompileLiterals=true\n    //% ms.fieldOptions.data='[[\"100 ms\", 100], [\"200 ms\", 200], [\"500 ms\", 500], [\"1 second\", 1000], [\"2 seconds\", 2000], [\"5 seconds\", 5000]]'\n    export function __timePicker(ms: number): number {\n        return ms;\n    }\n}\n","pxt-python-helpers.ts":"namespace _py {\n    export const ATTRIBUTE_ERROR: string = \"AttributeError\";\n    export const INDEX_ERROR: string = \"IndexError\";\n    export const VALUE_ERROR: string = \"ValueError\";\n    export const TYPE_ERROR: string = \"TypeError\";\n\n    export function py_string_capitalize(str: string): string {\n        nullCheck(str);\n        return str;\n    }\n\n    export function py_string_casefold(str: string): string {\n        nullCheck(str);\n        return str;\n    }\n\n    export function py_string_center(str: string, width: number, fillChar?: string): string {\n        nullCheck(str);\n        return str;\n    }\n\n    export function py_string_count(str: string, sub: string, start?: number, end?: number): number {\n        nullCheck(str);\n        return 0;\n    }\n\n    export function py_string_endswith(str: string, suffix: string, start?: number, end?: number): boolean {\n        nullCheck(str);\n        return false;\n    }\n\n    export function py_string_find(str: string, sub: string, start?: number, end?: number): number {\n        nullCheck(str);\n        return 0;\n    }\n\n    export function py_string_index(str: string, sub: string, start?: number, end?: number): number {\n        nullCheck(str);\n        return 0;\n    }\n\n    export function py_string_isalnum(str: string): boolean {\n        nullCheck(str);\n        return false;\n    }\n\n    export function py_string_isalpha(str: string): boolean {\n        nullCheck(str);\n        return false;\n    }\n\n    export function py_string_isascii(str: string): boolean {\n        nullCheck(str);\n        return false;\n    }\n\n    export function py_string_isdigit(str: string): boolean {\n        nullCheck(str);\n        return false;\n    }\n\n    export function py_string_isnumeric(str: string): boolean {\n        nullCheck(str);\n        return false;\n    }\n\n    export function py_string_isspace(str: string): boolean {\n        nullCheck(str);\n        return false;\n    }\n\n    export function py_string_isdecimal(str: string): boolean {\n        nullCheck(str);\n        return false;\n    }\n\n    export function py_string_isidentifier(str: string): boolean {\n        nullCheck(str);\n        return false;\n    }\n\n    export function py_string_islower(str: string): boolean {\n        nullCheck(str);\n        return false;\n    }\n\n    export function py_string_isprintable(str: string): boolean {\n        nullCheck(str);\n        return false;\n    }\n\n    export function py_string_istitle(str: string): boolean {\n        nullCheck(str);\n        return false;\n    }\n\n    export function py_string_isupper(str: string): boolean {\n        nullCheck(str);\n        return false;\n    }\n\n    export function py_string_join(str: string, iterable: any[]): string {\n        nullCheck(str);\n        return str;\n    }\n\n    export function py_string_ljust(str: string, width: number, fillChar?: string): string {\n        nullCheck(str);\n        return str;\n    }\n\n    export function py_string_lower(str: string): string {\n        nullCheck(str);\n        return str;\n    }\n\n    export function py_string_rfind(str: string, sub: string, start?: number, end?: number): number {\n        nullCheck(str);\n        return 0;\n    }\n\n    export function py_string_rindex(str: string, sub: string, start?: number, end?: number): number {\n        nullCheck(str);\n        return 0;\n    }\n\n    export function py_string_rjust(str: string, width: number, fillChar?: string): string {\n        nullCheck(str);\n        return str;\n    }\n\n    export function py_string_rsplit(str: string, sep?: string, maxsplit?: number): string[] {\n        nullCheck(str);\n\n        if (sep === \"\") {\n            throw VALUE_ERROR;\n        }\n\n        if (maxsplit === 0) return [str]\n        if (!maxsplit || maxsplit < 0) maxsplit = str.length;\n\n        const out: string[] = [];\n\n        let currentChar: string;\n        let splitEnd: number;\n        let previousSplit = str.length;\n\n        if (!sep) {\n            for (let i = str.length - 1; i >= 0; i--) {\n                currentChar = str.charAt(i);\n                if (isWhitespace(currentChar)) {\n                    if (splitEnd === undefined) splitEnd = i;\n                }\n                else if (splitEnd !== undefined) {\n                    if (previousSplit !== splitEnd + 1) out.push(str.substr(splitEnd + 1, previousSplit - (splitEnd + 1)));\n                    previousSplit = i + 1;\n                    splitEnd = undefined;\n\n                }\n\n                if (out.length === maxsplit) break;\n            }\n\n            if (out.length < maxsplit + 1) {\n                if (splitEnd !== undefined) {\n                    if (previousSplit !== splitEnd + 1)\n                        out.push(str.substr(splitEnd + 1, previousSplit - (splitEnd + 1)));\n                }\n                else {\n                    out.push(str.substr(0, previousSplit))\n                }\n            }\n        }\n        else {\n            let separatorIndex = 0;\n            for (let i = str.length; i >= 0; i--) {\n                currentChar = str.charAt(i);\n                if (currentChar === sep.charAt(sep.length - separatorIndex - 1)) {\n                    separatorIndex++;\n                    if (splitEnd === undefined) splitEnd = i;\n                }\n                else {\n                    separatorIndex = 0;\n                    splitEnd = undefined;\n                }\n\n                if (separatorIndex === sep.length) {\n                    out.push(str.substr(splitEnd + 1, previousSplit - (splitEnd + 1)));\n                    previousSplit = i;\n                    separatorIndex = 0;\n                    splitEnd = undefined;\n                }\n\n                if (out.length === maxsplit) break;\n            }\n\n            if (out.length < maxsplit + 1) {\n                out.push(str.substr(0, previousSplit))\n            }\n        }\n\n        out.reverse();\n        return out;\n    }\n\n    export function py_string_split(str: string, sep?: string, maxsplit?: number): string[] {\n        nullCheck(str);\n\n        if (sep === \"\") {\n            throw VALUE_ERROR;\n        }\n\n        if (maxsplit === 0) return [str]\n        if (!maxsplit || maxsplit < 0) maxsplit = str.length;\n\n        const out: string[] = [];\n\n        let currentChar: string;\n        let splitStart: number;\n        let previousSplit = 0;\n\n        if (!sep) {\n            for (let i = 0; i < str.length; i++) {\n                currentChar = str.charAt(i);\n                if (isWhitespace(currentChar)) {\n                    if (splitStart === undefined) splitStart = i;\n                }\n                else if (splitStart !== undefined) {\n                    if (previousSplit !== splitStart) out.push(str.substr(previousSplit, splitStart - previousSplit));\n                    previousSplit = i;\n                    splitStart = undefined;\n\n                }\n\n                if (out.length === maxsplit) break;\n            }\n\n            if (out.length < maxsplit + 1) {\n                if (splitStart !== undefined) {\n                    if (previousSplit !== splitStart)\n                        out.push(str.substr(previousSplit, splitStart - previousSplit));\n                }\n                else {\n                    out.push(str.substr(previousSplit))\n                }\n            }\n        }\n        else {\n            let separatorIndex = 0;\n            for (let i = 0; i < str.length; i++) {\n                currentChar = str.charAt(i);\n                if (currentChar === sep.charAt(separatorIndex)) {\n                    separatorIndex++;\n                    if (splitStart === undefined) splitStart = i;\n                }\n                else {\n                    separatorIndex = 0;\n                    splitStart = undefined;\n                }\n\n                if (separatorIndex === sep.length) {\n                    out.push(str.substr(previousSplit, splitStart - previousSplit));\n                    previousSplit = i + 1;\n                    separatorIndex = 0;\n                    splitStart = undefined;\n                }\n\n                if (out.length === maxsplit) break;\n            }\n\n            if (out.length < maxsplit + 1) {\n                out.push(str.substr(previousSplit))\n            }\n        }\n\n        return out;\n    }\n\n\n    function isWhitespace(char: string) {\n        // TODO Figure out everything python considers whitespace.\n        // the \\s character class in JS regexes also includes these: \\u00a0\\u1680\\u2000-\\u200a\\u2028\\u2029\\u202f\\u205f\\u3000\\ufeff\n        return char === \" \" || char === \"\\t\" || char === \"\\n\" || char === \"\\v\" || char === \"\\r\" || char === \"\\f\";\n    }\n\n    export function py_string_splitlines(str: string, keepends?: boolean): string[] {\n        nullCheck(str);\n        return [];\n    }\n\n    export function py_string_startswith(str: string, prefix: string, start?: number, end?: number): boolean {\n        nullCheck(str);\n        return false;\n    }\n\n    export function py_string_rstrip(str: string, chars?: string): string {\n        nullCheck(str);\n\n        for (let i = str.length - 1; i >= 0; i--) {\n            if (chars != undefined) {\n                if (chars.indexOf(str.charAt(i)) === -1) {\n                    return str.substr(0, i + 1);\n                }\n            }\n            else if (!isWhitespace(str.charAt(i))) {\n                return str.substr(0, i + 1);\n            }\n        }\n\n        return \"\";\n    }\n\n    export function py_string_lstrip(str: string, chars?: string): string {\n        nullCheck(str);\n\n        for (let i = 0; i < str.length; i++) {\n            if (chars != undefined) {\n                if (chars.indexOf(str.charAt(i)) === -1) {\n                    return str.substr(i);\n                }\n            }\n            else if (!isWhitespace(str.charAt(i))) {\n                return str.substr(i);\n            }\n        }\n\n        return \"\";\n    }\n\n    export function py_string_strip(str: string, chars?: string): string {\n        return py_string_rstrip(py_string_lstrip(str, chars), chars);\n    }\n\n    export function py_string_swapcase(str: string): string {\n        nullCheck(str);\n        return str;\n    }\n\n    export function py_string_title(str: string): string {\n        nullCheck(str);\n        return str;\n    }\n\n    export function py_string_upper(str: string): string {\n        nullCheck(str);\n        return str;\n    }\n\n    export function py_string_zfill(str: string, width: number): string {\n        nullCheck(str);\n        return str;\n    }\n\n    export function py_array_pop(arr: any[], index?: number): any {\n        nullCheck(arr);\n\n        if (arr.length === 0) {\n            throw INDEX_ERROR;\n        }\n\n        if (index == undefined) {\n            return arr.pop();\n        }\n        else if (index >= 0 && index < arr.length) {\n            return arr.removeAt(index | 0);\n        }\n\n        throw INDEX_ERROR;\n    }\n\n    export function py_array_clear(arr: any[]): void {\n        nullCheck(arr);\n\n        arr.length = 0;\n    }\n\n    export function py_array_index(arr: any[], value: any, start?: number, end?: number): number {\n        nullCheck(arr);\n\n        start = fixIndex(arr, start);\n        end = fixIndex(arr, end);\n\n        if (start == null) {\n            start = 0;\n        }\n\n        if (end == null) {\n            // end is exclusive\n            end = arr.length;\n        }\n\n        for (let i = start; i < end; i++) {\n            if (arr[i] === value) {\n                return i;\n            }\n        }\n\n        throw VALUE_ERROR;\n    }\n\n    export function py_array_count(arr: any[], value: any): number {\n        nullCheck(arr);\n\n        let count = 0;\n\n        for (let i = 0; i < arr.length; i++) {\n            if (arr[i] === value) count++;\n        }\n\n        return count;\n    }\n\n    function nullCheck(arg: any) {\n        if (arg == null) {\n            throw ATTRIBUTE_ERROR;\n        }\n    }\n\n    function fixIndex(arr: any[], index: number) {\n        if (index != null && arr.length) {\n            index = index | 0;\n            while (index < 0) index += arr.length;\n        }\n        return index;\n    }\n\n    /**\n     * Returns a sequence of numbers up to but not including the limit\n     * @param first The value to end the sequence before. This value will not show up in the result.\n     *      If more than one argument is passed, this argument is instead used for the first value in the range\n     * @param stop  The value to end the sequence before. This value will not show up in the result\n     * @param step  The value to increase or decrease by for each step in the range. Must be a nonzero integer\n     */\n    export function range(first: number, stop?: number, step?: number) {\n        if (step === undefined) step = 1\n        // step must be a nonzero integer (can be negative)\n        if (step === 0 || (step | 0) !== step) {\n            throw VALUE_ERROR;\n        }\n\n        // If only one argument is given, then start is actually stop\n        if (stop === undefined) {\n            stop = first;\n            first = 0;\n        }\n\n        const res: number[] = [];\n        if (step > 0 && first >= stop || step < 0 && first <= stop) return res;\n\n        let index = first;\n\n        while (step < 0 ? index > stop : index < stop) {\n            res.push(index);\n            index += step\n        }\n\n        return res;\n    }\n\n    function sliceRange(valueLength: number, start?: number, stop?: number, step?: number) {\n        if (step == null) step = 1\n\n        // step must be a nonzero integer (can be negative)\n        if (step === 0 || (step | 0) !== step) {\n            throw _py.VALUE_ERROR;\n        }\n\n        if (step < 0) {\n            if (start == null) {\n                start = valueLength - 1;\n            }\n            if (stop == null) {\n                stop = -1;\n            }\n        }\n        else {\n            if (start == null) {\n                start = 0;\n            }\n            if (stop == null) {\n                stop = valueLength;\n            }\n        }\n\n        return range(start, stop, step)\n    }\n\n    /**\n     * Returns a section of an array according to python's extended slice syntax\n     */\n    export function slice<U>(value: U[], start?: number, stop?: number, step?: number): U[] {\n        if (value == null) {\n            throw TYPE_ERROR;\n        }\n        return sliceRange(value.length, start, stop, step).map(index => value[index]);\n    }\n\n    /**\n     * Returns a section of a string according to python's extended slice syntax\n     */\n    export function stringSlice(value: string, start?: number, stop?: number, step?: number): string {\n        if (value == null) {\n            throw TYPE_ERROR;\n        }\n        return sliceRange(value.length, start, stop, step).map(index => value.charAt(index)).join(\"\");\n    }\n}","pxt-python.d.ts":"/// <reference no-default-lib=\"true\"/>\n\ndeclare namespace _py {\n    interface Array {\n        //% py2tsOverride=\"push($0)\"\n        append(value: any): void;\n\n        //% py2tsOverride=\"concat($0)\"\n        extend(other: Array): void;\n\n        //% py2tsOverride=\"insertAt($0, $1)\"\n        insert(index: number, value: any): void;\n\n        //% py2tsOverride=\"removeElement($0)\"\n        remove(value: any): void;\n\n        //% py2tsOverride=\"sort($0?)\"\n        sort(sorter?: (a: any, b: any) => number): void;\n\n        //% py2tsOverride=\"reverse()\"\n        reverse(): void;\n\n        //% py2tsOverride=\"slice()\"\n        copy(): void;\n\n        //% pyHelper=\"py_array_pop\"\n        pop(index?: number): any;\n\n        //% pyHelper=\"py_array_clear\"\n        clear(): void;\n\n        //% pyHelper=\"py_array_index\"\n        index(value: any, start?: number, end?: number): number;\n\n        //% pyHelper=\"py_array_count\"\n        count(value: any): number;\n    }\n\n    interface String {\n        //% pyHelper=\"py_string_capitalize\"\n        capitalize(): string;\n\n        //% pyHelper=\"py_string_casefold\"\n        casefold(): string;\n\n        //% pyHelper=\"py_string_center\"\n        center(width: number, fillChar?: string): string;\n\n        //% pyHelper=\"py_string_count\"\n        count(sub: string, start?: number, end?: number): number;\n\n        //% pyHelper=\"py_string_endswith\"\n        endswith(suffix: string, start?: number, end?: number): boolean;\n\n        //% pyHelper=\"py_string_find\"\n        find(sub: string, start?: number, end?: number): number;\n\n        //% pyHelper=\"py_string_index\"\n        index(sub: string, start?: number, end?: number): number;\n\n        //% pyHelper=\"py_string_isalnum\"\n        isalnum(): boolean;\n\n        //% pyHelper=\"py_string_isalpha\"\n        isalpha(): boolean;\n\n        //% pyHelper=\"py_string_isascii\"\n        isascii(): boolean;\n\n        //% pyHelper=\"py_string_isdigit\"\n        isdigit(): boolean;\n\n        //% pyHelper=\"py_string_isnumeric\"\n        isnumeric(): boolean;\n\n        //% pyHelper=\"py_string_isspace\"\n        isspace(): boolean;\n\n        //% pyHelper=\"py_string_isdecimal\"\n        isdecimal(): boolean;\n\n        //% pyHelper=\"py_string_isidentifier\"\n        isidentifier(): boolean;\n\n        //% pyHelper=\"py_string_islower\"\n        islower(): boolean;\n\n        //% pyHelper=\"py_string_isprintable\"\n        isprintable(): boolean;\n\n        //% pyHelper=\"py_string_istitle\"\n        istitle(): boolean;\n\n        //% pyHelper=\"py_string_isupper\"\n        isupper(): boolean;\n\n        //% pyHelper=\"py_string_join\"\n        join(iterable: any[]): string;\n\n        //% pyHelper=\"py_string_ljust\"\n        ljust(width: number, fillChar?: string): string;\n\n        //% pyHelper=\"py_string_lower\"\n        lower(): string;\n\n        //% pyHelper=\"py_string_lstrip\"\n        lstrip(chars?: string): string;\n\n        //% py2tsOverride=\"replace($0, $1)\"\n        replace(oldString: string, newString: string): string;\n\n        //% pyHelper=\"py_string_rfind\"\n        rfind(sub: string, start?: number, end?: number): number;\n\n        //% pyHelper=\"py_string_rindex\"\n        rindex(sub: string, start?: number, end?: number): number;\n\n        //% pyHelper=\"py_string_rjust\"\n        rjust(width: number, fillChar?: string): string;\n\n        //% pyHelper=\"py_string_rsplit\"\n        rsplit(sep?: string, maxSplit?: number): string[];\n\n        //% pyHelper=\"py_string_rstrip\"\n        rstrip(chars?: string): string;\n\n        //% pyHelper=\"py_string_split\"\n        split(sep?: string, maxsplit?: number): string[];\n\n        //% pyHelper=\"py_string_splitlines\"\n        splitlines(keepends?: boolean): string[];\n\n        //% pyHelper=\"py_string_startswith\"\n        startswith(prefix: string, start?: number, end?: number): boolean;\n\n        //% pyHelper=\"py_string_strip\"\n        strip(chars?: string): string;\n\n        //% pyHelper=\"py_string_swapcase\"\n        swapcase(): string;\n\n        //% pyHelper=\"py_string_title\"\n        title(): string;\n\n        //% pyHelper=\"py_string_upper\"\n        upper(): string;\n\n        //% pyHelper=\"py_string_zfill\"\n        zfill(width: number): string;\n    }\n\n    interface Dict {\n        clear(): void;\n        copy(): void;\n        get(key: string, defaultValue?: any): any;\n        // items(): [string, any][];\n        keys(): string[];\n        pop(key: string, defaultValue?: any): any;\n        // popitem(): [string, any];\n        setdefault(key: string, defaultValue?: any): any;\n        update(other: Dict): void;\n        values(): any[];\n    }\n\n    interface Set {\n        isdisjoint(other: Set): boolean;\n        issubset(other: Set): boolean;\n        issuperset(other: Set): boolean;\n        union(other: Set): Set;\n        intersection(other: Set): Set;\n        difference(other: Set): Set;\n        symmetric_difference(other: Set): Set;\n        copy(): Set;\n        update(other: Set): void;\n        intersection_update(other: Set): void;\n        difference_update(other: Set): void;\n        symmetric_difference_update(other: Set): void;\n        add(elem: any): void;\n        remove(elem: any): void;\n        discard(elem: any): void;\n        pop(): any;\n        clear(): void;\n    }\n}","pxt.cpp":"#include \"pxtbase.h\"\n\nusing namespace std;\n\nnamespace pxt {\n\nAction mkAction(int totallen, RefAction *act) {\n    check(getVTable(act)->classNo == BuiltInType::RefAction, PANIC_INVALID_BINARY_HEADER, 1);\n#ifdef PXT_VM\n    check(act->initialLen <= totallen, PANIC_INVALID_BINARY_HEADER, 13);\n#endif\n\n    if (totallen == 0) {\n        return (TValue)act; // no closure needed\n    }\n\n    void *ptr = gcAllocate(sizeof(RefAction) + totallen * sizeof(void *));\n    RefAction *r = new (ptr) RefAction();\n    r->len = totallen;\n#ifdef PXT_VM\n    r->numArgs = act->numArgs;\n    r->initialLen = act->initialLen;\n    r->flags = 0;\n#endif\n    r->func = act->func;\n    memset(r->fields, 0, r->len * sizeof(void *));\n\n    MEMDBG(\"mkAction: start=%p => %p\", act, r);\n\n    return (Action)r;\n}\n\nRefRecord *mkClassInstance(VTable *vtable) {\n    intcheck(vtable->methods[0] == &RefRecord_destroy, PANIC_SIZE, 3);\n    // intcheck(vtable->methods[1] == &RefRecord_print, PANIC_SIZE, 4);\n\n    void *ptr = gcAllocate(vtable->numbytes);\n    RefRecord *r = new (ptr) RefRecord(vtable);\n    memset(r->fields, 0, vtable->numbytes - sizeof(RefRecord));\n    MEMDBG(\"mkClass: vt=%p => %p\", vtable, r);\n    return r;\n}\n\nTValue RefRecord::ld(int idx) {\n    // intcheck((reflen == 255 ? 0 : reflen) <= idx && idx < len, PANIC_OUT_OF_BOUNDS, 1);\n    return fields[idx];\n}\n\nTValue RefRecord::ldref(int idx) {\n    // DMESG(\"LD %p len=%d reflen=%d idx=%d\", this, len, reflen, idx);\n    // intcheck(0 <= idx && idx < reflen, PANIC_OUT_OF_BOUNDS, 2);\n    return fields[idx];\n}\n\nvoid RefRecord::st(int idx, TValue v) {\n    // intcheck((reflen == 255 ? 0 : reflen) <= idx && idx < len, PANIC_OUT_OF_BOUNDS, 3);\n    fields[idx] = v;\n}\n\nvoid RefRecord::stref(int idx, TValue v) {\n    // DMESG(\"ST %p len=%d reflen=%d idx=%d\", this, len, reflen, idx);\n    // intcheck(0 <= idx && idx < reflen, PANIC_OUT_OF_BOUNDS, 4);\n    fields[idx] = v;\n}\n\nvoid RefObject::destroyVT() {\n    ((RefObjectMethod)getVTable(this)->methods[0])(this);\n}\n\n//%\nvoid deleteRefObject(RefObject *obj) {\n    obj->destroyVT();\n}\n\nvoid RefObject::printVT() {\n    ((RefObjectMethod)getVTable(this)->methods[1])(this);\n}\n\nvoid RefRecord_destroy(RefRecord *) {}\n\nvoid RefRecord_print(RefRecord *r) {\n    DMESG(\"RefRecord %p size=%d bytes\", r, getVTable(r)->numbytes);\n}\n\nvoid Segment::set(unsigned i, TValue value) {\n    if (i < size) {\n        data[i] = value;\n    } else if (i < Segment::MaxSize) {\n        growByMin(i + 1);\n        data[i] = value;\n    } else {\n        return;\n    }\n    if (length <= i) {\n        length = i + 1;\n    }\n\n#ifdef DEBUG_BUILD\n    DMESG(\"In Segment::set\");\n    this->print();\n#endif\n\n    return;\n}\n\nstatic inline int growthFactor(int size) {\n    if (size == 0) {\n        return 4;\n    }\n    if (size < 64) {\n        return size * 2; // Double\n    }\n    if (size < 512) {\n        return size * 5 / 3; // Grow by 1.66 rate\n    }\n    // Grow by constant rate\n    if ((unsigned)size + 256 < Segment::MaxSize)\n        return size + 256;\n    else\n        return Segment::MaxSize;\n}\n\nvoid LLSegment::setLength(unsigned newLen) {\n    if (newLen > Segment::MaxSize)\n        return;\n\n    if (newLen > size) {\n        int newSize = growthFactor(size);\n        if (newSize < (int)newLen)\n            newSize = newLen;\n\n        // this will throw if unable to allocate\n        TValue *tmp = (TValue *)(xmalloc(newSize * sizeof(TValue)));\n\n        // Copy existing data\n        if (size) {\n            memcpy(tmp, data, size * sizeof(TValue));\n        }\n        // fill the rest with default value\n        memset(tmp + size, 0, (newSize - size) * sizeof(TValue));\n\n        // free older segment;\n        xfree(data);\n\n        data = tmp;\n        size = newSize;\n    } else if (newLen < length) {\n        memset(data + newLen, 0, (length - newLen) * sizeof(TValue));\n    }\n\n    length = newLen;\n}\n\nvoid LLSegment::set(unsigned idx, TValue v) {\n    if (idx >= Segment::MaxSize)\n        return;\n    if (idx >= length)\n        setLength(idx + 1);\n    data[idx] = v;\n}\n\nTValue LLSegment::pop() {\n    if (length > 0) {\n        --length;\n        TValue value = data[length];\n        data[length] = 0;\n        return value;\n    }\n    return 0;\n}\n\nvoid LLSegment::destroy() {\n    length = size = 0;\n    xfree(data);\n    data = nullptr;\n}\n\nvoid Segment::growByMin(ramint_t minSize) {\n    ramint_t newSize = max(minSize, (ramint_t)growthFactor(size));\n\n    if (size < newSize) {\n        // this will throw if unable to allocate\n        TValue *tmp = (TValue *)(gcAllocateArray(newSize * sizeof(TValue)));\n\n        // Copy existing data\n        if (size)\n            memcpy(tmp, data, size * sizeof(TValue));\n        // fill the rest with default value\n        memset(tmp + size, 0, (newSize - size) * sizeof(TValue));\n\n        data = tmp;\n        size = newSize;\n\n#ifdef DEBUG_BUILD\n        DMESG(\"growBy - after reallocation\");\n        this->print();\n#endif\n    }\n    // else { no shrinking yet; }\n    return;\n}\n\nvoid Segment::ensure(ramint_t newSize) {\n    if (newSize < size) {\n        return;\n    }\n    growByMin(newSize);\n}\n\nvoid Segment::setLength(unsigned newLength) {\n    if (newLength > size) {\n        ensure(newLength);\n    }\n    length = newLength;\n    return;\n}\n\nTValue Segment::pop() {\n#ifdef DEBUG_BUILD\n    DMESG(\"In Segment::pop\");\n    this->print();\n#endif\n\n    if (length > 0) {\n        --length;\n        TValue value = data[length];\n        data[length] = Segment::DefaultValue;\n        return value;\n    }\n    return Segment::DefaultValue;\n}\n\n// this function removes an element at index i and shifts the rest of the elements to\n// left to fill the gap\nTValue Segment::remove(unsigned i) {\n#ifdef DEBUG_BUILD\n    DMESG(\"In Segment::remove index:%d\", i);\n    this->print();\n#endif\n    if (i < length) {\n        // value to return\n        TValue ret = data[i];\n        if (i + 1 < length) {\n            // Move the rest of the elements to fill in the gap.\n            memmove(data + i, data + i + 1, (length - i - 1) * sizeof(void *));\n        }\n        length--;\n        data[length] = Segment::DefaultValue;\n#ifdef DEBUG_BUILD\n        DMESG(\"After Segment::remove index:%d\", i);\n        this->print();\n#endif\n        return ret;\n    }\n    return Segment::DefaultValue;\n}\n\n// this function inserts element value at index i by shifting the rest of the elements right.\nvoid Segment::insert(unsigned i, TValue value) {\n#ifdef DEBUG_BUILD\n    DMESG(\"In Segment::insert index:%d value:%d\", i, value);\n    this->print();\n#endif\n\n    if (i < length) {\n        ensure(length + 1);\n\n        // Move the rest of the elements to fill in the gap.\n        memmove(data + i + 1, data + i, (length - i) * sizeof(void *));\n\n        data[i] = value;\n        length++;\n    } else {\n        // This is insert beyond the length, just call set which will adjust the length\n        set(i, value);\n    }\n#ifdef DEBUG_BUILD\n    DMESG(\"After Segment::insert index:%d\", i);\n    this->print();\n#endif\n}\n\nvoid Segment::print() {\n    DMESG(\"Segment: %p, length: %d, size: %d\", data, (unsigned)length, (unsigned)size);\n    for (unsigned i = 0; i < size; i++) {\n        DMESG(\"-> %d\", (unsigned)(uintptr_t)data[i]);\n    }\n}\n\nvoid Segment::destroy() {\n#ifdef DEBUG_BUILD\n    DMESG(\"In Segment::destroy\");\n    this->print();\n#endif\n    length = size = 0;\n    data = nullptr;\n}\n\nPXT_VTABLE_CTOR(RefCollection) {}\n\nvoid RefCollection::destroy(RefCollection *t) {\n    t->head.destroy();\n}\n\nvoid RefCollection::print(RefCollection *t) {\n    DMESG(\"RefCollection %p size=%d\", t, t->head.getLength());\n    t->head.print();\n}\n\nPXT_VTABLE(RefAction, ValType::Function)\nRefAction::RefAction() : PXT_VTABLE_INIT(RefAction) {}\n\n// fields[] contain captured locals\nvoid RefAction::destroy(RefAction *t) {}\n\nvoid RefAction::print(RefAction *t) {\n#ifdef PXT_VM\n    DMESG(\"RefAction %p pc=%X size=%d\", t, (uint32_t)t->func, t->len);\n#else\n    DMESG(\"RefAction %p pc=%X size=%d\", t, (const uint8_t *)t->func - (const uint8_t *)bytecode,\n          t->len);\n#endif\n}\n\nPXT_VTABLE_CTOR(RefRefLocal) {\n    v = 0;\n}\n\nvoid RefRefLocal::print(RefRefLocal *t) {\n    DMESG(\"RefRefLocal %p v=%p\", t, (void *)t->v);\n}\n\nvoid RefRefLocal::destroy(RefRefLocal *t) {\n    decr(t->v);\n}\n\nPXT_VTABLE_CTOR(RefMap) {}\n\nvoid RefMap::destroy(RefMap *t) {\n    t->keys.destroy();\n    t->values.destroy();\n}\n\nint RefMap::findIdx(String key) {\n    auto len = keys.getLength();\n    auto data = (String *)keys.getData();\n\n    // fast path\n    for (unsigned i = 0; i < len; ++i) {\n        if (data[i] == key)\n            return i;\n    }\n\n    // slow path\n    auto keylen = key->getUTF8Size();\n    auto keydata = key->getUTF8Data();\n    for (unsigned i = 0; i < len; ++i) {\n        auto s = data[i];\n        if (s->getUTF8Size() == keylen && memcmp(keydata, s->getUTF8Data(), keylen) == 0)\n            return i;\n    }\n\n    return -1;\n}\n\nvoid RefMap::print(RefMap *t) {\n    DMESG(\"RefMap %p size=%d\", t, t->keys.getLength());\n}\n\nvoid debugMemLeaks() {}\n\nvoid error(PXT_PANIC code, int subcode) {\n    DMESG(\"Error: %d [%d]\", code, subcode);\n    target_panic(code);\n}\n\n#ifndef PXT_VM\nuint16_t *bytecode;\n#endif\nTValue *globals;\n\nvoid checkStr(bool cond, const char *msg) {\n    if (!cond) {\n        while (true) {\n            // uBit.display.scroll(msg, 100);\n            // uBit.sleep(100);\n        }\n    }\n}\n\n#ifdef PXT_VM\nint templateHash() {\n    return *(int*)&vmImg->infoHeader->hexHash;\n}\n\nint programHash() {\n    return *(int*)&vmImg->infoHeader->programHash;\n}\n\nint getNumGlobals() {\n    return (int)vmImg->infoHeader->allocGlobals;\n}\n\nString programName() {\n    return mkString((char *)vmImg->infoHeader->name);\n}\n#else\nint templateHash() {\n    return ((int *)bytecode)[4];\n}\n\nint programHash() {\n    return ((int *)bytecode)[6];\n}\n\nint getNumGlobals() {\n    return bytecode[16];\n}\n\nString programName() {\n    return ((String *)bytecode)[15];\n}\n#endif\n\n#ifndef PXT_VM\nvoid variantNotSupported(const char *v) {\n    DMESG(\"variant not supported: %s\", v);\n    target_panic(PANIC_VARIANT_NOT_SUPPORTED);\n}\n\nvoid exec_binary(unsigned *pc) {\n    // XXX re-enable once the calibration code is fixed and [editor/embedded.ts]\n    // properly prepends a call to [internal_main].\n    // ::touch_develop::internal_main();\n\n    // unique group for radio based on source hash\n    // ::touch_develop::micro_bit::radioDefaultGroup = programHash();\n\n    unsigned ver = *pc++;\n    checkStr(ver == 0x4210, \":( Bad runtime version\");\n\n    bytecode = *((uint16_t **)pc++); // the actual bytecode is here\n\n    if (((uint32_t *)bytecode)[0] == 0x923B8E71) {\n        variantNotSupported((const char *)bytecode + 16);\n        return;\n    }\n\n    globals = (TValue *)app_alloc(sizeof(TValue) * getNumGlobals());\n    memset(globals, 0, sizeof(TValue) * getNumGlobals());\n\n    // can be any valid address, best in RAM for speed\n    globals[0] = (TValue)&globals;\n\n    // just compare the first word\n    // TODO\n    checkStr(((uint32_t *)bytecode)[0] == 0x923B8E70 && (unsigned)templateHash() == *pc,\n             \":( Failed partial flash\");\n\n    uintptr_t startptr = (uintptr_t)bytecode;\n\n    startptr += 64; // header\n\n    initPerfCounters();\n\n    initRuntime();\n\n    runAction0((Action)startptr);\n\n    pxt::releaseFiber();\n}\n\nvoid start() {\n    exec_binary((unsigned *)functionsAndBytecode);\n}\n#endif\n\n} // namespace pxt\n\nnamespace Array_ {\n//%\nbool isArray(TValue arr) {\n    auto vt = getAnyVTable(arr);\n    return vt && vt->classNo == BuiltInType::RefCollection;\n}\n} // namespace Array_\n\nnamespace pxtrt {\n//% expose\nRefCollection *keysOf(TValue v) {\n    auto r = NEW_GC(RefCollection);\n    MEMDBG(\"mkColl[keys]: => %p\", r);\n    if (getAnyVTable(v) != &RefMap_vtable)\n        return r;\n    auto rm = (RefMap *)v;\n    auto len = rm->keys.getLength();\n    if (!len)\n        return r;\n    registerGCObj(r);\n    r->setLength(len);\n    auto dst = r->getData();\n    memcpy(dst, rm->keys.getData(), len * sizeof(TValue));\n    unregisterGCObj(r);\n    return r;\n}\n//% expose\nTValue mapDeleteByString(RefMap *map, String key) {\n    if (getAnyVTable((TValue)map) != &RefMap_vtable)\n        soft_panic(PANIC_DELETE_ON_CLASS);\n    int i = map->findIdx(key);\n    if (i >= 0) {\n        map->keys.remove(i);\n        map->values.remove(i);\n    }\n    return TAG_TRUE;\n}\n\n} // namespace pxtrt\n","pxt.h":"#ifndef __PXT_H\n#define __PXT_H\n\n//#define DEBUG_MEMLEAKS 1\n\n#pragma GCC diagnostic ignored \"-Wunused-parameter\"\n\n#include \"pxtbase.h\"\n\nnamespace pxt {\n\nclass RefMImage : public RefObject {\n  public:\n    ImageData *img;\n\n    RefMImage(ImageData *d);\n    void makeWritable();\n    static void destroy(RefMImage *map);\n    static void print(RefMImage *map);\n    static void scan(RefMImage *t);\n    static unsigned gcsize(RefMImage *t);\n};\n\n#define MSTR(s) ManagedString((s)->getUTF8Data(), (s)->getUTF8Size())\n\nstatic inline String PSTR(ManagedString s) {\n    return mkString(s.toCharArray(), s.length());\n}\n\ntypedef uint32_t ImageLiteral_;\n\nstatic inline ImageData *imageBytes(ImageLiteral_ lit) {\n    return (ImageData *)lit;\n}\n\n#if MICROBIT_CODAL\n// avoid clashes with codal-defined classes\n#define Image MImage\n#define Button MButton\n#endif\n\ntypedef MicroBitPin DevicePin;\n\ntypedef RefMImage *Image;\n\nextern MicroBit uBit;\nextern MicroBitEvent lastEvent;\nextern bool serialLoggingDisabled;\n\nMicroBitPin *getPin(int id);\n\nstatic inline int min_(int a, int b) {\n    if (a < b)\n        return a;\n    else\n        return b;\n}\n\nstatic inline int max_(int a, int b) {\n    if (a > b)\n        return a;\n    else\n        return b;\n}\n\nvoid initMicrobitGC();\n\n} // namespace pxt\n\nusing namespace pxt;\n\n#define DEVICE_EVT_ANY 0\n\n#undef PXT_MAIN\n#define PXT_MAIN                                                                                   \\\n    int main() {                                                                                   \\\n        pxt::initMicrobitGC();                                                                     \\\n        pxt::start();                                                                              \\\n        return 0;                                                                                  \\\n    }\n\n#endif\n\n// vim: ts=2 sw=2 expandtab\n","pxt.json":"{\n    \"name\": \"core\",\n    \"description\": \"The microbit core library\",\n    \"dependencies\": {},\n    \"files\": [\n        \"README.md\",\n        \"platform.h\",\n        \"pxt.cpp\",\n        \"pxt.h\",\n        \"pxtbase.h\",\n        \"pxtcore.h\",\n        \"math.ts\",\n        \"dal.d.ts\",\n        \"enums.d.ts\",\n        \"shims.d.ts\",\n        \"pxt-core.d.ts\",\n        \"core.cpp\",\n        \"pxt-helpers.ts\",\n        \"helpers.ts\",\n        \"pxt-python.d.ts\",\n        \"pxt-python-helpers.ts\",\n        \"pinscompat.ts\",\n        \"configkeys.h\",\n        \"gc.cpp\",\n        \"codal.cpp\",\n        \"images.cpp\",\n        \"basic.cpp\",\n        \"basic.ts\",\n        \"icons.ts\",\n        \"icons.jres\",\n        \"input.cpp\",\n        \"input.ts\",\n        \"gestures.jres\",\n        \"control.ts\",\n        \"control.cpp\",\n        \"controlgc.cpp\",\n        \"perfcounters.ts\",\n        \"interval.ts\",\n        \"gcstats.ts\",\n        \"console.ts\",\n        \"game.ts\",\n        \"led.cpp\",\n        \"led.ts\",\n        \"music.cpp\",\n        \"music.ts\",\n        \"melodies.ts\",\n        \"pins.cpp\",\n        \"pins.ts\",\n        \"serial.cpp\",\n        \"serial.ts\",\n        \"buffer.cpp\",\n        \"buffer.ts\",\n        \"json.ts\",\n        \"poll.ts\",\n        \"controlmessage.ts\",\n        \"pxtparts.json\",\n        \"advmath.cpp\",\n        \"trig.cpp\",\n        \"fixed.ts\",\n        \"templates.ts\",\n        \"sendbuffer.s\",\n        \"sendbuffernrf52.s\",\n        \"sendbufferbrightness.s\",\n        \"light.cpp\",\n        \"logo.cpp\",\n        \"loops.ts\",\n        \"touchmode.cpp\",\n        \"soundexpressions.ts\",\n        \"soundexpressions.cpp\",\n        \"parts/speaker.svg\",\n        \"parts/headphone.svg\",\n        \"playable.ts\"\n    ],\n    \"testFiles\": [],\n    \"public\": true,\n    \"targetVersions\": {\n        \"target\": \"7.1.42\",\n        \"pxt\": \"11.4.28\"\n    },\n    \"dalDTS\": {\n        \"corePackage\": \".\",\n        \"compileServiceVariant\": \"mbcodal\",\n        \"includeDirs\": [\n            \"libraries/codal-core/inc\",\n            \"libraries/codal-microbit-v2/inc\",\n            \"libraries/codal-microbit-v2/model\",\n            \"libraries/codal-microbit-v2/inc/compat\",\n            \"pxtapp\"\n        ],\n        \"excludePrefix\": [\n            \"USB_\",\n            \"REQUEST_\",\n            \"LIS3DH_\",\n            \"FXOS8700_\",\n            \"MMA8\",\n            \"LSM303_\",\n            \"MAG_\",\n            \"MPU6050_\",\n            \"REF_TAG_\",\n            \"HF2_\",\n            \"PXT_REF_TAG_\",\n            \"MS_\",\n            \"SCSI_\"\n        ]\n    },\n    \"yotta\": {\n        \"config\": {\n            \"microbit-dal\": {\n                \"fiber_user_data\": 1,\n                \"pxt\": 1\n            }\n        },\n        \"optionalConfig\": {\n            \"microbit-dal\": {\n                \"bluetooth\": {\n                    \"private_addressing\": 0,\n                    \"advertising_timeout\": 0,\n                    \"tx_power\": 6,\n                    \"dfu_service\": 1,\n                    \"event_service\": 1,\n                    \"device_info_service\": 1,\n                    \"eddystone_url\": 1,\n                    \"eddystone_uid\": 1,\n                    \"open\": 0,\n                    \"pairing_mode\": 1,\n                    \"whitelist\": 1,\n                    \"security_level\": \"SECURITY_MODE_ENCRYPTION_NO_MITM\",\n                    \"partial_flashing\": 1\n                }\n            }\n        },\n        \"userConfigs\": [\n            {\n                \"description\": \"No Pairing Required: Anyone can connect via Bluetooth.\",\n                \"config\": {\n                    \"microbit-dal\": {\n                        \"bluetooth\": {\n                            \"open\": 1,\n                            \"whitelist\": 0,\n                            \"security_level\": null\n                        }\n                    }\n                }\n            },\n            {\n                \"description\": \"JustWorks pairing (default): Pairing is automatic once the pairing is initiated.\",\n                \"config\": {\n                    \"microbit-dal\": {\n                        \"bluetooth\": {\n                            \"open\": 0,\n                            \"whitelist\": 1,\n                            \"security_level\": \"SECURITY_MODE_ENCRYPTION_NO_MITM\"\n                        }\n                    }\n                }\n            },\n            {\n                \"description\": \"Passkey pairing: Pairing requires 6 digit key to pair.\",\n                \"config\": {\n                    \"microbit-dal\": {\n                        \"bluetooth\": {\n                            \"open\": 0,\n                            \"whitelist\": 1,\n                            \"security_level\": \"SECURITY_MODE_ENCRYPTION_WITH_MITM\"\n                        }\n                    }\n                }\n            }\n        ]\n    },\n    \"partial\": true\n}\n","pxtbase.h":"#ifndef __PXTBASE_H\n#define __PXTBASE_H\n\n#pragma GCC diagnostic ignored \"-Wunused-parameter\"\n#pragma GCC diagnostic ignored \"-Wformat\"\n#pragma GCC diagnostic ignored \"-Warray-bounds\"\n\n// needed for gcc6; not sure why\n#undef min\n#undef max\n\n#define NOLOG(...)                                                                                 \\\n    do {                                                                                           \\\n    } while (0)\n\n#define MEMDBG NOLOG\n//#define MEMDBG DMESG\n#define MEMDBG2 NOLOG\n\n#include \"pxtconfig.h\"\n#include \"configkeys.h\"\n\n#ifndef PXT_UTF8\n#define PXT_UTF8 0\n#endif\n\n#if defined(PXT_VM)\n#include <stdint.h>\n#if UINTPTR_MAX == 0xffffffff\n#define PXT32 1\n#elif UINTPTR_MAX == 0xffffffffffffffff\n#define PXT64 1\n#else\n#error \"UINTPTR_MAX has invalid value\"\n#endif\n#endif\n\n#define intcheck(...) check(__VA_ARGS__)\n//#define intcheck(...) do {} while (0)\n\n#ifdef PXT_USE_FLOAT\n#define NUMBER float\n#else\n#define NUMBER double\n#endif\n\n#include <string.h>\n#include <stdint.h>\n#include <math.h>\n\n#ifdef POKY\nvoid *operator new(size_t size, void *ptr);\nvoid *operator new(size_t size);\n#else\n#include <new>\n#endif\n\n#include \"platform.h\"\n#include \"pxtcore.h\"\n\n#ifndef PXT_REGISTER_RESET\n#define PXT_REGISTER_RESET(fn) ((void)0)\n#endif\n\n#define PXT_REFCNT_FLASH 0xfffe\n\n#define CONCAT_1(a, b) a##b\n#define CONCAT_0(a, b) CONCAT_1(a, b)\n// already provided in some platforms, like mbedos\n#ifndef STATIC_ASSERT\n#define STATIC_ASSERT(e) enum { CONCAT_0(_static_assert_, __LINE__) = 1 / ((e) ? 1 : 0) };\n#endif\n\n#ifndef ramint_t\n// this type limits size of arrays\n#if defined(__linux__) || defined(PXT_VM)\n// TODO fix the inline array accesses to take note of this!\n#define ramint_t uint32_t\n#else\n#define ramint_t uint16_t\n#endif\n#endif\n\n#ifndef PXT_IN_ISR\n#define PXT_IN_ISR() (SCB->ICSR & SCB_ICSR_VECTACTIVE_Msk)\n#endif\n\n#ifdef POKY\ninline void *operator new(size_t, void *p) {\n    return p;\n}\ninline void *operator new[](size_t, void *p) {\n    return p;\n}\n#endif\n\nnamespace pxt {\n\ntemplate <typename T> inline const T &max(const T &a, const T &b) {\n    if (a < b)\n        return b;\n    return a;\n}\n\ntemplate <typename T> inline const T &min(const T &a, const T &b) {\n    if (a < b)\n        return a;\n    return b;\n}\n\ntemplate <typename T> inline void swap(T &a, T &b) {\n    T tmp = a;\n    a = b;\n    b = tmp;\n}\n\n//\n// Tagged values (assume 4 bytes for now, Cortex-M0)\n//\nstruct TValueStruct {};\ntypedef TValueStruct *TValue;\n\ntypedef TValue TNumber;\ntypedef TValue Action;\ntypedef TValue ImageLiteral;\n\n// To be implemented by the target\nextern \"C\" void target_panic(int error_code);\nextern \"C\" void target_reset();\nvoid sleep_ms(unsigned ms);\nvoid sleep_us(uint64_t us);\nvoid releaseFiber();\nuint64_t current_time_us();\nint current_time_ms();\nvoid initRuntime();\nvoid initSystemTimer();\nvoid sendSerial(const char *data, int len);\nvoid setSendToUART(void (*f)(const char *, int));\nuint64_t getLongSerialNumber();\nvoid registerWithDal(int id, int event, Action a, int flags = 16); // EVENT_LISTENER_DEFAULT_FLAGS\nvoid runInParallel(Action a);\nvoid runForever(Action a);\nvoid waitForEvent(int id, int event);\n//%\nunsigned afterProgramPage();\n//%\nvoid dumpDmesg();\nuint32_t hash_fnv1(const void *data, unsigned len);\n\n// also defined DMESG macro\n// end\n\n#define TAGGED_SPECIAL(n) (TValue)(void *)((n << 2) | 2)\n#define TAG_FALSE TAGGED_SPECIAL(2) // 10\n#define TAG_TRUE TAGGED_SPECIAL(16) // 66\n#define TAG_UNDEFINED (TValue)0\n#define TAG_NULL TAGGED_SPECIAL(1) // 6\n#define TAG_NAN TAGGED_SPECIAL(3)  // 14\n#define TAG_NUMBER(n) (TNumber)(void *)(((uintptr_t)(uint32_t)(n) << 1) | 1)\n#define TAG_NON_VALUE TAGGED_SPECIAL(4) // 18; doesn't represent any JS value\n\n#ifdef PXT_VM\ninline bool isEncodedDouble(uint64_t v) {\n    return (v >> 48) != 0;\n}\n#endif\n\ninline bool isDouble(TValue v) {\n#ifdef PXT64\n    return ((uintptr_t)v >> 48) != 0;\n#else\n    (void)v;\n    return false;\n#endif\n}\n\ninline bool isPointer(TValue v) {\n    return !isDouble(v) && v != 0 && ((intptr_t)v & 3) == 0;\n}\n\ninline bool isTagged(TValue v) {\n    return (!isDouble(v) && ((intptr_t)v & 3)) || !v;\n}\n\ninline bool isInt(TValue v) {\n    return !isDouble(v) && ((intptr_t)v & 1);\n}\n\ninline bool isSpecial(TValue v) {\n    return !isDouble(v) && ((intptr_t)v & 2);\n}\n\ninline bool bothNumbers(TValue a, TValue b) {\n    return !isDouble(a) && !isDouble(b) && ((intptr_t)a & (intptr_t)b & 1);\n}\n\ninline int numValue(TValue n) {\n    return (int)((intptr_t)n >> 1);\n}\n\ninline bool canBeTagged(int v) {\n    (void)v;\n#ifdef PXT_BOX_DEBUG\n    return false;\n#elif defined(PXT64)\n    return true;\n#else\n    return (v << 1) >> 1 == v;\n#endif\n}\n\n// see https://anniecherkaev.com/the-secret-life-of-nan\n\n#define NanBoxingOffset 0x1000000000000LL\n\ntemplate <typename TO, typename FROM> TO bitwise_cast(FROM in) {\n    STATIC_ASSERT(sizeof(TO) == sizeof(FROM));\n    union {\n        FROM from;\n        TO to;\n    } u;\n    u.from = in;\n    return u.to;\n}\n\ninline double decodeDouble(uint64_t v) {\n    return bitwise_cast<double>(v - NanBoxingOffset);\n}\n\n#ifdef PXT64\nSTATIC_ASSERT(sizeof(void *) == 8);\ninline double doubleVal(TValue v) {\n    return bitwise_cast<double>((uint64_t)v - NanBoxingOffset);\n}\n\ninline TValue tvalueFromDouble(double d) {\n    return (TValue)(bitwise_cast<uint64_t>(d) + NanBoxingOffset);\n}\n#else\nSTATIC_ASSERT(sizeof(void *) == 4);\n#endif\n\n// keep in sym with sim/control.ts\ntypedef enum {\n    PANIC_CODAL_OOM = 20,\n    PANIC_GC_OOM = 21,\n    PANIC_GC_TOO_BIG_ALLOCATION = 22,\n    PANIC_CODAL_HEAP_ERROR = 30,\n    PANIC_CODAL_NULL_DEREFERENCE = 40,\n    PANIC_CODAL_USB_ERROR = 50,\n    PANIC_CODAL_HARDWARE_CONFIGURATION_ERROR = 90,\n\n    PANIC_INVALID_BINARY_HEADER = 901,\n    PANIC_OUT_OF_BOUNDS = 902,\n    PANIC_REF_DELETED = 903,\n    PANIC_SIZE = 904,\n    PANIC_INVALID_VTABLE = 905,\n    PANIC_INTERNAL_ERROR = 906,\n    PANIC_NO_SUCH_CONFIG = 907,\n    PANIC_NO_SUCH_PIN = 908,\n    PANIC_INVALID_ARGUMENT = 909,\n    PANIC_MEMORY_LIMIT_EXCEEDED = 910,\n    PANIC_SCREEN_ERROR = 911,\n    PANIC_MISSING_PROPERTY = 912,\n    PANIC_INVALID_IMAGE = 913,\n    PANIC_CALLED_FROM_ISR = 914,\n    PANIC_HEAP_DUMPED = 915,\n    PANIC_STACK_OVERFLOW = 916,\n    PANIC_BLOCKING_TO_STRING = 917,\n    PANIC_VM_ERROR = 918,\n    PANIC_SETTINGS_CLEARED = 920,\n    PANIC_SETTINGS_OVERLOAD = 921,\n    PANIC_SETTINGS_SECRET_MISSING = 922,\n    PANIC_DELETE_ON_CLASS = 923,\n    PANIC_OUT_OF_TIMERS = 924,\n    PANIC_JACDAC = 925,\n    PANIC_MICROPHONE_MISSING = 926,\n    PANIC_VARIANT_NOT_SUPPORTED = 927,\n\n    PANIC_CAST_FIRST = 980,\n    PANIC_CAST_FROM_UNDEFINED = 980,\n    PANIC_CAST_FROM_BOOLEAN = 981,\n    PANIC_CAST_FROM_NUMBER = 982,\n    PANIC_CAST_FROM_STRING = 983,\n    PANIC_CAST_FROM_OBJECT = 984,\n    PANIC_CAST_FROM_FUNCTION = 985,\n    PANIC_CAST_FROM_NULL = 989,\n\n    PANIC_UNHANDLED_EXCEPTION = 999,\n\n} PXT_PANIC;\n\nextern const uintptr_t functionsAndBytecode[];\nextern TValue *globals;\nextern uint16_t *bytecode;\nclass RefRecord;\n\n// Utility functions\n\ntypedef TValue (*RunActionType)(Action a, TValue arg0, TValue arg1, TValue arg2);\n\n#define asmRunAction3 ((RunActionType)(((uintptr_t *)bytecode)[12]))\n\nstatic inline TValue runAction3(Action a, TValue arg0, TValue arg1, TValue arg2) {\n    return asmRunAction3(a, arg0, arg1, 0);\n}\nstatic inline TValue runAction2(Action a, TValue arg0, TValue arg1) {\n    return asmRunAction3(a, arg0, arg1, 0);\n}\nstatic inline TValue runAction1(Action a, TValue arg0) {\n    return asmRunAction3(a, arg0, 0, 0);\n}\nstatic inline TValue runAction0(Action a) {\n    return asmRunAction3(a, 0, 0, 0);\n}\n\nclass RefAction;\nclass BoxedString;\nstruct VTable;\n\n//%\nAction mkAction(int totallen, RefAction *act);\n//% expose\nint templateHash();\n//% expose\nint programHash();\n//% expose\nBoxedString *programName();\n//% expose\nunsigned programSize();\n//%\nint getNumGlobals();\n//%\nRefRecord *mkClassInstance(VTable *vt);\n//%\nvoid debugMemLeaks();\n//%\nvoid anyPrint(TValue v);\n\n//%\nint getConfig(int key, int defl = -1);\n\n//%\nint toInt(TNumber v);\n//%\nunsigned toUInt(TNumber v);\n//%\nNUMBER toDouble(TNumber v);\n//%\nfloat toFloat(TNumber v);\n//%\nTNumber fromDouble(NUMBER r);\n//%\nTNumber fromFloat(float r);\n\n//%\nTNumber fromInt(int v);\n//%\nTNumber fromUInt(unsigned v);\n//%\nTValue fromBool(bool v);\n//%\nbool eq_bool(TValue a, TValue b);\n//%\nbool eqq_bool(TValue a, TValue b);\n\n//%\nvoid failedCast(TValue v, void *addr = NULL);\n//%\nvoid missingProperty(TValue v);\n\nvoid error(PXT_PANIC code, int subcode = 0);\nvoid exec_binary(unsigned *pc);\nvoid start();\n\nstruct HandlerBinding {\n    HandlerBinding *next;\n    int source;\n    int value;\n    Action action;\n#ifndef PXT_CODAL\n    uint32_t flags;\n    struct Event *pending;\n#endif\n};\nHandlerBinding *findBinding(int source, int value);\nHandlerBinding *nextBinding(HandlerBinding *curr, int source, int value);\nvoid setBinding(int source, int value, Action act);\n\n// Legacy stuff; should no longer be used\n//%\nTValue incr(TValue e);\n//%\nvoid decr(TValue e);\n\ninline TValue incr(TValue e) {\n    return e;\n}\ninline void decr(TValue e) {}\n\nclass RefObject;\n\nstatic inline RefObject *incrRC(RefObject *r) {\n    return r;\n}\nstatic inline void decrRC(RefObject *) {}\n\ninline void *ptrOfLiteral(int offset) {\n    return &bytecode[offset];\n}\n\n// Checks if object is ref-counted, and has a custom PXT vtable in front\n// TODO\ninline bool isRefCounted(TValue e) {\n    return isPointer(e);\n}\n\ninline void check(int cond, PXT_PANIC code, int subcode = 0) {\n    if (!cond)\n        error(code, subcode);\n}\n\ninline void oops(int subcode = 0) {\n    target_panic(800 + subcode);\n}\n\nclass RefObject;\n\ntypedef void (*RefObjectMethod)(RefObject *self);\ntypedef unsigned (*RefObjectSizeMethod)(RefObject *self);\ntypedef void *PVoid;\ntypedef void **PPVoid;\n\ntypedef void *Object_;\n\n#define VTABLE_MAGIC 0xF9\n#define VTABLE_MAGIC2 0xF8\n\nenum class ValType : uint8_t {\n    Undefined,\n    Boolean,\n    Number,\n    String,\n    Object,\n    Function,\n};\n\n// keep in sync with pxt-core (search for the type name)\nenum class BuiltInType : uint16_t {\n    BoxedString = 1,\n    BoxedNumber = 2,\n    BoxedBuffer = 3,\n    RefAction = 4,\n    RefImage = 5,\n    RefCollection = 6,\n    RefRefLocal = 7,\n    RefMap = 8,\n    RefMImage = 9,             // microbit-specific\n    MMap = 10,                 // linux, mostly ev3\n    BoxedString_SkipList = 11, // used by VM bytecode representation only\n    BoxedString_ASCII = 12,    // ditto\n    ZPin = 13,\n    User0 = 16,\n};\n\nstruct VTable {\n    uint16_t numbytes;\n    ValType objectType;\n    uint8_t magic;\n#ifdef PXT_VM\n    uint16_t ifaceHashEntries;\n    BuiltInType lastClassNo;\n#else\n    PVoid *ifaceTable;\n#endif\n    BuiltInType classNo;\n    uint16_t reserved;\n    uint32_t ifaceHashMult;\n\n    // we only use the first few methods here; pxt will generate more\n    PVoid methods[8];\n};\n\n//%\nextern const VTable string_inline_ascii_vt;\n#if PXT_UTF8\n//%\nextern const VTable string_inline_utf8_vt;\n//%\nextern const VTable string_cons_vt;\n//%\nextern const VTable string_skiplist16_vt;\n//%\nextern const VTable string_skiplist16_packed_vt;\n#endif\n//%\nextern const VTable buffer_vt;\n//%\nextern const VTable number_vt;\n//%\nextern const VTable RefAction_vtable;\n\n#ifndef PXT_IS_READONLY\n// assume ARM - ram addresses are 0x2000_0000+; flash is either 0x0+ or 0x0800_0000+\n#define PXT_IS_READONLY(v) (isTagged(v) || !((uintptr_t)v >> 28))\n#endif\n\ninline bool isReadOnly(TValue v) {\n    return PXT_IS_READONLY(v);\n}\n\n// A base abstract class for ref-counted objects.\nclass RefObject {\n  public:\n    const VTable *vtable;\n\n    RefObject(const VTable *vt) {\n#if defined(PXT32) && defined(PXT_VM) && !defined(PXT_ESP32)\n        if ((uint32_t)vt & 0xf0000000)\n            target_panic(PANIC_INVALID_VTABLE);\n#endif\n        vtable = vt;\n    }\n\n    void destroyVT();\n    void printVT();\n\n    inline uintptr_t vt() { return (uintptr_t)vtable; }\n    inline void setVT(uintptr_t v) { vtable = (const VTable *)v; }\n\n    inline void ref() {}\n    inline void unref() {}\n    inline bool isReadOnly() { return pxt::isReadOnly((TValue)this); }\n};\n\nclass Segment {\n  private:\n    TValue *data;\n    ramint_t length;\n    ramint_t size;\n\n    // this just gives max value of ramint_t\n    void growByMin(ramint_t minSize);\n    void ensure(ramint_t newSize);\n\n  public:\n    static constexpr ramint_t MaxSize = (((1U << (8 * sizeof(ramint_t) - 1)) - 1) << 1) + 1;\n    static constexpr TValue DefaultValue = TAG_UNDEFINED; // == NULL\n\n    Segment() : data(nullptr), length(0), size(0) {}\n\n    TValue get(unsigned i) { return i < length ? data[i] : NULL; }\n    void set(unsigned i, TValue value);\n\n    unsigned getLength() { return length; };\n    void setLength(unsigned newLength);\n\n    void push(TValue value) { set(length, value); }\n    TValue pop();\n\n    TValue remove(unsigned i);\n    void insert(unsigned i, TValue value);\n\n    void destroy();\n\n    void print();\n\n    TValue *getData() { return data; }\n};\n\n// Low-Level segment using system malloc\nclass LLSegment {\n  private:\n    TValue *data;\n    ramint_t length;\n    ramint_t size;\n\n  public:\n    LLSegment() : data(nullptr), length(0), size(0) {}\n\n    void set(unsigned idx, TValue v);\n    void push(TValue value) { set(length, value); }\n    TValue pop();\n    void destroy();\n    void setLength(unsigned newLen);\n\n    TValue get(unsigned i) { return i < length ? data[i] : NULL; }\n    unsigned getLength() { return length; };\n    TValue *getData() { return data; }\n};\n\n// A ref-counted collection of either primitive or ref-counted objects (String, Image,\n// user-defined record, another collection)\nclass RefCollection : public RefObject {\n  public:\n    Segment head;\n\n    RefCollection();\n\n    static void destroy(RefCollection *coll);\n    static void scan(RefCollection *coll);\n    static unsigned gcsize(RefCollection *coll);\n    static void print(RefCollection *coll);\n\n    unsigned length() { return head.getLength(); }\n    void setLength(unsigned newLength) { head.setLength(newLength); }\n    TValue getAt(int i) { return head.get(i); }\n    TValue *getData() { return head.getData(); }\n};\n\nclass RefMap : public RefObject {\n  public:\n    Segment keys;\n    Segment values;\n\n    RefMap();\n    static void destroy(RefMap *map);\n    static void scan(RefMap *map);\n    static unsigned gcsize(RefMap *coll);\n    static void print(RefMap *map);\n    int findIdx(BoxedString *key);\n};\n\n// A ref-counted, user-defined JS object.\nclass RefRecord : public RefObject {\n  public:\n    // The object is allocated, so that there is space at the end for the fields.\n    TValue fields[];\n\n    RefRecord(VTable *v) : RefObject(v) {}\n\n    TValue ld(int idx);\n    TValue ldref(int idx);\n    void st(int idx, TValue v);\n    void stref(int idx, TValue v);\n};\n\nstatic inline VTable *getVTable(RefObject *r) {\n    return (VTable *)(r->vt() & ~1);\n}\n\nstatic inline VTable *getAnyVTable(TValue v) {\n    if (!isRefCounted(v))\n        return NULL;\n    auto vt = getVTable((RefObject *)v);\n    if (vt->magic == VTABLE_MAGIC)\n        return vt;\n    return NULL;\n}\n\n// these are needed when constructing vtables for user-defined classes\n//%\nvoid RefRecord_destroy(RefRecord *r);\n//%\nvoid RefRecord_print(RefRecord *r);\n//%\nvoid RefRecord_scan(RefRecord *r);\n//%\nunsigned RefRecord_gcsize(RefRecord *r);\n\ntypedef TValue (*ActionCB)(TValue *captured, TValue arg0, TValue arg1, TValue arg2);\n\n// Ref-counted function pointer.\nclass RefAction : public RefObject {\n  public:\n    uint16_t len;\n    uint16_t numArgs;\n#ifdef PXT_VM\n    uint16_t initialLen;\n    uint16_t flags;\n    uintptr_t func;\n#else\n    ActionCB func; // The function pointer\n#endif\n    // fields[] contain captured locals\n    TValue fields[];\n\n    static void destroy(RefAction *act);\n    static void scan(RefAction *act);\n    static unsigned gcsize(RefAction *coll);\n    static void print(RefAction *act);\n\n    RefAction();\n\n    inline void stCore(int idx, TValue v) {\n        // DMESG(\"ST [%d] = %d \", idx, v); this->print();\n        intcheck(0 <= idx && idx < len, PANIC_OUT_OF_BOUNDS, 10);\n        intcheck(fields[idx] == 0, PANIC_OUT_OF_BOUNDS, 11); // only one assignment permitted\n        fields[idx] = v;\n    }\n};\n\n// These two are used to represent locals written from inside inline functions\nclass RefRefLocal : public RefObject {\n  public:\n    TValue v;\n    static void destroy(RefRefLocal *l);\n    static void scan(RefRefLocal *l);\n    static unsigned gcsize(RefRefLocal *l);\n    static void print(RefRefLocal *l);\n    RefRefLocal();\n};\n\ntypedef int color;\n\n// note: this is hardcoded in PXT (hexfile.ts)\n\nclass BoxedNumber : public RefObject {\n  public:\n    NUMBER num;\n    BoxedNumber() : RefObject(&number_vt) {}\n} __attribute__((packed));\n\nclass BoxedString : public RefObject {\n  public:\n    union {\n        struct {\n            uint16_t length; // ==size\n            char data[0];\n        } ascii;\n#if PXT_UTF8\n        struct {\n            uint16_t size;\n            char data[0];\n        } utf8;\n        struct {\n            BoxedString *left;\n            BoxedString *right;\n        } cons;\n        struct {\n            uint16_t size;   // in bytes\n            uint16_t length; // in characters\n            uint16_t *list;\n        } skip;\n        struct {\n            uint16_t size;   // in bytes\n            uint16_t length; // in characters\n            uint16_t list[0];\n        } skip_pack;\n#endif\n    };\n\n#if PXT_UTF8\n    uintptr_t runMethod(int idx) {\n        return ((uintptr_t(*)(BoxedString *))vtable->methods[idx])(this);\n    }\n    const char *getUTF8Data() { return (const char *)runMethod(4); }\n    uint32_t getUTF8Size() { return (uint32_t)runMethod(5); }\n    // in characters\n    uint32_t getLength() { return (uint32_t)runMethod(6); }\n    const char *getUTF8DataAt(uint32_t pos) {\n        auto meth = ((const char *(*)(BoxedString *, uint32_t))vtable->methods[7]);\n        return meth(this, pos);\n    }\n#else\n    const char *getUTF8Data() { return ascii.data; }\n    uint32_t getUTF8Size() { return ascii.length; }\n    uint32_t getLength() { return ascii.length; }\n    const char *getUTF8DataAt(uint32_t pos) { return pos < ascii.length ? ascii.data + pos : NULL; }\n#endif\n\n    TNumber charCodeAt(int pos);\n\n    BoxedString(const VTable *vt) : RefObject(vt) {}\n};\n\n// cross version compatible way of accessing string data\n#ifndef PXT_STRING_DATA\n#define PXT_STRING_DATA(str) str->getUTF8Data()\n#endif\n\n// cross version compatible way of accessing string length\n#ifndef PXT_STRING_DATA_LENGTH\n#define PXT_STRING_DATA_LENGTH(str) str->getUTF8Size()\n#endif\n\nclass BoxedBuffer : public RefObject {\n  public:\n    // data needs to be word-aligned, so we use 32 bits for length\n    int length;\n    uint8_t data[0];\n    BoxedBuffer() : RefObject(&buffer_vt) {}\n\n    static bool isInstance(TValue v);\n};\n\n// cross version compatible way of access data field\n#ifndef PXT_BUFFER_DATA\n#define PXT_BUFFER_DATA(buffer) buffer->data\n#endif\n\n// cross version compatible way of access data length\n#ifndef PXT_BUFFER_LENGTH\n#define PXT_BUFFER_LENGTH(buffer) buffer->length\n#endif\n\n#ifndef PXT_CREATE_BUFFER\n#define PXT_CREATE_BUFFER(data, len) pxt::mkBuffer(data, len)\n#endif\n\n// Legacy format:\n// the first byte of data indicates the format - currently 0xE1 or 0xE4 to 1 or 4 bit bitmaps\n// second byte indicates width in pixels\n// third byte indicates the height (which should also match the size of the buffer)\n// just like ordinary buffers, these can be layed out in flash\n\n// Current format:\n// 87 BB WW WW HH HH 00 00 DATA\n// that is: 0x87, 0x01 or 0x04 - bpp, width in little endian, height, 0x00, 0x00 followed by data\n// for 4 bpp images, rows are word-aligned (as in legacy)\n\n#define IMAGE_HEADER_MAGIC 0x87\n\nstruct ImageHeader {\n    uint8_t magic;\n    uint8_t bpp;\n    uint16_t width;\n    uint16_t height;\n    uint16_t padding;\n    uint8_t pixels[0];\n};\n\nclass RefImage : public RefObject {\n  public:\n    BoxedBuffer *buffer;\n    uint32_t revision;\n\n    RefImage(BoxedBuffer *buf);\n    RefImage(uint32_t sz);\n\n    void setBuffer(BoxedBuffer *b);\n\n    uint8_t *data() { return buffer->data; }\n    int length() { return (int)buffer->length; }\n\n    ImageHeader *header() { return (ImageHeader *)buffer->data; }\n    int pixLength() { return length() - sizeof(ImageHeader); }\n\n    int width() { return header()->width; }\n    int height() { return header()->height; }\n    int wordHeight();\n    int bpp() { return header()->bpp; }\n\n    bool hasPadding() { return (height() & 0x7) != 0; }\n\n    uint8_t *pix() { return header()->pixels; }\n\n    int byteHeight() {\n        if (bpp() == 1)\n            return (height() + 7) >> 3;\n        else if (bpp() == 4)\n            return ((height() * 4 + 31) >> 5) << 2;\n        else {\n            oops(21);\n            return -1;\n        }\n    }\n\n    uint8_t *pix(int x, int y) {\n        uint8_t *d = &pix()[byteHeight() * x];\n        if (y) {\n            if (bpp() == 1)\n                d += y >> 3;\n            else if (bpp() == 4)\n                d += y >> 1;\n        }\n        return d;\n    }\n\n    uint8_t fillMask(color c);\n    bool inRange(int x, int y);\n    void clamp(int *x, int *y);\n    void makeWritable();\n\n    static void destroy(RefImage *t);\n    static void scan(RefImage *t);\n    static unsigned gcsize(RefImage *t);\n    static void print(RefImage *t);\n};\n\nRefImage *mkImage(int w, int h, int bpp);\n\ntypedef BoxedBuffer *Buffer;\ntypedef BoxedString *String;\ntypedef RefImage *Image_;\n\nuint32_t toRealUTF8(String str, uint8_t *dst);\n\n// keep in sync with github/pxt/pxtsim/libgeneric.ts\nenum class NumberFormat {\n    Int8LE = 1,\n    UInt8LE,\n    Int16LE,\n    UInt16LE,\n    Int32LE,\n    Int8BE,\n    UInt8BE,\n    Int16BE,\n    UInt16BE,\n    Int32BE,\n\n    UInt32LE,\n    UInt32BE,\n    Float32LE,\n    Float64LE,\n    Float32BE,\n    Float64BE,\n};\n\n// this will, unlike mkStringCore, UTF8-canonicalize the data\nString mkString(const char *data, int len = -1);\n// data can be NULL in both cases\nBuffer mkBuffer(const void *data, int len);\nString mkStringCore(const char *data, int len = -1);\n\nTNumber getNumberCore(uint8_t *buf, int size, NumberFormat format);\nvoid setNumberCore(uint8_t *buf, int size, NumberFormat format, TNumber value);\n\nvoid seedRandom(unsigned seed);\nvoid seedAddRandom(unsigned seed);\n// max is inclusive\nunsigned getRandom(unsigned max);\n\nValType valType(TValue v);\n\n// this is equivalent to JS `throw v`; it will leave\n// the current function(s), all the way until the nearest try block and\n// ignore all destructors (think longjmp())\nvoid throwValue(TValue v);\n\nvoid registerGC(TValue *root, int numwords = 1);\nvoid unregisterGC(TValue *root, int numwords = 1);\nvoid registerGCPtr(TValue ptr);\nvoid unregisterGCPtr(TValue ptr);\nstatic inline void registerGCObj(RefObject *ptr) {\n    registerGCPtr((TValue)ptr);\n}\nstatic inline void unregisterGCObj(RefObject *ptr) {\n    unregisterGCPtr((TValue)ptr);\n}\nvoid gc(int flags);\n\nstruct StackSegment {\n    void *top;\n    void *bottom;\n    StackSegment *next;\n};\n\n#define NUM_TRY_FRAME_REGS 3\nstruct TryFrame {\n    TryFrame *parent;\n    uintptr_t registers[NUM_TRY_FRAME_REGS];\n};\n\nstruct ThreadContext {\n    TValue *globals;\n    StackSegment stack;\n    TryFrame *tryFrame;\n    TValue thrownValue;\n#ifdef PXT_GC_THREAD_LIST\n    ThreadContext *next;\n    ThreadContext *prev;\n#endif\n};\n\n#ifdef PXT_GC_THREAD_LIST\nextern ThreadContext *threadContexts;\nvoid *threadAddressFor(ThreadContext *, void *sp);\n#endif\n\nvoid releaseThreadContext(ThreadContext *ctx);\nThreadContext *getThreadContext();\nvoid setThreadContext(ThreadContext *ctx);\n\n#ifndef PXT_GC_THREAD_LIST\nvoid gcProcessStacks(int flags);\n#endif\n\nvoid gcProcess(TValue v);\nvoid gcFreeze();\n\n#ifdef PXT_VM\nvoid gcStartup();\nvoid gcPreStartup();\n#endif\n\nvoid coreReset();\nvoid gcReset();\nvoid systemReset();\n\nvoid doNothing();\n\nvoid *gcAllocate(int numbytes);\nvoid *gcAllocateArray(int numbytes);\nextern \"C\" void *app_alloc(int numbytes);\nextern \"C\" void *app_free(void *ptr);\nextern \"C\" void *app_alloc_at(void *at, int numbytes);\nvoid gcPreAllocateBlock(uint32_t sz);\n\nint redirectSamples(int16_t *dst, int numsamples, int samplerate);\n\n#ifdef PXT64\n#define TOWORDS(bytes) (((bytes) + 7) >> 3)\n#else\n#define TOWORDS(bytes) (((bytes) + 3) >> 2)\n#endif\n\n#ifndef PXT_VM\n#define soft_panic target_panic\n#endif\n\nextern int debugFlags;\n\nenum class PerfCounters {\n    GC,\n};\n\n#ifdef PXT_PROFILE\n#ifndef PERF_NOW\n#error \"missing platform timer support\"\n#endif\n\n#ifndef PERF_NOW_MASK\n#define PERF_NOW_MASK 0xffffffff\n#endif\n\n#ifndef PERF_NOW_SCALE\n#define PERF_NOW_SCALE 1\n#endif\n\nstruct PerfCounter {\n    uint32_t value;\n    uint32_t numstops;\n    uint32_t start;\n};\n\nextern struct PerfCounter *perfCounters;\n\nvoid initPerfCounters();\n//%\nvoid dumpPerfCounters();\n//%\nvoid startPerfCounter(PerfCounters n);\n//%\nvoid stopPerfCounter(PerfCounters n);\n#else\ninline void startPerfCounter(PerfCounters n) {}\ninline void stopPerfCounter(PerfCounters n) {}\ninline void initPerfCounters() {}\ninline void dumpPerfCounters() {}\n#endif\n\n// Handling of built-in string literals (like \"[Object]\", \"true\" etc.).\n\n// This has the same layout as BoxedString, but has statically allocated buffer\ntemplate <size_t N> struct BoxedStringLayout {\n    const void *vtable;\n    uint16_t size;\n    const char data[N];\n};\n\ntemplate <size_t N> constexpr size_t _boxedStringLen(char const (&)[N]) {\n    return N;\n}\n\n// strings defined here as used as (String)name\n#define PXT_DEF_STRING(name, val)                                                                  \\\n    const BoxedStringLayout<_boxedStringLen(val)> name[1] = {                                      \\\n        {&pxt::string_inline_ascii_vt, _boxedStringLen(val) - 1, val}};\n\n// bigger value - less memory, but slower\n// 16/20 keeps s.length and s.charCodeAt(i) at about 200 cycles (for actual unicode strings),\n// which is similar to amortized allocation time\n#define PXT_STRING_SKIP_INCR 16 // needs to be power of 2; needs to be kept in sync with compiler\n#define PXT_STRING_MIN_SKIP                                                                        \\\n    20 // min. size of string to use skip list; static code has its own limit\n\n#define PXT_NUM_SKIP_ENTRIES(p) ((p)->skip.length / PXT_STRING_SKIP_INCR)\n#define PXT_SKIP_DATA_IND(p) ((const char *)(p->skip.list + PXT_NUM_SKIP_ENTRIES(p)))\n#define PXT_SKIP_DATA_PACK(p) ((const char *)(p->skip_pack.list + PXT_NUM_SKIP_ENTRIES(p)))\n\n} // namespace pxt\n\nusing namespace pxt;\n\nnamespace numops {\n//%\nString toString(TValue v);\n//%\nint toBool(TValue v);\n//%\nint toBoolDecr(TValue v);\n} // namespace numops\n\nnamespace pxt {\ninline bool toBoolQuick(TValue v) {\n    if (v == TAG_TRUE)\n        return true;\n    if (v == TAG_FALSE || v == TAG_UNDEFINED || v == TAG_NULL)\n        return false;\n    return numops::toBool(v);\n}\n} // namespace pxt\n\nnamespace pxtrt {\n//%\nRefMap *mkMap();\n//%\nTValue mapGetByString(RefMap *map, String key);\n//%\nint lookupMapKey(String key);\n//%\nTValue mapGet(RefMap *map, unsigned key);\n//% expose\nvoid mapSetByString(RefMap *map, String key, TValue val);\n//%\nvoid mapSet(RefMap *map, unsigned key, TValue val);\n} // namespace pxtrt\n\nnamespace pins {\nBuffer createBuffer(int size);\n}\n\nnamespace String_ {\n//%\nint compare(String a, String b);\n} // namespace String_\n\nnamespace Array_ {\n//%\nRefCollection *mk();\n//%\nint length(RefCollection *c);\n//%\nvoid setLength(RefCollection *c, int newLength);\n//%\nvoid push(RefCollection *c, TValue x);\n//%\nTValue pop(RefCollection *c);\n//%\nTValue getAt(RefCollection *c, int x);\n//%\nvoid setAt(RefCollection *c, int x, TValue y);\n//%\nTValue removeAt(RefCollection *c, int x);\n//%\nvoid insertAt(RefCollection *c, int x, TValue value);\n//%\nint indexOf(RefCollection *c, TValue x, int start);\n//%\nbool removeElement(RefCollection *c, TValue x);\n} // namespace Array_\n\n#define NEW_GC(T, ...) new (gcAllocate(sizeof(T))) T(__VA_ARGS__)\n\n// The ARM Thumb generator in the JavaScript code is parsing\n// the hex file and looks for the magic numbers as present here.\n//\n// Then it fetches function pointer addresses from there.\n//\n// The vtable pointers are there, so that the ::emptyData for various types\n// can be patched with the right vtable.\n//\n\n#ifndef MICROBIT_CODAL\n#define FLASH_TOP 0x00000000\n#else\n#if MICROBIT_CODAL\n#if MICROBIT_TOP_OF_FLASH\n#define FLASH_TOP MICROBIT_TOP_OF_FLASH\n#else\n#define FLASH_TOP 0x00073000\n#endif\n#else\n#define FLASH_TOP 0x00000000\n#endif         \n#endif\n\n#define PXT_SHIMS_BEGIN                                                                            \\\n    namespace pxt {                                                                                \\\n    const uintptr_t functionsAndBytecode[]                                                         \\\n        __attribute__((aligned(0x20))) = {0x08010801, 0x42424242, 0x08010801, 0x8de9d83e, FLASH_TOP,\n\n#define PXT_SHIMS_END                                                                              \\\n    }                                                                                              \\\n    ;                                                                                              \\\n    }\n\n#if !defined(X86_64) && !defined(PXT_VM)\n#pragma GCC diagnostic ignored \"-Wpmf-conversions\"\n#endif\n\n#ifdef PXT_VM\n#define DEF_VTABLE(name, tp, valtype, ...)                                                         \\\n    const VTable name = {sizeof(tp), valtype, VTABLE_MAGIC, 0, BuiltInType::tp, BuiltInType::tp,   \\\n                         0,          0,       {__VA_ARGS__}};\n#define DEF_VTABLE_EXT(name, tp, valtype, ...)                                                     \\\n    const VTable name = {sizeof(tp), valtype, VTABLE_MAGIC2, 0, BuiltInType::tp, BuiltInType::tp,  \\\n                         0,          0,       {__VA_ARGS__}};\n#else\n#define DEF_VTABLE(name, tp, valtype, ...)                                                         \\\n    const VTable name = {sizeof(tp), valtype, VTABLE_MAGIC, 0, BuiltInType::tp,                    \\\n                         0,          0,       {__VA_ARGS__}};\n#define DEF_VTABLE_EXT(name, tp, valtype, ...)                                                     \\\n    const VTable name = {sizeof(tp), valtype, VTABLE_MAGIC2, 0, BuiltInType::tp,                   \\\n                         0,          0,       {__VA_ARGS__}};\n#endif\n\n#define PXT_VTABLE(classname, valtp)                                                               \\\n    DEF_VTABLE(classname##_vtable, classname, valtp, (void *)&classname::destroy,                  \\\n               (void *)&classname::print, (void *)&classname::scan, (void *)&classname::gcsize)\n\n#define PXT_EXT_VTABLE(classname)                                                                  \\\n    static int classname##_gcsize() { return sizeof(classname); }                                  \\\n    DEF_VTABLE_EXT(classname##_vtable, classname, ValType::Object, (void *)&pxt::doNothing,        \\\n                   (void *)&pxt::anyPrint, (void *)&pxt::doNothing, (void *)&classname##_gcsize)\n\n#define PXT_VTABLE_INIT(classname) RefObject(&classname##_vtable)\n\n#define PXT_VTABLE_CTOR(classname)                                                                 \\\n    PXT_VTABLE(classname, ValType::Object)                                                         \\\n    classname::classname() : PXT_VTABLE_INIT(classname)\n\n#define PXT_MAIN                                                                                   \\\n    int main() {                                                                                   \\\n        pxt::start();                                                                              \\\n        return 0;                                                                                  \\\n    }\n\n#define PXT_FNPTR(x) (uintptr_t)(void *)(x)\n\n#define PXT_ABI(...)\n\n#define JOIN(a, b) a##b\n/// Defines getClassName() function to fetch the singleton\n#define SINGLETON(ClassName)                                                                       \\\n    static ClassName *JOIN(inst, ClassName);                                                       \\\n    ClassName *JOIN(get, ClassName)() {                                                            \\\n        if (!JOIN(inst, ClassName))                                                                \\\n            JOIN(inst, ClassName) = new ClassName();                                               \\\n        return JOIN(inst, ClassName);                                                              \\\n    }\n\n/// Defines getClassName() function to fetch the singleton if PIN present\n#define SINGLETON_IF_PIN(ClassName, pin)                                                           \\\n    static ClassName *JOIN(inst, ClassName);                                                       \\\n    ClassName *JOIN(get, ClassName)() {                                                            \\\n        if (!JOIN(inst, ClassName) && LOOKUP_PIN(pin))                                             \\\n            JOIN(inst, ClassName) = new ClassName();                                               \\\n        return JOIN(inst, ClassName);                                                              \\\n    }\n\n#ifdef PXT_VM\n#include \"vm.h\"\n#endif\n\n#endif\n","pxtcore.h":"#ifndef __PXTCORE_H\n#define __PXTCORE_H\n\n#include \"MicroBit.h\"\n#include \"MicroBitImage.h\"\n#include \"ManagedString.h\"\n#include \"ManagedType.h\"\n\nnamespace pxt {\nvoid debuglog(const char *format, ...);\n}\n\n// #define GC_GET_HEAP_SIZE() device_heap_size(0)\n#define xmalloc malloc\n#define xfree free\n\n#define NON_GC_HEAP_RESERVATION 1024\n\n#ifdef CODAL_CONFIG_H\n#define MICROBIT_CODAL 1\n#define GC_MAX_ALLOC_SIZE 11000\n#else\n#define MICROBIT_CODAL 0\n#define GC_MAX_ALLOC_SIZE 9000\n#define GC_BLOCK_SIZE 256\n#endif\n\n#if !MICROBIT_CODAL\n#undef DMESG\n#define DMESG NOLOG\n#endif\n\n#undef BYTES_TO_WORDS\n\n#endif\n","pxtparts.json":"{\n    \"buttonpair\": {\n        \"simulationBehavior\": \"buttonpair\",\n        \"visual\": {\n            \"builtIn\": \"buttonpair\",\n            \"width\": 75,\n            \"height\": 45,\n            \"pinDistance\": 15,\n            \"pinLocations\": [\n                {\n                    \"x\": 0,\n                    \"y\": 0\n                },\n                {\n                    \"x\": 30,\n                    \"y\": 45\n                },\n                {\n                    \"x\": 45,\n                    \"y\": 0\n                },\n                {\n                    \"x\": 75,\n                    \"y\": 45\n                }\n            ]\n        },\n        \"numberOfPins\": 4,\n        \"pinDefinitions\": [\n            {\n                \"target\": \"P14\",\n                \"style\": \"male\",\n                \"orientation\": \"-Z\"\n            },\n            {\n                \"target\": \"ground\",\n                \"style\": \"male\",\n                \"orientation\": \"-Z\"\n            },\n            {\n                \"target\": \"P15\",\n                \"style\": \"male\",\n                \"orientation\": \"-Z\"\n            },\n            {\n                \"target\": \"ground\",\n                \"style\": \"male\",\n                \"orientation\": \"-Z\"\n            }\n        ],\n        \"instantiation\": {\n            \"kind\": \"singleton\"\n        },\n        \"assembly\": [\n            {\n                \"part\": true\n            },\n            {\n                \"pinIndices\": [\n                    0,\n                    1\n                ]\n            },\n            {\n                \"pinIndices\": [\n                    2,\n                    3\n                ]\n            }\n        ]\n    },\n    \"microservo\": {\n        \"simulationBehavior\": \"microservo\",\n        \"visual\": {\n            \"builtIn\": \"microservo\",\n            \"width\": 74.85,\n            \"height\": 200,\n            \"pinDistance\": 10,\n            \"pinLocations\": [\n                {\n                    \"x\": 30,\n                    \"y\": 5\n                },\n                {\n                    \"x\": 37,\n                    \"y\": 5\n                },\n                {\n                    \"x\": 45,\n                    \"y\": 5\n                }\n            ]\n        },\n        \"numberOfPins\": 3,\n        \"pinDefinitions\": [\n            {\n                \"target\": {\n                    \"pinInstantiationIdx\": 0\n                },\n                \"style\": \"croc\",\n                \"orientation\": \"+Z\"\n            },\n            {\n                \"target\": \"threeVolt\",\n                \"style\": \"croc\",\n                \"orientation\": \"+Z\"\n            },\n            {\n                \"target\": \"ground\",\n                \"style\": \"croc\",\n                \"orientation\": \"+Z\"\n            }\n        ],\n        \"instantiations\": [\n            {\n                \"kind\": \"function\",\n                \"fullyQualifiedName\": \"pins.servoWritePin,pins.servoSetPulse,PwmOnlyPin.servoWrite,PwmOnlyPin.servoSetPulse,servos.Servo.setAngle,servos.Servo.run,servos.Servo.setPulse\",\n                \"argumentRoles\": [\n                    {\n                        \"pinInstantiationIdx\": 0,\n                        \"partParameter\": \"name\"\n                    }\n                ]\n            }\n        ],\n        \"assembly\": [\n            {\n                \"part\": true,\n                \"pinIndices\": [\n                    2\n                ]\n            },\n            {\n                \"pinIndices\": [\n                    0,\n                    1\n                ]\n            }\n        ]\n    },\n    \"neopixel\": {\n        \"simulationBehavior\": \"neopixel\",\n        \"visual\": {\n            \"builtIn\": \"neopixel\",\n            \"width\": 58,\n            \"height\": 113,\n            \"pinDistance\": 9,\n            \"pinLocations\": [\n                {\n                    \"x\": 10,\n                    \"y\": 0\n                },\n                {\n                    \"x\": 19,\n                    \"y\": 0\n                },\n                {\n                    \"x\": 28,\n                    \"y\": 0\n                }\n            ]\n        },\n        \"numberOfPins\": 3,\n        \"pinDefinitions\": [\n            {\n                \"target\": {\n                    \"pinInstantiationIdx\": 0\n                },\n                \"style\": \"croc\",\n                \"orientation\": \"+Z\"\n            },\n            {\n                \"target\": \"threeVolt\",\n                \"style\": \"croc\",\n                \"orientation\": \"+Z\"\n            },\n            {\n                \"target\": \"ground\",\n                \"style\": \"croc\",\n                \"orientation\": \"+Z\"\n            }\n        ],\n        \"instantiation\": {\n            \"kind\": \"function\",\n            \"fullyQualifiedName\": \"neopixel.create\",\n            \"argumentRoles\": [\n                {\n                    \"pinInstantiationIdx\": 0,\n                    \"partParameter\": \"pin\"\n                },\n                {\n                    \"partParameter\": \"mode\"\n                }\n            ]\n        },\n        \"assembly\": [\n            {\n                \"part\": true,\n                \"pinIndices\": [\n                    2\n                ]\n            },\n            {\n                \"pinIndices\": [\n                    0,\n                    1\n                ]\n            }\n        ]\n    },\n    \"ledmatrix\": {\n        \"visual\": {\n            \"builtIn\": \"ledmatrix\",\n            \"width\": 105,\n            \"height\": 105,\n            \"pinDistance\": 15,\n            \"pinLocations\": [\n                {\n                    \"x\": 0,\n                    \"y\": 0\n                },\n                {\n                    \"x\": 15,\n                    \"y\": 0\n                },\n                {\n                    \"x\": 30,\n                    \"y\": 0\n                },\n                {\n                    \"x\": 45,\n                    \"y\": 0\n                },\n                {\n                    \"x\": 105,\n                    \"y\": 105\n                },\n                {\n                    \"x\": 0,\n                    \"y\": 105\n                },\n                {\n                    \"x\": 15,\n                    \"y\": 105\n                },\n                {\n                    \"x\": 30,\n                    \"y\": 105\n                },\n                {\n                    \"x\": 45,\n                    \"y\": 105\n                },\n                {\n                    \"x\": 60,\n                    \"y\": 0\n                }\n            ]\n        },\n        \"simulationBehavior\": \"ledmatrix\",\n        \"numberOfPins\": 10,\n        \"instantiation\": {\n            \"kind\": \"singleton\"\n        },\n        \"pinDefinitions\": [\n            {\n                \"target\": \"P6\",\n                \"style\": \"male\",\n                \"orientation\": \"-Z\",\n                \"colorGroup\": 0\n            },\n            {\n                \"target\": \"P7\",\n                \"style\": \"male\",\n                \"orientation\": \"-Z\",\n                \"colorGroup\": 0\n            },\n            {\n                \"target\": \"P8\",\n                \"style\": \"male\",\n                \"orientation\": \"-Z\",\n                \"colorGroup\": 0\n            },\n            {\n                \"target\": \"P9\",\n                \"style\": \"male\",\n                \"orientation\": \"-Z\",\n                \"colorGroup\": 0\n            },\n            {\n                \"target\": \"P10\",\n                \"style\": \"male\",\n                \"orientation\": \"-Z\",\n                \"colorGroup\": 0\n            },\n            {\n                \"target\": \"P12\",\n                \"style\": \"male\",\n                \"orientation\": \"-Z\",\n                \"colorGroup\": 1\n            },\n            {\n                \"target\": \"P13\",\n                \"style\": \"male\",\n                \"orientation\": \"-Z\",\n                \"colorGroup\": 1\n            },\n            {\n                \"target\": \"P16\",\n                \"style\": \"male\",\n                \"orientation\": \"-Z\",\n                \"colorGroup\": 1\n            },\n            {\n                \"target\": \"P19\",\n                \"style\": \"male\",\n                \"orientation\": \"-Z\",\n                \"colorGroup\": 1\n            },\n            {\n                \"target\": \"P20\",\n                \"style\": \"male\",\n                \"orientation\": \"-Z\",\n                \"colorGroup\": 1\n            }\n        ],\n        \"assembly\": [\n            {\n                \"part\": true\n            },\n            {\n                \"pinIndices\": [\n                    0,\n                    1,\n                    2,\n                    3,\n                    4\n                ]\n            },\n            {\n                \"pinIndices\": [\n                    5,\n                    6,\n                    7,\n                    8,\n                    9\n                ]\n            }\n        ]\n    },\n    \"headphone\": {\n        \"numberOfPins\": 2,\n        \"visual\": {\n            \"image\": \"parts/headphone.svg\",\n            \"width\": 142,\n            \"height\": 180,\n            \"pinDistance\": 20,\n            \"pinLocations\": [\n                {\n                    \"x\": 17,\n                    \"y\": 11\n                },\n                {\n                    \"x\": 55,\n                    \"y\": 50\n                }\n            ]\n        },\n        \"pinDefinitions\": [\n            {\n                \"target\": \"P0\",\n                \"style\": \"croc\",\n                \"orientation\": \"Y\"\n            },\n            {\n                \"target\": \"ground\",\n                \"style\": \"croc\",\n                \"orientation\": \"Y\"\n            }\n        ],\n        \"instantiation\": {\n            \"kind\": \"singleton\"\n        },\n        \"assembly\": [\n            {\n                \"part\": true,\n                \"pinIndices\": [\n                    0\n                ]\n            },\n            {\n                \"pinIndices\": [\n                    1\n                ]\n            }\n        ]\n    },\n    \"speaker\": {\n        \"numberOfPins\": 2,\n        \"visual\": {\n            \"image\": \"parts/speaker.svg\",\n            \"width\": 500,\n            \"height\": 500,\n            \"pinDistance\": 70,\n            \"pinLocations\": [\n                {\n                    \"x\": 180,\n                    \"y\": 135\n                },\n                {\n                    \"x\": 320,\n                    \"y\": 135\n                }\n            ]\n        },\n        \"pinDefinitions\": [\n            {\n                \"target\": \"P0\",\n                \"style\": \"male\",\n                \"orientation\": \"-Z\"\n            },\n            {\n                \"target\": \"ground\",\n                \"style\": \"male\",\n                \"orientation\": \"-Z\"\n            }\n        ],\n        \"instantiation\": {\n            \"kind\": \"singleton\"\n        },\n        \"assembly\": [\n            {\n                \"part\": true,\n                \"pinIndices\": [\n                    0\n                ]\n            },\n            {\n                \"pinIndices\": [\n                    1\n                ]\n            }\n        ]\n    }\n}","sendbuffer.s":".syntax unified\n.section .text.neopixel_send_buffer_core\n.global neopixel_send_buffer_core\n\nneopixel_send_buffer_core:\n    push {r4,r5,r6,r7,lr}\n    \n    mov r4, r1 // ptr\n    mov r5, r2 // len\n    \n    ldr r0, [r0, #8] // get mbed DigitalOut from MicroBitPin\n    ldr r1, [r0, #4] // r1-mask for this pin\n    ldr r2, [r0, #16] // r2-clraddr\n    ldr r3, [r0, #12] // r3-setaddr\n    \n    b .start\n    \n.nextbit:               //            C0\n    str r1, [r3, #0]    // pin := hi  C2\n    tst r6, r0          //            C3\n    bne .islate         //            C4\n    str r1, [r2, #0]    // pin := lo  C6\n.islate:\n    lsrs r6, r6, #1     // r6 >>= 1   C7\n    bne .justbit        //            C8\n    \n    // not just a bit - need new byte\n    adds r4, #1         // r4++       C9\n    subs r5, #1         // r5--       C10\n    bcc .stop           // if (r5<0) goto .stop  C11\n.start:\n    movs r6, #0x80      // reset mask C12\n    nop                 //            C13\n\n.common:               //             C13\n    str r1, [r2, #0]   // pin := lo   C15\n    // always re-load byte - it just fits with the cycles better this way\n    ldrb r0, [r4, #0]  // r0 := *r4   C17\n    b .nextbit         //             C20\n\n.justbit: // C10\n    // no nops, branch taken is already 3 cycles\n    b .common // C13\n\n.stop:    \n    str r1, [r2, #0]   // pin := lo\n\n    pop {r4,r5,r6,r7,pc}\n","sendbufferbrightness.s":".syntax unified\r\n.section .text.neopixel_send_buffer_brightness_core\r\n.global neopixel_send_buffer_brightness_core\r\n\r\nneopixel_send_buffer_brightness_core:\r\n\r\n    push {r4,r5,r6,r7,lr}\r\n    \r\n    mov r4, r1 // ptr\r\n    mov r5, r2 // len\r\n    mov r7, r3 // get the brightness figure\r\n    \r\n    ldr r0, [r0, #8] // get mbed DigitalOut from MicroBitPin\r\n    ldr r1, [r0, #4] // r1-mask for this pin\r\n    ldr r2, [r0, #16] // r2-clraddr\r\n    ldr r3, [r0, #12] // r3-setaddr\r\n \r\n    b .start\r\n    \r\n.nextbit:               //            C0\r\n    str r1, [r3, #0]    // pin := hi  C2\r\n    tst r6, r0          //            C3\r\n    bne .islate         //            C4\r\n    str r1, [r2, #0]    // pin := lo  C6\r\n.islate:\r\n    lsrs r6, r6, #1     // r6 >>= 1   C7\r\n    bne .justbit        //            C8\r\n    \r\n    // not just a bit - need new byte\r\n    adds r4, #1         // r4++       C9\r\n    subs r5, #1         // r5--       C10\r\n    bcc .stop           // if (r5<0) goto .stop  C11\r\n.start:\r\n    movs r6, #0x80      // reset mask C12\r\n    ldrb r0, [r4, #0]   // r0 := *r4   \r\n    muls r0, r7         // hope we have single cycle multiplier...\r\n    lsrs r0, r0, #8     // r0 >>= 8 following multiplication\r\n    \r\n.common:               //             C13\r\n    str r1, [r2, #0]   // pin := lo   C15\r\n    nop                 // twiddle \r\n    nop                 // twaddle\r\n    \r\n    b .nextbit         //             C20\r\n\r\n.justbit: // C10\r\n    // no nops, branch taken is already 3 cycles\r\n    b .common // C13\r\n\r\n.stop:    \r\n    str r1, [r2, #0]   // pin := lo\r\n\r\n    pop {r4,r5,r6,r7,pc}","sendbuffernrf52.s":".syntax unified\n\n#ifndef NRF51\n\n// put it in RAM\n.section .data.neopixel_send_buffer_nrf52\n.global neopixel_send_buffer_nrf52\n.thumb\n.type   neopixel_send_buffer_nrf52, %function\n\n\n\n\nneopixel_send_buffer_nrf52:\n    push {r4,r5,r6,r7,lr}\n    \n    lsrs r7, r1, #20 // r7 - brightness\n    ands r1, #0xff\n    movs r4, #1\n    lsls r1, r4, r1 // r1 - mask\n\n    mov r4, r2 // ptr\n    mov r5, r3 // len\n    mov r3, r0 // port+0x500\n    \n    b .start\n.nextbit:\n    str r1, [r3, #0x8]    // pin := hi\n\n    movs r2, #8\n    tst r6, r0\n    it eq\n    movseq r2, #3\n\n.d1:\n    subs r2, #1\n    bne .d1\n\n    str r1, [r3, #0xC]    // pin := lo\n\n    movs r2, #4\n    tst r6, r0\n    it eq\n    movseq r2, #6\n\n    lsrs r6, r6, #1     // r6 >>= 1 \n    beq .reload\n\n    nop\n    nop\n    nop\n\n.d0:\n    subs r2, #1\n    bne .d0\n\n    b .nextbit\n\n.reload:    \n    subs r2, #2 // offset following operations\n.d2:\n    subs r2, #1\n    bne .d2\n\n    // not just a bit - need new byte\n    adds r4, #1         // r4++    \n    subs r5, #1         // r5--      \n    ble .stop           // if (r5<=0) goto .stop  \n.start:\n    movs r6, #0x80      // reset mask\n    ldrb r0, [r4, #0]  // r0 := *r4 \n    muls r0, r7      \n    lsrs r0, r0, #8     // r0 >>= 8\n    str r1, [r3, #0xC]   // pin := lo   \n    b .nextbit         //\n\n.stop:    \n    str r1, [r3, #0xC]   // pin := lo\n\n    pop {r4,r5,r6,r7,pc}\n\n#endif\n","serial.cpp":"#include \"pxt.h\"\n\n#define MICROBIT_SERIAL_READ_BUFFER_LENGTH 64\n\n// make sure USB_TX and USB_RX don't overlap with other pin ids\n// also, 1001,1002 need to be kept in sync with getPin() function\nenum SerialPin {\n    P0 = MICROBIT_ID_IO_P0,\n    P1 = MICROBIT_ID_IO_P1,\n    P2 = MICROBIT_ID_IO_P2,\n    P8 = MICROBIT_ID_IO_P8,\n    P12 = MICROBIT_ID_IO_P12,\n    P13 = MICROBIT_ID_IO_P13,\n    P14 = MICROBIT_ID_IO_P14,\n    P15 = MICROBIT_ID_IO_P15,\n    P16 = MICROBIT_ID_IO_P16,\n    USB_TX = 1001,\n    USB_RX = 1002\n};\n\nenum BaudRate {\n  //% block=115200\n  BaudRate115200 = 115200,\n  //% block=57600\n  BaudRate57600 = 57600,\n  //% block=38400\n  BaudRate38400 = 38400,\n  //% block=31250\n  BaudRate31250 = 31250,\n  //% block=28800\n  BaudRate28800 = 28800,\n  //% block=19200\n  BaudRate19200 = 19200,\n  //% block=14400\n  BaudRate14400 = 14400,\n  //% block=9600\n  BaudRate9600 = 9600,\n  //% block=4800\n  BaudRate4800 = 4800,\n  //% block=2400\n  BaudRate2400 = 2400,\n  //% block=1200\n  BaudRate1200 = 1200\n};\n\n//% weight=2 color=#002050 icon=\"\\uf287\"\n//% advanced=true\nnamespace serial {\n#if MICROBIT_CODAL\n    bool is_redirected;\n#endif\n\n    // note that at least one // followed by % is needed per declaration!\n\n    /**\n     * Read a line of text from the serial port and return the buffer when the delimiter is met.\n     * @param delimiter text delimiter that separates each text chunk\n     */\n    //% help=serial/read-until\n    //% blockId=serial_read_until block=\"serial|read until %delimiter=serial_delimiter_conv\"\n    //% weight=19\n    String readUntil(String delimiter) {\n      return PSTR(uBit.serial.readUntil(MSTR(delimiter)));\n    }\n\n    /**\n    * Read the buffered received data as a string\n    */\n    //% help=serial/read-string\n    //% blockId=serial_read_buffer block=\"serial|read string\"\n    //% weight=18\n    String readString() {\n      int n = uBit.serial.getRxBufferSize();\n      if (n == 0) return mkString(\"\", 0);\n      return PSTR(uBit.serial.read(n, MicroBitSerialMode::ASYNC));\n    }\n\n    /**\n    * Register an event to be fired when one of the delimiter is matched.\n    * @param delimiters the characters to match received characters against.\n    */\n    //% help=serial/on-data-received\n    //% weight=18 blockId=serial_on_data_received block=\"serial|on data received %delimiters=serial_delimiter_conv\"\n    void onDataReceived(String delimiters, Action body) {\n      uBit.serial.eventOn(MSTR(delimiters));\n      registerWithDal(MICROBIT_ID_SERIAL, MICROBIT_SERIAL_EVT_DELIM_MATCH, body);\n      // lazy initialization of serial buffers\n      uBit.serial.read(MicroBitSerialMode::ASYNC);\n    }\n\n    /**\n     * Send a piece of text through the serial connection.\n     */\n    //% help=serial/write-string\n    //% weight=87 blockGap=8\n    //% blockId=serial_writestring block=\"serial|write string %text\"\n    //% text.shadowOptions.toString=true\n    void writeString(String text) {\n      if (!text) return;\n\n      uBit.serial.send(MSTR(text));\n    }\n\n    /**\n    * Send a buffer through serial connection\n    */\n    //% blockId=serial_writebuffer block=\"serial|write buffer %buffer=serial_readbuffer\"\n    //% help=serial/write-buffer advanced=true weight=6\n    void writeBuffer(Buffer buffer) {\n      if (!buffer) return;\n\n      uBit.serial.send(buffer->data, buffer->length);\n    }\n\n    /**\n    * Read multiple characters from the receive buffer. \n    * If length is positive, pauses until enough characters are present.\n    * @param length default buffer length\n    */\n    //% blockId=serial_readbuffer block=\"serial|read buffer %length\"\n    //% help=serial/read-buffer advanced=true weight=5\n    Buffer readBuffer(int length) {\n      auto mode = SYNC_SLEEP;\n      if (length <= 0) {\n        length = uBit.serial.getRxBufferSize();\n        mode = ASYNC;\n      }\n\n      auto buf = mkBuffer(NULL, length);\n      auto res = buf;\n      registerGCObj(buf); // make sure buffer is pinned, while we wait for data\n      int read = uBit.serial.read(buf->data, buf->length, mode);\n      if (read != length) {\n        res = mkBuffer(buf->data, read);\n      }\n      unregisterGCObj(buf);\n\n      return res;\n    }\n\n    bool tryResolvePin(SerialPin p, PinName& name) {\n      switch(p) {\n#if !MICROBIT_CODAL\n        case SerialPin::USB_TX: name = USBTX; return true;\n        case SerialPin::USB_RX: name = USBRX; return true;\n#endif\n        default: \n          auto pin = getPin(p); \n          if (NULL != pin) {\n            name = (PinName)pin->name;\n            return true;\n          }\n      }\n      return false;\n    }\n\n    /**\n    * Set the serial input and output to use pins instead of the USB connection.\n    * @param tx the new transmission pin, eg: SerialPin.P0\n    * @param rx the new reception pin, eg: SerialPin.P1\n    * @param rate the new baud rate. eg: 115200\n    */\n    //% weight=10\n    //% help=serial/redirect\n    //% blockId=serial_redirect block=\"serial|redirect to|TX %tx|RX %rx|at baud rate %rate\"\n    //% blockExternalInputs=1\n    //% tx.fieldEditor=\"gridpicker\" tx.fieldOptions.columns=3\n    //% tx.fieldOptions.tooltips=\"false\"\n    //% rx.fieldEditor=\"gridpicker\" rx.fieldOptions.columns=3\n    //% rx.fieldOptions.tooltips=\"false\"\n    //% blockGap=8\n    void redirect(SerialPin tx, SerialPin rx, BaudRate rate) {\n#if MICROBIT_CODAL\n      if (getPin(tx) && getPin(rx)) {\n        uBit.serial.redirect(*getPin(tx), *getPin(rx));\n        is_redirected = 1;\n      }\n      uBit.serial.setBaud(rate);\n#else\n      PinName txn;\n      PinName rxn;\n      if (tryResolvePin(tx, txn) && tryResolvePin(rx, rxn))\n        uBit.serial.redirect(txn, rxn);\n      uBit.serial.baud((int)rate);\n#endif\n    }\n\n    /**\n    Set the baud rate of the serial port\n    */\n    //% weight=10\n    //% blockId=serial_setbaudrate block=\"serial|set baud rate %rate\"\n    //% blockGap=8 inlineInputMode=inline\n    //% help=serial/set-baud-rate\n    //% group=\"Configuration\" advanced=true\n    void setBaudRate(BaudRate rate) {\n#if MICROBIT_CODAL\n      uBit.serial.setBaud(rate);\n#else\n      uBit.serial.baud((int)rate);\n#endif\n    }\n\n\n    /**\n    * Direct the serial input and output to use the USB connection.\n    */\n    //% weight=9 help=serial/redirect-to-usb\n    //% blockId=serial_redirect_to_usb block=\"serial|redirect to USB\"\n    void redirectToUSB() {\n#if MICROBIT_CODAL\n      is_redirected = false;\n      uBit.serial.redirect(uBit.io.usbTx, uBit.io.usbRx);\n      uBit.serial.setBaud(115200);\n#else\n      uBit.serial.redirect(USBTX, USBRX);\n      uBit.serial.baud(115200);\n#endif\n    }\n\n    /**\n    * Sets the size of the RX buffer in bytes\n    * @param size length of the rx buffer in bytes, eg: 32\n    */\n    //% help=serial/set-rx-buffer-size\n    //% blockId=serialSetRxBufferSize block=\"serial set rx buffer size to $size\"\n    //% advanced=true\n    void setRxBufferSize(uint8_t size) {\n      uBit.serial.setRxBufferSize(size);\n    }\n\n    /**\n    * Sets the size of the TX buffer in bytes\n    * @param size length of the tx buffer in bytes, eg: 32\n    */\n    //% help=serial/set-tx-buffer-size\n    //% blockId=serialSetTxBufferSize block=\"serial set tx buffer size to $size\"\n    //% advanced=true\n    void setTxBufferSize(uint8_t size) {\n      uBit.serial.setTxBufferSize(size);\n    }\n\n    /** Send DMESG debug buffer over serial. */\n    //%\n    void writeDmesg() {\n        pxt::dumpDmesg();\n    }\n}\n\nnamespace pxt {\n\nstatic void sendString(const char *c, int len) {\n  while (len--)\n    uBit.serial.putc(*c++);\n}\n\nvoid dumpDmesg() {\n#if MICROBIT_CODAL\n    if (serial::is_redirected)\n      return;\n    microbit_dmesg_flush();\n#endif\n}\n\n}\n","serial.ts":"const enum Delimiters {\n    //% block=\"new line (\\n)\"\n    NewLine = 10,\n    //% block=\",\"\n    Comma = 44,\n    //% block=\"$\"\n    Dollar = 36,\n    //% block=\":\"\n    Colon = 58,\n    //% block=\".\"\n    Fullstop = 46,\n    //% block=\"#\"\n    Hash = 35,\n    //% block=\"carriage return (\\r)\"\n    CarriageReturn = 13,\n    //% block=\"space\"\n    Space = 32,\n    //% block=\"tab (\\t)\"\n    Tab = 9,\n    //% block=\"|\"\n    Pipe = 124,\n    //% block=\";\"\n    SemiColon = 59,\n}\n\n/**\n * Reading and writing data over a serial connection.\n */\n//% weight=2 color=#002050 icon=\"\\uf287\"\n//% advanced=true\nnamespace serial {\n    /**\n     * The string used to mark a new line, default is \\r\\n\n     */\n    export let NEW_LINE = \"\\r\\n\";\n    export let NEW_LINE_DELIMITER: Delimiters = Delimiters.NewLine;\n    let writeLinePadding = 32;\n\n    /**\n     * Print a line of text to the serial port\n     * @param value to send over serial\n     */\n    //% weight=90\n    //% help=serial/write-line blockGap=8\n    //% blockId=serial_writeline block=\"serial|write line %text\"\n    //% text.shadowOptions.toString=true\n    export function writeLine(text: string): void {\n        if (!text) text = \"\";\n        serial.writeString(text);\n        // pad data to the 32 byte boundary\n        // to ensure apps receive the packet\n        if (writeLinePadding > 0) {\n            let r = (writeLinePadding - (text.length + NEW_LINE.length) % writeLinePadding) % writeLinePadding;\n            for (let i = 0; i < r; ++i)\n                serial.writeString(\" \");\n        }\n        serial.writeString(NEW_LINE);\n    }\n\n    /**\n     * Sets the padding length for lines sent with \"write line\".\n     * @param length the number of bytes alignment, eg: 0\n     *\n     */\n    //% weight=1\n    //% help=serial/set-write-line-padding\n    //% blockId=serialWriteNewLinePadding block=\"serial set write line padding to $length\"\n    //% advanced=true\n    //% length.min=0 length.max=128\n    export function setWriteLinePadding(length: number) {\n        writeLinePadding = length | 0;\n    }\n\n    /**\n     * Print a numeric value to the serial port\n     */\n    //% help=serial/write-number\n    //% weight=89 blockGap=8\n    //% blockId=serial_writenumber block=\"serial|write number %value\"\n    export function writeNumber(value: number): void {\n        writeString(value.toString());\n    }\n\n    /**\n     * Print an array of numeric values as CSV to the serial port\n     */\n    //% help=serial/write-numbers\n    //% weight=86\n    //% blockId=serial_writenumbers block=\"serial|write numbers %values\"\n    export function writeNumbers(values: number[]): void {\n        if (!values) return;\n        for (let i = 0; i < values.length; ++i) {\n            if (i > 0) writeString(\",\");\n            writeNumber(values[i]);\n        }\n        writeLine(\"\")\n    }\n\n    /**\n     * Write a name:value pair as a line to the serial port.\n     * @param name name of the value stream, eg: x\n     * @param value to write\n     */\n    //% weight=88 blockGap=8\n    //% help=serial/write-value\n    //% blockId=serial_writevalue block=\"serial|write value %name|= %value\"\n    export function writeValue(name: string, value: number): void {\n        writeLine((name ? name + \":\" : \"\") + value);\n    }\n\n    /**\n     * Read a line of text from the serial port.\n     */\n    //% help=serial/read-line\n    //% blockId=serial_read_line block=\"serial|read line\"\n    //% weight=20 blockGap=8\n    export function readLine(): string {\n        return serial.readUntil(delimiters(NEW_LINE_DELIMITER));\n    }\n\n    /**\n     * Return the corresponding delimiter string\n     */\n    //% blockId=\"serial_delimiter_conv\" block=\"%del\"\n    //% weight=1 blockHidden=true\n    export function delimiters(del: Delimiters): string {\n        return String.fromCharCode(del as number);\n    }\n}\n","shims.d.ts":"// Auto-generated. Do not edit.\n\n\n    /**\n     * Creation, manipulation and display of LED images.\n     */\n    //% color=#7600A8 weight=31 icon=\"\\uf03e\"\n    //% advanced=true\ndeclare namespace images {\n\n    /**\n     * Creates an image that fits on the LED screen.\n     */\n    //% weight=75 help=images/create-image\n    //% blockId=device_build_image block=\"create image\"\n    //% parts=\"ledmatrix\" imageLiteral=1 shim=images::createImage\n    function createImage(leds: string): Image;\n\n    /**\n     * Creates an image with 2 frames.\n     */\n    //% weight=74 help=images/create-big-image\n    //% blockId=device_build_big_image block=\"create big image\" imageLiteral=2\n    //% parts=\"ledmatrix\" shim=images::createBigImage\n    function createBigImage(leds: string): Image;\n}\n\n\ndeclare interface Image {\n    /**\n     * Plots the image at a given column to the screen\n     */\n    //% help=images/plot-image\n    //% parts=\"ledmatrix\" xOffset.defl=0 shim=ImageMethods::plotImage\n    plotImage(xOffset?: int32): void;\n\n    /**\n     * Shows an frame from the image at offset ``x offset``.\n     * @param xOffset column index to start displaying the image\n     * @param interval time in milliseconds to pause after drawing\n     */\n    //% help=images/show-image weight=80 blockNamespace=images\n    //% blockId=device_show_image_offset block=\"show image %sprite(myImage)|at offset %offset ||and interval (ms) %interval\"\n    //%\n    //% blockGap=8 parts=\"ledmatrix\" async interval.defl=400 shim=ImageMethods::showImage\n    showImage(xOffset: int32, interval?: int32): void;\n\n    /**\n     * Draws the ``index``-th frame of the image on the screen.\n     * @param xOffset column index to start displaying the image\n     */\n    //% help=images/plot-frame weight=80\n    //% parts=\"ledmatrix\" shim=ImageMethods::plotFrame\n    plotFrame(xOffset: int32): void;\n\n    /**\n     * Scrolls an image .\n     * @param frameOffset x offset moved on each animation step, eg: 1, 2, 5\n     * @param interval time between each animation step in milli seconds, eg: 200\n     */\n    //% help=images/scroll-image weight=79 async blockNamespace=images\n    //% blockId=device_scroll_image\n    //% block=\"scroll image %sprite(myImage)|with offset %frameoffset|and interval (ms) %delay\"\n    //% blockGap=8 parts=\"ledmatrix\" shim=ImageMethods::scrollImage\n    scrollImage(frameOffset: int32, interval: int32): void;\n\n    /**\n     * Sets all pixels off.\n     */\n    //% help=images/clear\n    //% parts=\"ledmatrix\" shim=ImageMethods::clear\n    clear(): void;\n\n    /**\n     * Sets a specific pixel brightness at a given position\n     */\n    //%\n    //% parts=\"ledmatrix\" shim=ImageMethods::setPixelBrightness\n    setPixelBrightness(x: int32, y: int32, value: int32): void;\n\n    /**\n     * Gets the pixel brightness ([0..255]) at a given position\n     */\n    //%\n    //% parts=\"ledmatrix\" shim=ImageMethods::pixelBrightness\n    pixelBrightness(x: int32, y: int32): int32;\n\n    /**\n     * Gets the width in columns\n     */\n    //% help=functions/width shim=ImageMethods::width\n    width(): int32;\n\n    /**\n     * Gets the height in rows (always 5)\n     */\n    //% shim=ImageMethods::height\n    height(): int32;\n\n    /**\n     * Set a pixel state at position ``(x,y)``\n     * @param x pixel column\n     * @param y pixel row\n     * @param value pixel state\n     */\n    //% help=images/set-pixel\n    //% parts=\"ledmatrix\" shim=ImageMethods::setPixel\n    setPixel(x: int32, y: int32, value: boolean): void;\n\n    /**\n     * Get the pixel state at position ``(x,y)``\n     * @param x pixel column\n     * @param y pixel row\n     */\n    //% help=images/pixel\n    //% parts=\"ledmatrix\" shim=ImageMethods::pixel\n    pixel(x: int32, y: int32): boolean;\n\n    /**\n     * Show a particular frame of the image strip.\n     * @param frame image frame to show\n     */\n    //% weight=70 help=images/show-frame\n    //% parts=\"ledmatrix\" interval.defl=400 shim=ImageMethods::showFrame\n    showFrame(frame: int32, interval?: int32): void;\n}\n\n\n    /**\n     * Provides access to basic micro:bit functionality.\n     */\n    //% color=#1E90FF weight=116 icon=\"\\uf00a\"\ndeclare namespace basic {\n\n    /**\n     * Draws an image on the LED screen.\n     * @param leds the pattern of LED to turn on/off.\n     * @param interval time in milliseconds to pause after drawing.\n     */\n    //% help=basic/show-leds\n    //% weight=95 blockGap=8\n    //% imageLiteral=1 async\n    //% blockId=device_show_leds\n    //% block=\"show leds\" icon=\"\\uf00a\"\n    //% parts=\"ledmatrix\" interval.defl=400 shim=basic::showLeds\n    function showLeds(leds: string, interval?: int32): void;\n\n    /**\n     * Display text on the display, one character at a time. If the string fits on the screen (i.e. is one letter), does not scroll.\n     * @param text the text to scroll on the screen, eg: \"Hello!\"\n     * @param interval how fast to shift characters; eg: 150, 100, 200, -100\n     */\n    //% help=basic/show-string\n    //% weight=87 blockGap=16\n    //% block=\"show|string %text\"\n    //% async\n    //% blockId=device_print_message\n    //% parts=\"ledmatrix\"\n    //% text.shadowOptions.toString=true interval.defl=150 shim=basic::showString\n    function showString(text: string, interval?: int32): void;\n\n    /**\n     * Turn off all LEDs\n     */\n    //% help=basic/clear-screen weight=79\n    //% blockId=device_clear_display block=\"clear screen\"\n    //% parts=\"ledmatrix\" shim=basic::clearScreen\n    function clearScreen(): void;\n\n    /**\n     * Shows a sequence of LED screens as an animation.\n     * @param leds pattern of LEDs to turn on/off\n     * @param interval time in milliseconds between each redraw.\n     */\n    //% help=basic/show-animation imageLiteral=1 async\n    //% parts=\"ledmatrix\" interval.defl=400 shim=basic::showAnimation\n    function showAnimation(leds: string, interval?: int32): void;\n\n    /**\n     * Draws an image on the LED screen.\n     * @param leds pattern of LEDs to turn on/off\n     */\n    //% help=basic/plot-leds weight=80\n    //% parts=\"ledmatrix\" imageLiteral=1 shim=basic::plotLeds\n    function plotLeds(leds: string): void;\n\n    /**\n     * Repeats the code forever in the background. On each iteration, allows other codes to run.\n     * @param body code to execute\n     */\n    //% help=basic/forever weight=55 blockGap=16 blockAllowMultiple=1 afterOnStart=true\n    //% blockId=device_forever block=\"forever\" icon=\"\\uf01e\" shim=basic::forever\n    function forever(a: () => void): void;\n\n    /**\n     * Pause for the specified time in milliseconds\n     * @param ms how long to pause for, eg: 100, 200, 500, 1000, 2000\n     */\n    //% help=basic/pause weight=54\n    //% async block=\"pause (ms) %pause\" blockGap=16\n    //% blockId=device_pause icon=\"\\uf110\"\n    //% pause.shadow=timePicker shim=basic::pause\n    function pause(ms: int32): void;\n}\n\n\n\n    //% color=#D400D4 weight=111 icon=\"\\uf192\"\ndeclare namespace input {\n\n    /**\n     * Do something when a button (A, B or both A+B) is pushed down and released again.\n     * @param button the button that needs to be pressed\n     * @param body code to run when event is raised\n     */\n    //% help=input/on-button-pressed weight=85 blockGap=16\n    //% blockId=device_button_event block=\"on button|%NAME|pressed\"\n    //% parts=\"buttonpair\" shim=input::onButtonPressed\n    function onButtonPressed(button: Button, body: () => void): void;\n\n    /**\n     * Do something when when a gesture is done (like shaking the micro:bit).\n     * @param gesture the type of gesture to track, eg: Gesture.Shake\n     * @param body code to run when gesture is raised\n     */\n    //% help=input/on-gesture weight=84 blockGap=16\n    //% blockId=device_gesture_event block=\"on |%NAME\"\n    //% parts=\"accelerometer\"\n    //% NAME.fieldEditor=\"gestures\" NAME.fieldOptions.columns=4 shim=input::onGesture\n    function onGesture(gesture: Gesture, body: () => void): void;\n\n    /**\n     * Tests if a gesture is currently detected.\n     * @param gesture the type of gesture to detect, eg: Gesture.Shake\n     */\n    //% help=input/is-gesture weight=10 blockGap=8\n    //% blockId=deviceisgesture block=\"is %gesture gesture\"\n    //% parts=\"accelerometer\"\n    //% gesture.fieldEditor=\"gestures\" gesture.fieldOptions.columns=4 shim=input::isGesture\n    function isGesture(gesture: Gesture): boolean;\n\n    /**\n     * Do something when a pin is touched and released again (while also touching the GND pin).\n     * @param name the pin that needs to be pressed, eg: TouchPin.P0\n     * @param body the code to run when the pin is pressed\n     */\n    //% help=input/on-pin-pressed weight=83 blockGap=32\n    //% blockId=device_pin_event block=\"on pin %name|pressed\" shim=input::onPinPressed\n    function onPinPressed(name: TouchPin, body: () => void): void;\n\n    /**\n     * Do something when a pin is released.\n     * @param name the pin that needs to be released, eg: TouchPin.P0\n     * @param body the code to run when the pin is released\n     */\n    //% help=input/on-pin-released weight=6 blockGap=16\n    //% blockId=device_pin_released block=\"on pin %NAME|released\"\n    //% advanced=true shim=input::onPinReleased\n    function onPinReleased(name: TouchPin, body: () => void): void;\n\n    /**\n     * Get the button state (pressed or not) for ``A`` and ``B``.\n     * @param button the button to query the request, eg: Button.A\n     */\n    //% help=input/button-is-pressed weight=60\n    //% block=\"button|%NAME|is pressed\"\n    //% blockId=device_get_button2\n    //% icon=\"\\uf192\" blockGap=8\n    //% parts=\"buttonpair\" shim=input::buttonIsPressed\n    function buttonIsPressed(button: Button): boolean;\n\n    /**\n     * Get the pin state (pressed or not). Requires to hold the ground to close the circuit.\n     * @param name pin used to detect the touch, eg: TouchPin.P0\n     */\n    //% help=input/pin-is-pressed weight=58\n    //% blockId=\"device_pin_is_pressed\" block=\"pin %NAME|is pressed\"\n    //% blockGap=8 shim=input::pinIsPressed\n    function pinIsPressed(name: TouchPin): boolean;\n\n    /**\n     * Get the acceleration value in milli-gravitys (when the board is laying flat with the screen up, x=0, y=0 and z=-1024)\n     * @param dimension x, y, or z dimension, eg: Dimension.X\n     */\n    //% help=input/acceleration weight=58\n    //% blockId=device_acceleration block=\"acceleration (mg)|%NAME\" blockGap=8\n    //% parts=\"accelerometer\" shim=input::acceleration\n    function acceleration(dimension: Dimension): int32;\n\n    /**\n     * Reads the light level applied to the LED screen in a range from ``0`` (dark) to ``255`` bright.\n     */\n    //% help=input/light-level weight=57\n    //% blockId=device_get_light_level block=\"light level\" blockGap=8\n    //% parts=\"ledmatrix\" shim=input::lightLevel\n    function lightLevel(): int32;\n\n    /**\n     * Get the current compass heading in degrees.\n     */\n    //% help=input/compass-heading\n    //% weight=56\n    //% blockId=device_heading block=\"compass heading (°)\" blockGap=8\n    //% parts=\"compass\" shim=input::compassHeading\n    function compassHeading(): int32;\n\n    /**\n     * Gets the temperature in Celsius degrees (°C).\n     */\n    //% weight=55\n    //% help=input/temperature\n    //% blockId=device_temperature block=\"temperature (°C)\" blockGap=8\n    //% parts=\"thermometer\" shim=input::temperature\n    function temperature(): int32;\n\n    /**\n     * The pitch or roll of the device, rotation along the ``x-axis`` or ``y-axis``, in degrees.\n     * @param kind pitch or roll\n     */\n    //% help=input/rotation weight=52\n    //% blockId=device_get_rotation block=\"rotation (°)|%NAME\" blockGap=8\n    //% parts=\"accelerometer\" advanced=true shim=input::rotation\n    function rotation(kind: Rotation): int32;\n\n    /**\n     * Get the magnetic force value in ``micro-Teslas`` (``µT``). This function is not supported in the simulator.\n     * @param dimension the x, y, or z dimension, eg: Dimension.X\n     */\n    //% help=input/magnetic-force weight=54\n    //% blockId=device_get_magnetic_force block=\"magnetic force (µT)|%NAME\" blockGap=8\n    //% parts=\"compass\"\n    //% advanced=true shim=input::magneticForce\n    function magneticForce(dimension: Dimension): number;\n\n    /**\n     * Obsolete, compass calibration is automatic.\n     */\n    //% help=input/calibrate-compass advanced=true\n    //% blockId=\"input_compass_calibrate\" block=\"calibrate compass\"\n    //% weight=55 shim=input::calibrateCompass\n    function calibrateCompass(): void;\n\n    /**\n     * Sets the accelerometer sample range in gravities.\n     * @param range a value describe the maximum strengh of acceleration measured\n     */\n    //% help=input/set-accelerometer-range\n    //% blockId=device_set_accelerometer_range block=\"set accelerometer|range %range\"\n    //% weight=5\n    //% parts=\"accelerometer\"\n    //% advanced=true shim=input::setAccelerometerRange\n    function setAccelerometerRange(range: AcceleratorRange): void;\n}\n\n\n\n    //% weight=1 color=\"#333333\"\n    //% advanced=true\ndeclare namespace control {\n\n    /**\n     * Gets the number of milliseconds elapsed since power on.\n     */\n    //% help=control/millis weight=50\n    //% blockId=control_running_time block=\"millis (ms)\" shim=control::millis\n    function millis(): int32;\n\n    /**\n     * Gets current time in microseconds. Overflows every ~18 minutes.\n     */\n    //% shim=control::micros\n    function micros(): int32;\n\n    /**\n     * Schedules code that run in the background.\n     */\n    //% help=control/in-background blockAllowMultiple=1 afterOnStart=true\n    //% blockId=\"control_in_background\" block=\"run in background\" blockGap=8 shim=control::inBackground\n    function inBackground(a: () => void): void;\n\n    /**\n     * Blocks the calling thread until the specified event is raised.\n     */\n    //% help=control/wait-for-event async\n    //% blockId=control_wait_for_event block=\"wait for event|from %src|with value %value\" shim=control::waitForEvent\n    function waitForEvent(src: int32, value: int32): void;\n\n    /**\n     * Resets the BBC micro:bit.\n     */\n    //% weight=30 async help=control/reset blockGap=8\n    //% blockId=\"control_reset\" block=\"reset\" shim=control::reset\n    function reset(): void;\n\n    /**\n     * Blocks the current fiber for the given microseconds\n     * @param micros number of micro-seconds to wait. eg: 4\n     */\n    //% help=control/wait-micros weight=29 async\n    //% blockId=\"control_wait_us\" block=\"wait (µs)%micros\"\n    //% micros.min=0 micros.max=6000 shim=control::waitMicros\n    function waitMicros(micros: int32): void;\n\n    /**\n     * Raises an event in the event bus.\n     * @param src ID of the MicroBit Component that generated the event e.g. MICROBIT_ID_BUTTON_A.\n     * @param value Component specific code indicating the cause of the event.\n     * @param mode optional definition of how the event should be processed after construction (default is CREATE_AND_FIRE).\n     */\n    //% weight=21 blockGap=12 blockId=\"control_raise_event\" block=\"raise event|from source %src=control_event_source_id|with value %value=control_event_value_id\" blockExternalInputs=1\n    //% help=control/raise-event\n    //% mode.defl=1 shim=control::raiseEvent\n    function raiseEvent(src: int32, value: int32, mode?: EventCreationMode): void;\n\n    /**\n     * Registers an event handler.\n     */\n    //% weight=20 blockGap=8 blockId=\"control_on_event\" block=\"on event|from %src=control_event_source_id|with value %value=control_event_value_id\"\n    //% help=control/on-event\n    //% blockExternalInputs=1 flags.defl=0 shim=control::onEvent\n    function onEvent(src: int32, value: int32, handler: () => void, flags?: int32): void;\n\n    /**\n     * Gets the value of the last event executed on the bus\n     */\n    //% blockId=control_event_value\" block=\"event value\"\n    //% help=control/event-value\n    //% weight=18 shim=control::eventValue\n    function eventValue(): int32;\n\n    /**\n     * Gets the timestamp of the last event executed on the bus\n     */\n    //% blockId=control_event_timestamp\" block=\"event timestamp\"\n    //% help=control/event-timestamp\n    //% weight=19 blockGap=8 shim=control::eventTimestamp\n    function eventTimestamp(): int32;\n\n    /**\n     * Make a friendly name for the device based on its serial number\n     */\n    //% blockId=\"control_device_name\" block=\"device name\" weight=10 blockGap=8\n    //% help=control/device-name\n    //% advanced=true shim=control::deviceName\n    function deviceName(): string;\n\n    /**\n     * Returns the major version of the microbit\n     */\n    //% help=control/hardware-version shim=control::_hardwareVersion\n    function _hardwareVersion(): string;\n\n    /**\n     * Derive a unique, consistent serial number of this device from internal data.\n     */\n    //% blockId=\"control_device_serial_number\" block=\"device serial number\" weight=9\n    //% help=control/device-serial-number\n    //% advanced=true shim=control::deviceSerialNumber\n    function deviceSerialNumber(): int32;\n\n    /**\n     * Derive a unique, consistent 64-bit serial number of this device from internal data.\n     */\n    //% help=control/device-long-serial-number\n    //% advanced=true shim=control::deviceLongSerialNumber\n    function deviceLongSerialNumber(): Buffer;\n\n    /**\n     * Informs simulator/runtime of a MIDI message\n     * Internal function to support the simulator.\n     */\n    //% part=midioutput blockHidden=1 shim=control::__midiSend\n    function __midiSend(buffer: Buffer): void;\n\n    /**\n     *\n     */\n    //% shim=control::__log\n    function __log(priority: int32, text: string): void;\n\n    /**\n     * Allocates the next user notification event\n     */\n    //% help=control/allocate-notify-event shim=control::allocateNotifyEvent\n    function allocateNotifyEvent(): int32;\n\n    /** Write a message to DMESG debugging buffer. */\n    //% shim=control::dmesg\n    function dmesg(s: string): void;\n\n    /** Write a message and value (pointer) to DMESG debugging buffer. */\n    //% shim=control::dmesgPtr\n    function dmesgPtr(str: string, ptr: Object): void;\n}\ndeclare namespace control {\n\n    /**\n     * Force GC and dump basic information about heap.\n     */\n    //% shim=control::gc\n    function gc(): void;\n\n    /**\n     * Force GC and halt waiting for debugger to do a full heap dump.\n     */\n    //% shim=control::heapDump\n    function heapDump(): void;\n\n    /**\n     * Set flags used when connecting an external debugger.\n     */\n    //% shim=control::setDebugFlags\n    function setDebugFlags(flags: int32): void;\n\n    /**\n     * Record a heap snapshot to debug memory leaks.\n     */\n    //% shim=control::heapSnapshot\n    function heapSnapshot(): void;\n\n    /**\n     * Return true if profiling is enabled in the current build.\n     */\n    //% shim=control::profilingEnabled\n    function profilingEnabled(): boolean;\n}\n\n\n\n    //% color=#7600A8 weight=101 icon=\"\\uf205\"\ndeclare namespace led {\n\n    /**\n     * Turn on the specified LED using x, y coordinates (x is horizontal, y is vertical). (0,0) is upper left.\n     * @param x the horizontal coordinate of the LED starting at 0\n     * @param y the vertical coordinate of the LED starting at 0\n     */\n    //% help=led/plot weight=78\n    //% blockId=device_plot block=\"plot|x %x|y %y\" blockGap=8\n    //% parts=\"ledmatrix\"\n    //% x.min=0 x.max=4 y.min=0 y.max=4\n    //% x.fieldOptions.precision=1 y.fieldOptions.precision=1 shim=led::plot\n    function plot(x: int32, y: int32): void;\n\n    /**\n     * Turn on the specified LED with specific brightness using x, y coordinates (x is horizontal, y is vertical). (0,0) is upper left.\n     * @param x the horizontal coordinate of the LED starting at 0\n     * @param y the vertical coordinate of the LED starting at 0\n     * @param brightness the brightness from 0 (off) to 255 (bright), eg:255\n     */\n    //% help=led/plot-brightness weight=78\n    //% blockId=device_plot_brightness block=\"plot|x %x|y %y|brightness %brightness\" blockGap=8\n    //% parts=\"ledmatrix\"\n    //% x.min=0 x.max=4 y.min=0 y.max=4 brightness.min=0 brightness.max=255\n    //% x.fieldOptions.precision=1 y.fieldOptions.precision=1\n    //% advanced=true shim=led::plotBrightness\n    function plotBrightness(x: int32, y: int32, brightness: int32): void;\n\n    /**\n     * Turn off the specified LED using x, y coordinates (x is horizontal, y is vertical). (0,0) is upper left.\n     * @param x the horizontal coordinate of the LED\n     * @param y the vertical coordinate of the LED\n     */\n    //% help=led/unplot weight=77\n    //% blockId=device_unplot block=\"unplot|x %x|y %y\" blockGap=8\n    //% parts=\"ledmatrix\"\n    //% x.min=0 x.max=4 y.min=0 y.max=4\n    //% x.fieldOptions.precision=1 y.fieldOptions.precision=1 shim=led::unplot\n    function unplot(x: int32, y: int32): void;\n\n    /**\n     * Get the brightness state of the specified LED using x, y coordinates. (0,0) is upper left.\n     * @param x the horizontal coordinate of the LED\n     * @param y the vertical coordinate of the LED\n     */\n    //% help=led/point-brightness weight=76\n    //% blockId=device_point_brightness block=\"point|x %x|y %y brightness\"\n    //% parts=\"ledmatrix\"\n    //% x.min=0 x.max=4 y.min=0 y.max=4\n    //% x.fieldOptions.precision=1 y.fieldOptions.precision=1\n    //% advanced=true shim=led::pointBrightness\n    function pointBrightness(x: int32, y: int32): int32;\n\n    /**\n     * Get the screen brightness from 0 (off) to 255 (full bright).\n     */\n    //% help=led/brightness weight=60\n    //% blockId=device_get_brightness block=\"brightness\" blockGap=8\n    //% parts=\"ledmatrix\"\n    //% advanced=true shim=led::brightness\n    function brightness(): int32;\n\n    /**\n     * Set the screen brightness from 0 (off) to 255 (full bright).\n     * @param value the brightness value, eg:255, 127, 0\n     */\n    //% help=led/set-brightness weight=59\n    //% blockId=device_set_brightness block=\"set brightness %value\"\n    //% parts=\"ledmatrix\"\n    //% advanced=true\n    //% value.min=0 value.max=255 shim=led::setBrightness\n    function setBrightness(value: int32): void;\n\n    /**\n     * Cancels the current animation and clears other pending animations.\n     */\n    //% weight=50 help=led/stop-animation\n    //% blockId=device_stop_animation block=\"stop animation\"\n    //% parts=\"ledmatrix\"\n    //% advanced=true shim=led::stopAnimation\n    function stopAnimation(): void;\n\n    /**\n     * Sets the display mode between black and white and greyscale for rendering LEDs.\n     * @param mode mode the display mode in which the screen operates\n     */\n    //% weight=1 help=led/set-display-mode\n    //% parts=\"ledmatrix\" advanced=true weight=1\n    //% blockId=\"led_set_display_mode\" block=\"set display mode $mode\" shim=led::setDisplayMode\n    function setDisplayMode(mode: DisplayMode): void;\n\n    /**\n     * Gets the current display mode\n     */\n    //% weight=1 parts=\"ledmatrix\" advanced=true shim=led::displayMode\n    function displayMode(): DisplayMode;\n\n    /**\n     * Turns on or off the display\n     */\n    //% help=led/enable blockId=device_led_enable block=\"led enable %on\"\n    //% advanced=true parts=\"ledmatrix\" shim=led::enable\n    function enable(on: boolean): void;\n\n    /**\n     * Takes a screenshot of the LED screen and returns an image.\n     */\n    //% help=led/screenshot\n    //% parts=\"ledmatrix\" shim=led::screenshot\n    function screenshot(): Image;\n}\ndeclare namespace music {\n\n    /**\n     * Set the default output volume of the sound synthesizer.\n     * @param volume the volume 0...255\n     */\n    //% blockId=synth_set_volume block=\"set volume %volume\"\n    //% volume.min=0 volume.max=255\n    //%\n    //% help=music/set-volume\n    //% weight=70\n    //% group=\"Volume\"\n    //% blockGap=8 volume.defl=127 shim=music::setVolume\n    function setVolume(volume?: int32): void;\n\n    /**\n     * Returns the current output volume of the sound synthesizer.\n     */\n    //% blockId=synth_get_volume block=\"volume\"\n    //% help=music/volume\n    //% weight=69\n    //% group=\"Volume\"\n    //% blockGap=8 shim=music::volume\n    function volume(): int32;\n\n    /**\n     * Turn the built-in speaker on or off.\n     * Disabling the speaker resets the sound pin to the default of P0.\n     * @param enabled whether the built-in speaker is enabled in addition to the sound pin\n     */\n    //% blockId=music_set_built_in_speaker_enable block=\"set built-in speaker $enabled\"\n    //% group=\"micro:bit (V2)\"\n    //% parts=builtinspeaker\n    //% help=music/set-built-in-speaker-enabled\n    //% enabled.shadow=toggleOnOff\n    //% weight=0 shim=music::setBuiltInSpeakerEnabled\n    function setBuiltInSpeakerEnabled(enabled: boolean): void;\n\n    /**\n     * Check whether any sound is being played, no matter the source\n     */\n    //% blockId=music_sound_is_playing block=\"sound is playing\"\n    //% group=\"micro:bit (V2)\"\n    //% help=music/is-sound-playing\n    //% weight=0 shim=music::isSoundPlaying\n    function isSoundPlaying(): boolean;\n\n    /**\n     * Defines an optional sample level to generate during periods of silence.\n     **/\n    //% group=\"micro:bit (V2)\"\n    //% help=music/set-silence-level\n    //% level.min=0\n    //% level.max=1024\n    //%\n    //% weight=1 level.defl=0 shim=music::setSilenceLevel\n    function setSilenceLevel(level?: int32): void;\n}\ndeclare namespace pins {\n\n    /**\n     * Read the specified pin or connector as either 0 or 1\n     * @param name pin to read from, eg: DigitalPin.P0\n     */\n    //% help=pins/digital-read-pin weight=30\n    //% blockId=device_get_digital_pin block=\"digital read|pin %name\" blockGap=8\n    //% name.shadow=digital_pin_shadow shim=pins::digitalReadPin\n    function digitalReadPin(name: int32): int32;\n\n    /**\n     * Set a pin or connector value to either 0 or 1.\n     * @param name pin to write to, eg: DigitalPin.P0\n     * @param value value to set on the pin, 1 eg,0\n     */\n    //% help=pins/digital-write-pin weight=29\n    //% blockId=device_set_digital_pin block=\"digital write|pin %name|to %value\"\n    //% value.min=0 value.max=1\n    //% name.shadow=digital_pin_shadow shim=pins::digitalWritePin\n    function digitalWritePin(name: int32, value: int32): void;\n\n    /**\n     * Read the connector value as analog, that is, as a value comprised between 0 and 1023.\n     * @param name pin to write to, eg: AnalogPin.P0\n     */\n    //% help=pins/analog-read-pin weight=25\n    //% blockId=device_get_analog_pin block=\"analog read|pin %name\" blockGap=\"8\"\n    //% name.shadow=analog_read_write_pin_shadow shim=pins::analogReadPin\n    function analogReadPin(name: int32): int32;\n\n    /**\n     * Set the connector value as analog. Value must be comprised between 0 and 1023.\n     * @param name pin name to write to, eg: AnalogPin.P0\n     * @param value value to write to the pin between ``0`` and ``1023``. eg:1023,0\n     */\n    //% help=pins/analog-write-pin weight=24\n    //% blockId=device_set_analog_pin block=\"analog write|pin %name|to %value\" blockGap=8\n    //% value.min=0 value.max=1023\n    //% name.shadow=analog_pin_shadow shim=pins::analogWritePin\n    function analogWritePin(name: int32, value: int32): void;\n\n    /**\n     * Configure the pulse-width modulation (PWM) period of the analog output in microseconds.\n     * If this pin is not configured as an analog output (using `analog write pin`), the operation has no effect.\n     * @param name analog pin to set period to, eg: AnalogPin.P0\n     * @param micros period in microseconds. eg:20000\n     */\n    //% help=pins/analog-set-period weight=23 blockGap=8\n    //% blockId=device_set_analog_period block=\"analog set period|pin %pin|to (µs)%micros\"\n    //% pin.shadow=analog_pin_shadow shim=pins::analogSetPeriod\n    function analogSetPeriod(name: int32, micros: int32): void;\n\n    /**\n     * Configure the pin as a digital input and generate an event when the pin is pulsed either high or low.\n     * @param name digital pin to register to, eg: DigitalPin.P0\n     * @param pulse the value of the pulse, eg: PulseValue.High\n     */\n    //% help=pins/on-pulsed advanced=true\n    //% blockId=pins_on_pulsed block=\"on|pin %pin|pulsed %pulse\"\n    //% pin.fieldEditor=\"gridpicker\" pin.fieldOptions.columns=4\n    //% pin.fieldOptions.tooltips=\"false\" pin.fieldOptions.width=\"250\"\n    //% group=\"Pulse\"\n    //% weight=25\n    //% blockGap=8 shim=pins::onPulsed\n    function onPulsed(name: DigitalPin, pulse: PulseValue, body: () => void): void;\n\n    /**\n     * Get the duration of the last pulse in microseconds. This function should be called from a ``onPulsed`` handler.\n     */\n    //% help=pins/pulse-duration advanced=true\n    //% blockId=pins_pulse_duration block=\"pulse duration (µs)\"\n    //% group=\"Pulse\"\n    //% weight=24\n    //% blockGap=8 shim=pins::pulseDuration\n    function pulseDuration(): int32;\n\n    /**\n     * Return the duration of a pulse at a pin in microseconds.\n     * @param name the pin which measures the pulse, eg: DigitalPin.P0\n     * @param value the value of the pulse, eg: PulseValue.High\n     * @param maximum duration in microseconds\n     */\n    //% blockId=\"pins_pulse_in\" block=\"pulse in (µs)|pin %name|pulsed %value\"\n    //% advanced=true\n    //% help=pins/pulse-in\n    //% name.shadow=digital_pin_shadow\n    //% group=\"Pulse\"\n    //% weight=23\n    //% blockGap=8 maxDuration.defl=2000000 shim=pins::pulseIn\n    function pulseIn(name: int32, value: PulseValue, maxDuration?: int32): int32;\n\n    /**\n     * Write a value to the servo, controlling the shaft accordingly. On a standard servo, this will set the angle of the shaft (in degrees), moving the shaft to that orientation. On a continuous rotation servo, this will set the speed of the servo (with ``0`` being full-speed in one direction, ``180`` being full speed in the other, and a value near ``90`` being no movement).\n     * @param name pin to write to, eg: AnalogPin.P0\n     * @param value angle or rotation speed, eg:180,90,0\n     */\n    //% help=pins/servo-write-pin weight=20\n    //% blockId=device_set_servo_pin block=\"servo write|pin %name|to %value\" blockGap=8\n    //% parts=microservo trackArgs=0\n    //% value.min=0 value.max=180\n    //% name.shadow=analog_pin_shadow\n    //% group=\"Servo\" shim=pins::servoWritePin\n    function servoWritePin(name: int32, value: int32): void;\n\n    /**\n     * Specifies that a continuous servo is connected.\n     */\n    //% shim=pins::servoSetContinuous\n    function servoSetContinuous(name: int32, value: boolean): void;\n\n    /**\n     * Configure the IO pin as an analog/pwm output and set a pulse width. The period is 20 ms period and the pulse width is set based on the value given in **microseconds** or `1/1000` milliseconds.\n     * @param name pin name\n     * @param micros pulse duration in microseconds, eg:1500\n     */\n    //% help=pins/servo-set-pulse weight=19\n    //% blockId=device_set_servo_pulse block=\"servo set pulse|pin %value|to (µs) %micros\"\n    //% value.shadow=analog_pin_shadow\n    //% group=\"Servo\" shim=pins::servoSetPulse\n    function servoSetPulse(name: int32, micros: int32): void;\n\n    /**\n     * Set the pin used when using analog pitch or music.\n     * @param name pin to modulate pitch from\n     */\n    //% blockId=device_analog_set_pitch_pin block=\"analog set pitch pin %name\"\n    //% help=pins/analog-set-pitch-pin advanced=true\n    //% name.shadow=analog_pin_shadow\n    //% group=\"Pins\"\n    //% weight=12\n    //% blockGap=8 shim=pins::analogSetPitchPin\n    function analogSetPitchPin(name: int32): void;\n\n    /**\n     * Sets the volume on the pitch pin\n     * @param volume the intensity of the sound from 0..255\n     */\n    //% blockId=device_analog_set_pitch_volume block=\"analog set pitch volume $volume\"\n    //% help=pins/analog-set-pitch-volume weight=3 advanced=true\n    //% volume.min=0 volume.max=255\n    //% deprecated shim=pins::analogSetPitchVolume\n    function analogSetPitchVolume(volume: int32): void;\n\n    /**\n     * Gets the volume the pitch pin from 0..255\n     */\n    //% blockId=device_analog_pitch_volume block=\"analog pitch volume\"\n    //% help=pins/analog-pitch-volume weight=3 advanced=true\n    //% deprecated shim=pins::analogPitchVolume\n    function analogPitchVolume(): int32;\n\n    /**\n     * Send a pulse-width modulation (PWM) signal to the current pitch pin. Use `analog set pitch pin` to define the pitch pin.\n     * @param frequency frequency to modulate in Hz.\n     * @param ms duration of the pitch in milliseconds.\n     */\n    //% blockId=device_analog_pitch block=\"analog pitch %frequency|for (ms) %ms\"\n    //% help=pins/analog-pitch async advanced=true\n    //% group=\"Pins\"\n    //% weight=14\n    //% blockGap=8 shim=pins::analogPitch\n    function analogPitch(frequency: int32, ms: int32): void;\n\n    /**\n     * Configure the pull direction of of a pin.\n     * @param name pin to set the pull mode on, eg: DigitalPin.P0\n     * @param pull one of the mbed pull configurations, eg: PinPullMode.PullUp\n     */\n    //% help=pins/set-pull advanced=true\n    //% blockId=device_set_pull block=\"set pull|pin %pin|to %pull\"\n    //% pin.shadow=digital_pin_shadow\n    //% group=\"Pins\"\n    //% weight=15\n    //% blockGap=8 shim=pins::setPull\n    function setPull(name: int32, pull: PinPullMode): void;\n\n    /**\n     * Configure the events emitted by this pin. Events can be subscribed to\n     * using ``control.onEvent()``.\n     * @param name pin to set the event mode on, eg: DigitalPin.P0\n     * @param type the type of events for this pin to emit, eg: PinEventType.Edge\n     */\n    //% help=pins/set-events advanced=true\n    //% blockId=device_set_pin_events block=\"set pin %pin|to emit %type|events\"\n    //% pin.shadow=digital_pin_shadow\n    //% group=\"Pins\"\n    //% weight=13\n    //% blockGap=8 shim=pins::setEvents\n    function setEvents(name: int32, type: PinEventType): void;\n\n    /**\n     * Create a new zero-initialized buffer.\n     * @param size number of bytes in the buffer\n     */\n    //% shim=pins::createBuffer\n    function createBuffer(size: int32): Buffer;\n\n    /**\n     * Set the matrix width for Neopixel strip (already assigned to a pin).\n     * Should be used in conjunction with `set matrix width` from Neopixel package.\n     * @param name pin of Neopixel strip, eg: DigitalPin.P1\n     * @param value width of matrix (at least ``2``)\n     */\n    //% help=pins/neopixel-matrix-width advanced=true\n    //% blockId=pin_neopixel_matrix_width block=\"neopixel matrix width|pin %pin %width\"\n    //% pin.shadow=digital_pin_shadow\n    //% width.min=2\n    //% group=\"Pins\"\n    //% weight=11\n    //% blockGap=8 width.defl=5 shim=pins::setMatrixWidth\n    function setMatrixWidth(pin: int32, width?: int32): void;\n\n    /**\n     * Read `size` bytes from a 7-bit I2C `address`.\n     */\n    //% repeat.defl=0 shim=pins::i2cReadBuffer\n    function i2cReadBuffer(address: int32, size: int32, repeat?: boolean): Buffer;\n\n    /**\n     * Write bytes to a 7-bit I2C `address`.\n     */\n    //% repeat.defl=0 shim=pins::i2cWriteBuffer\n    function i2cWriteBuffer(address: int32, buf: Buffer, repeat?: boolean): int32;\n\n    /**\n     * Write to the SPI slave and return the response\n     * @param value Data to be sent to the SPI slave\n     */\n    //% help=pins/spi-write advanced=true\n    //% blockId=spi_write block=\"spi write %value\"\n    //% group=\"SPI\"\n    //% blockGap=8\n    //% weight=53 shim=pins::spiWrite\n    function spiWrite(value: int32): int32;\n\n    /**\n     * Write to and read from the SPI slave at the same time\n     * @param command Data to be sent to the SPI slave (can be null)\n     * @param response Data received from the SPI slave (can be null)\n     */\n    //% help=pins/spi-transfer argsNullable shim=pins::spiTransfer\n    function spiTransfer(command: Buffer, response: Buffer): void;\n\n    /**\n     * Set the SPI frequency\n     * @param frequency the clock frequency, eg: 1000000\n     */\n    //% help=pins/spi-frequency advanced=true\n    //% blockId=spi_frequency block=\"spi frequency %frequency\"\n    //% group=\"SPI\"\n    //% blockGap=8\n    //% weight=55 shim=pins::spiFrequency\n    function spiFrequency(frequency: int32): void;\n\n    /**\n     * Set the SPI bits and mode\n     * @param bits the number of bits, eg: 8\n     * @param mode the mode, eg: 3\n     */\n    //% help=pins/spi-format advanced=true\n    //% blockId=spi_format block=\"spi format|bits %bits|mode %mode\"\n    //% group=\"SPI\"\n    //% blockGap=8\n    //% weight=54 shim=pins::spiFormat\n    function spiFormat(bits: int32, mode: int32): void;\n\n    /**\n     * Set the MOSI, MISO, SCK pins used by the SPI connection\n     *\n     */\n    //% help=pins/spi-pins advanced=true\n    //% blockId=spi_pins block=\"spi set pins|MOSI %mosi|MISO %miso|SCK %sck\"\n    //% mosi.shadow=digital_pin_shadow\n    //% miso.shadow=digital_pin_shadow\n    //% sck.shadow=digital_pin_shadow\n    //% group=\"SPI\"\n    //% blockGap=8\n    //% weight=51 shim=pins::spiPins\n    function spiPins(mosi: int32, miso: int32, sck: int32): void;\n\n    /**\n     * Mounts a push button on the given pin\n     */\n    //% help=pins/push-button advanced=true shim=pins::pushButton\n    function pushButton(pin: int32): void;\n\n    /**\n     * Set the pin used when producing sounds and melodies. Default is P0.\n     * @param name pin to modulate pitch from\n     */\n    //% blockId=pin_set_audio_pin block=\"set audio pin $name\"\n    //% help=pins/set-audio-pin\n    //% name.shadow=digital_pin_shadow\n    //% weight=1\n    //% blockGap=8 shim=pins::setAudioPin\n    function setAudioPin(name: int32): void;\n\n    /**\n     * Sets whether or not audio will be output using a pin on the edge\n     * connector.\n     */\n    //% blockId=pin_set_audio_pin_enabled\n    //% block=\"set audio pin enabled $enabled\"\n    //% weight=0 help=pins/set-audio-pin-enabled shim=pins::setAudioPinEnabled\n    function setAudioPinEnabled(enabled: boolean): void;\n}\n\n\n\n    //% weight=2 color=#002050 icon=\"\\uf287\"\n    //% advanced=true\ndeclare namespace serial {\n\n    /**\n     * Read a line of text from the serial port and return the buffer when the delimiter is met.\n     * @param delimiter text delimiter that separates each text chunk\n     */\n    //% help=serial/read-until\n    //% blockId=serial_read_until block=\"serial|read until %delimiter=serial_delimiter_conv\"\n    //% weight=19 shim=serial::readUntil\n    function readUntil(delimiter: string): string;\n\n    /**\n     * Read the buffered received data as a string\n     */\n    //% help=serial/read-string\n    //% blockId=serial_read_buffer block=\"serial|read string\"\n    //% weight=18 shim=serial::readString\n    function readString(): string;\n\n    /**\n     * Register an event to be fired when one of the delimiter is matched.\n     * @param delimiters the characters to match received characters against.\n     */\n    //% help=serial/on-data-received\n    //% weight=18 blockId=serial_on_data_received block=\"serial|on data received %delimiters=serial_delimiter_conv\" shim=serial::onDataReceived\n    function onDataReceived(delimiters: string, body: () => void): void;\n\n    /**\n     * Send a piece of text through the serial connection.\n     */\n    //% help=serial/write-string\n    //% weight=87 blockGap=8\n    //% blockId=serial_writestring block=\"serial|write string %text\"\n    //% text.shadowOptions.toString=true shim=serial::writeString\n    function writeString(text: string): void;\n\n    /**\n     * Send a buffer through serial connection\n     */\n    //% blockId=serial_writebuffer block=\"serial|write buffer %buffer=serial_readbuffer\"\n    //% help=serial/write-buffer advanced=true weight=6 shim=serial::writeBuffer\n    function writeBuffer(buffer: Buffer): void;\n\n    /**\n     * Read multiple characters from the receive buffer. \n     * If length is positive, pauses until enough characters are present.\n     * @param length default buffer length\n     */\n    //% blockId=serial_readbuffer block=\"serial|read buffer %length\"\n    //% help=serial/read-buffer advanced=true weight=5 shim=serial::readBuffer\n    function readBuffer(length: int32): Buffer;\n\n    /**\n     * Set the serial input and output to use pins instead of the USB connection.\n     * @param tx the new transmission pin, eg: SerialPin.P0\n     * @param rx the new reception pin, eg: SerialPin.P1\n     * @param rate the new baud rate. eg: 115200\n     */\n    //% weight=10\n    //% help=serial/redirect\n    //% blockId=serial_redirect block=\"serial|redirect to|TX %tx|RX %rx|at baud rate %rate\"\n    //% blockExternalInputs=1\n    //% tx.fieldEditor=\"gridpicker\" tx.fieldOptions.columns=3\n    //% tx.fieldOptions.tooltips=\"false\"\n    //% rx.fieldEditor=\"gridpicker\" rx.fieldOptions.columns=3\n    //% rx.fieldOptions.tooltips=\"false\"\n    //% blockGap=8 shim=serial::redirect\n    function redirect(tx: SerialPin, rx: SerialPin, rate: BaudRate): void;\n\n    /**\n    Set the baud rate of the serial port\n     */\n    //% weight=10\n    //% blockId=serial_setbaudrate block=\"serial|set baud rate %rate\"\n    //% blockGap=8 inlineInputMode=inline\n    //% help=serial/set-baud-rate\n    //% group=\"Configuration\" advanced=true shim=serial::setBaudRate\n    function setBaudRate(rate: BaudRate): void;\n\n    /**\n     * Direct the serial input and output to use the USB connection.\n     */\n    //% weight=9 help=serial/redirect-to-usb\n    //% blockId=serial_redirect_to_usb block=\"serial|redirect to USB\" shim=serial::redirectToUSB\n    function redirectToUSB(): void;\n\n    /**\n     * Sets the size of the RX buffer in bytes\n     * @param size length of the rx buffer in bytes, eg: 32\n     */\n    //% help=serial/set-rx-buffer-size\n    //% blockId=serialSetRxBufferSize block=\"serial set rx buffer size to $size\"\n    //% advanced=true shim=serial::setRxBufferSize\n    function setRxBufferSize(size: uint8): void;\n\n    /**\n     * Sets the size of the TX buffer in bytes\n     * @param size length of the tx buffer in bytes, eg: 32\n     */\n    //% help=serial/set-tx-buffer-size\n    //% blockId=serialSetTxBufferSize block=\"serial set tx buffer size to $size\"\n    //% advanced=true shim=serial::setTxBufferSize\n    function setTxBufferSize(size: uint8): void;\n\n    /** Send DMESG debug buffer over serial. */\n    //% shim=serial::writeDmesg\n    function writeDmesg(): void;\n}\n\n\n\n    //% indexerGet=BufferMethods::getByte indexerSet=BufferMethods::setByte\ndeclare interface Buffer {\n    /**\n     * Reads an unsigned byte at a particular location\n     */\n    //% shim=BufferMethods::getUint8\n    getUint8(off: int32): int32;\n\n    /**\n     * Returns false when the buffer can be written to.\n     */\n    //% shim=BufferMethods::isReadOnly\n    isReadOnly(): boolean;\n\n    /**\n     * Writes an unsigned byte at a particular location\n     */\n    //% shim=BufferMethods::setUint8\n    setUint8(off: int32, v: int32): void;\n\n    /**\n     * Write a number in specified format in the buffer.\n     */\n    //% shim=BufferMethods::setNumber\n    setNumber(format: NumberFormat, offset: int32, value: number): void;\n\n    /**\n     * Read a number in specified format from the buffer.\n     */\n    //% shim=BufferMethods::getNumber\n    getNumber(format: NumberFormat, offset: int32): number;\n\n    /** Returns the length of a Buffer object. */\n    //% property shim=BufferMethods::length\n    length: int32;\n\n    /**\n     * Fill (a fragment) of the buffer with given value.\n     */\n    //% offset.defl=0 length.defl=-1 shim=BufferMethods::fill\n    fill(value: int32, offset?: int32, length?: int32): void;\n\n    /**\n     * Return a copy of a fragment of a buffer.\n     */\n    //% offset.defl=0 length.defl=-1 shim=BufferMethods::slice\n    slice(offset?: int32, length?: int32): Buffer;\n\n    /**\n     * Shift buffer left in place, with zero padding.\n     * @param offset number of bytes to shift; use negative value to shift right\n     * @param start start offset in buffer. Default is 0.\n     * @param length number of elements in buffer. If negative, length is set as the buffer length minus\n     * start. eg: -1\n     */\n    //% start.defl=0 length.defl=-1 shim=BufferMethods::shift\n    shift(offset: int32, start?: int32, length?: int32): void;\n\n    /**\n     * Convert a buffer to string assuming UTF8 encoding\n     */\n    //% shim=BufferMethods::toString\n    toString(): string;\n\n    /**\n     * Convert a buffer to its hexadecimal representation.\n     */\n    //% shim=BufferMethods::toHex\n    toHex(): string;\n\n    /**\n     * Rotate buffer left in place.\n     * @param offset number of bytes to shift; use negative value to shift right\n     * @param start start offset in buffer. Default is 0.\n     * @param length number of elements in buffer. If negative, length is set as the buffer length minus\n     * start. eg: -1\n     */\n    //% start.defl=0 length.defl=-1 shim=BufferMethods::rotate\n    rotate(offset: int32, start?: int32, length?: int32): void;\n\n    /**\n     * Write contents of `src` at `dstOffset` in current buffer.\n     */\n    //% shim=BufferMethods::write\n    write(dstOffset: int32, src: Buffer): void;\n\n    /**\n     * Compute k-bit FNV-1 non-cryptographic hash of the buffer.\n     */\n    //% shim=BufferMethods::hash\n    hash(bits: int32): uint32;\n}\ndeclare namespace control {\n\n    /**\n     * Create a new zero-initialized buffer.\n     * @param size number of bytes in the buffer\n     */\n    //% deprecated=1 shim=control::createBuffer\n    function createBuffer(size: int32): Buffer;\n\n    /**\n     * Create a new buffer with UTF8-encoded string\n     * @param str the string to put in the buffer\n     */\n    //% deprecated=1 shim=control::createBufferFromUTF8\n    function createBufferFromUTF8(str: string): Buffer;\n}\ndeclare namespace light {\n\n    /**\n     * Sends a color buffer to a light strip\n     **/\n    //% advanced=true shim=light::sendWS2812Buffer\n    function sendWS2812Buffer(buf: Buffer, pin: int32): void;\n\n    /**\n     * Sends a color buffer to a light strip\n     **/\n    //% advanced=true shim=light::sendWS2812BufferWithBrightness\n    function sendWS2812BufferWithBrightness(buf: Buffer, pin: int32, brightness: int32): void;\n\n    /**\n     * Sets the light mode of a pin\n     **/\n    //% advanced=true\n    //% shim=light::setMode\n    function setMode(pin: int32, mode: int32): void;\n}\ndeclare namespace input {\n\n    /**\n     * Do something when the logo is touched and released again.\n     * @param body the code to run when the logo is pressed\n     */\n    //% weight=83 blockGap=32\n    //% blockId=input_logo_event block=\"on logo $action\"\n    //% group=\"micro:bit (V2)\"\n    //% parts=\"logotouch\"\n    //% help=\"input/on-logo-event\" shim=input::onLogoEvent\n    function onLogoEvent(action: TouchButtonEvent, body: () => void): void;\n\n    /**\n     * Get the logo state (pressed or not).\n     */\n    //% weight=58\n    //% blockId=\"input_logo_is_pressed\" block=\"logo is pressed\"\n    //% blockGap=8\n    //% group=\"micro:bit (V2)\"\n    //% parts=\"logotouch\"\n    //% help=\"input/logo-is-pressed\" shim=input::logoIsPressed\n    function logoIsPressed(): boolean;\n}\ndeclare namespace pins {\n\n    /**\n     * Configure the touch detection for the pins and logo.\n     * P0, P1, P2 use resistive touch by default.\n     * The logo uses capacitative touch by default.\n     * @param name target to change the touch mode for\n     * @param mode the touch mode to use\n     */\n    //% weight=60\n    //% blockId=device_touch_set_type block=\"set %name to touch mode %mode\"\n    //% advanced=true\n    //% group=\"micro:bit (V2)\"\n    //% help=pins/touch-set-mode shim=pins::touchSetMode\n    function touchSetMode(name: TouchTarget, mode: TouchTargetMode): void;\n}\ndeclare namespace music {\n\n    /**\n     * Internal use only\n     **/\n    //% async shim=music::__playSoundExpression\n    function __playSoundExpression(nodes: string, waitTillDone: boolean): void;\n\n    /**\n     * Internal use only\n     */\n    //% shim=music::__stopSoundExpressions\n    function __stopSoundExpressions(): void;\n}\n\n// Auto-generated. Do not edit. Really.\n","soundexpressions.cpp":"#include \"pxt.h\"\r\n\r\nnamespace music {\r\n    /**\r\n     * Internal use only\r\n     **/\r\n    //% async\r\n    void __playSoundExpression(String nodes, bool waitTillDone) {\r\n#if MICROBIT_CODAL\r\n        if (waitTillDone)\r\n            uBit.audio.soundExpressions.play(MSTR(nodes));\r\n        else\r\n            uBit.audio.soundExpressions.playAsync(MSTR(nodes));\r\n#else\r\n        target_panic(PANIC_VARIANT_NOT_SUPPORTED);\r\n#endif\r\n    }\r\n\r\n    /**\r\n    * Internal use only\r\n    */\r\n    //% \r\n    void __stopSoundExpressions() {\r\n#if MICROBIT_CODAL\r\n        uBit.audio.soundExpressions.stop();\r\n#endif\r\n    }\r\n}","soundexpressions.ts":"/**\n * A sound expression.\n */\n//% fixedInstances\n//% blockNamespace=music\n//% group=\"micro:bit (V2)\"\nclass SoundExpression extends music.Playable {\n    constructor(private notes: string) {\n        super()\n    }\n\n    _play(mode: music.PlaybackMode) {\n        if (mode === music.PlaybackMode.InBackground) {\n            this.play();\n        } else if (mode === music.PlaybackMode.UntilDone) {\n            this.playUntilDone();\n        } else {\n            this.loop();\n        }\n    }\n\n    /**\n     * Starts to play a sound expression.\n     */\n    //% block=\"play sound $this\"\n    //% weight=80\n    //% blockGap=8\n    //% help=music/play\n    //% group=\"micro:bit (V2)\"\n    //% parts=builtinspeaker\n    //% deprecated=1\n    play() {\n        music.__playSoundExpression(this.notes, false)\n    }\n\n    /**\n     * Plays a sound expression until finished\n     */\n    //% block=\"play sound $this until done\"\n    //% weight=81\n    //% blockGap=8\n    //% help=music/play-until-done\n    //% group=\"micro:bit (V2)\"\n    //% parts=builtinspeaker\n    //% deprecated=1\n    playUntilDone() {\n        music.__playSoundExpression(this.notes, true)\n    }\n\n    getNotes() {\n        return this.notes;\n    }\n}\n\nenum WaveShape {\n    //% block=\"sine\"\n    Sine = 0,\n    //% block=\"sawtooth\"\n    Sawtooth = 1,\n    //% block=\"triangle\"\n    Triangle = 2,\n    //% block=\"square\"\n    Square = 3,\n    //% block=\"noise\"\n    Noise = 4\n}\n\nenum InterpolationCurve {\n    //% block=\"linear\"\n    Linear,\n    //% block=\"curve\"\n    Curve,\n    //% block=\"logarithmic\"\n    Logarithmic\n}\n\nenum SoundExpressionEffect {\n    //% block=\"none\"\n    None = 0,\n    //% block=\"vibrato\"\n    Vibrato = 1,\n    //% block=\"tremolo\"\n    Tremolo = 2,\n    //% block=\"warble\"\n    Warble = 3\n}\n\nenum SoundExpressionPlayMode {\n    //% block=\"until done\"\n    UntilDone,\n    //% block=\"in background\"\n    InBackground\n}\n\nnamespace soundExpression {\n    //% fixedInstance whenUsed block=\"{id:soundexpression}giggle\"\n    export const giggle = new SoundExpression(\"giggle\");\n    //% fixedInstance whenUsed block=\"{id:soundexpression}happy\"\n    export const happy = new SoundExpression(\"happy\");\n    //% fixedInstance whenUsed block=\"{id:soundexpression}hello\"\n    export const hello = new SoundExpression(\"hello\");\n    //% fixedInstance whenUsed block=\"{id:soundexpression}mysterious\"\n    export const mysterious = new SoundExpression(\"mysterious\");\n    //% fixedInstance whenUsed block=\"{id:soundexpression}sad\"\n    export const sad = new SoundExpression(\"sad\");\n    //% fixedInstance whenUsed block=\"{id:soundexpression}slide\"\n    export const slide = new SoundExpression(\"slide\");\n    //% fixedInstance whenUsed block=\"{id:soundexpression}soaring\"\n    export const soaring = new SoundExpression(\"soaring\");\n    //% fixedInstance whenUsed block=\"{id:soundexpression}spring\"\n    export const spring = new SoundExpression(\"spring\");\n    //% fixedInstance whenUsed block=\"{id:soundexpression}twinkle\"\n    export const twinkle = new SoundExpression(\"twinkle\");\n    //% fixedInstance whenUsed block=\"{id:soundexpression}yawn\"\n    export const yawn = new SoundExpression(\"yawn\");\n\n    export enum InterpolationEffect {\n        None = 0,\n        Linear = 1,\n        Curve = 2,\n        ExponentialRising = 5,\n        ExponentialFalling = 6,\n        ArpeggioRisingMajor = 8,\n        ArpeggioRisingMinor = 10,\n        ArpeggioRisingDiminished = 12,\n        ArpeggioRisingChromatic = 14,\n        ArpeggioRisingWholeTone = 16,\n        ArpeggioFallingMajor = 9,\n        ArpeggioFallingMinor = 11,\n        ArpeggioFallingDiminished = 13,\n        ArpeggioFallingChromatic = 15,\n        ArpeggioFallingWholeTone = 17,\n        Logarithmic = 18\n    }\n\n    export class Sound {\n        src: string;\n\n        constructor() {\n            this.src = \"000000000000000000000000000000000000000000000000000000000000000000000000\"\n        }\n\n        get wave(): WaveShape {\n            return this.getValue(0, 1);\n        }\n\n        set wave(value: WaveShape) {\n            this.setValue(0, Math.constrain(value, 0, 4), 1);\n        }\n\n        get volume() {\n            return this.getValue(1, 4);\n        }\n\n        set volume(value: number) {\n            this.setValue(1, Math.constrain(value, 0, 1023), 4);\n        }\n\n        get frequency() {\n            return this.getValue(5, 4);\n        }\n\n        set frequency(value: number) {\n            this.setValue(5, value, 4);\n        }\n\n        get duration() {\n            return this.getValue(9, 4);\n        }\n\n        set duration(value: number) {\n            this.setValue(9, value, 4);\n        }\n\n        get shape(): InterpolationEffect {\n            return this.getValue(13, 2);\n        }\n\n        set shape(value: InterpolationEffect) {\n            this.setValue(13, value, 2);\n        }\n\n        get endFrequency() {\n            return this.getValue(18, 4);\n        }\n\n        set endFrequency(value: number) {\n            this.setValue(18, value, 4);\n        }\n\n        get endVolume() {\n            return this.getValue(26, 4);\n        }\n\n        set endVolume(value: number) {\n            this.setValue(26, Math.constrain(value, 0, 1023), 4);\n        }\n\n        get steps() {\n            return this.getValue(30, 4);\n        }\n\n        set steps(value: number) {\n            this.setValue(30, value, 4);\n        }\n\n        get fx(): SoundExpressionEffect {\n            return this.getValue(34, 2);\n        }\n\n        set fx(value: SoundExpressionEffect) {\n            this.setValue(34, Math.constrain(value, 0, 3), 2);\n        }\n\n        get fxParam() {\n            return this.getValue(36, 4);\n        }\n\n        set fxParam(value: number) {\n            this.setValue(36, value, 4);\n        }\n\n        get fxnSteps() {\n            return this.getValue(40, 4);\n        }\n\n        set fxnSteps(value: number) {\n            this.setValue(40, value, 4);\n        }\n\n        get frequencyRandomness() {\n            return this.getValue(44, 4);\n        }\n\n        set frequencyRandomness(value: number) {\n            this.setValue(44, value, 4);\n        }\n\n        get endFrequencyRandomness() {\n            return this.getValue(48, 4);\n        }\n\n        set endFrequencyRandomness(value: number) {\n            this.setValue(48, value, 4);\n        }\n\n        get volumeRandomness() {\n            return this.getValue(52, 4);\n        }\n\n        set volumeRandomness(value: number) {\n            this.setValue(52, value, 4);\n        }\n\n        get endVolumeRandomness() {\n            return this.getValue(56, 4);\n        }\n\n        set endVolumeRandomness(value: number) {\n            this.setValue(56, value, 4);\n        }\n\n        get durationRandomness() {\n            return this.getValue(60, 4);\n        }\n\n        set durationRandomness(value: number) {\n            this.setValue(60, value, 4);\n        }\n\n        get fxParamRandomness() {\n            return this.getValue(64, 4);\n        }\n\n        set fxParamRandomness(value: number) {\n            this.setValue(64, value, 4);\n        }\n\n        get fxnStepsRandomness() {\n            return this.getValue(68, 4);\n        }\n\n        set fxnStepsRandomness(value: number) {\n            this.setValue(68, value, 4);\n        }\n\n        copy() {\n            const result = new Sound();\n            result.src = this.src.slice(0);\n            return result;\n        }\n\n        protected setValue(offset: number, value: number, length: number) {\n            value = Math.constrain(value | 0, 0, Math.pow(10, length) - 1);\n            this.src = this.src.substr(0, offset) + formatNumber(value, length) + this.src.substr(offset + length);\n        }\n\n        protected getValue(offset: number, length: number) {\n            return parseInt(this.src.substr(offset, length));\n        }\n    }\n\n    function formatNumber(num: number, length: number) {\n        let result = num + \"\";\n        while (result.length < length) result = \"0\" + result;\n        return result;\n    }\n\n    export function playSound(toPlay: Sound | Sound[]) {\n        let src = \"\";\n        if (Array.isArray(toPlay)) {\n            src = (toPlay as Sound[]).map(s => s.src).join(\",\");\n        }\n        else {\n            src = (toPlay as Sound).src;\n        }\n\n        new SoundExpression(src).playUntilDone();\n    }\n}\n\nnamespace music {\n    /**\n     * Play a sound effect from a sound expression string.\n     * @param sound the sound expression string\n     * @param mode the play mode, play until done or in the background\n     */\n    //% blockId=soundExpression_playSoundEffect\n    //% block=\"play sound $sound $mode\"\n    //% sound.shadow=soundExpression_createSoundEffect\n    //% weight=100 help=music/play-sound-effect\n    //% blockGap=8\n    //% deprecated=1\n    //% group=\"micro:bit (V2)\"\n    export function playSoundEffect(sound: string, mode: SoundExpressionPlayMode) {\n        if (mode === SoundExpressionPlayMode.InBackground) {\n            new SoundExpression(sound).play();\n        }\n        else {\n            new SoundExpression(sound).playUntilDone();\n        }\n    }\n\n    /**\n     * Create a sound expression from a set of sound effect parameters.\n     * @param waveShape waveform of the sound effect\n     * @param startFrequency starting frequency for the sound effect waveform\n     * @param endFrequency ending frequency for the sound effect waveform\n     * @param startVolume starting volume of the sound, or starting amplitude\n     * @param endVolume ending volume of the sound, or ending amplitude\n     * @param duration the amount of time in milliseconds (ms) that sound will play for\n     * @param effect the effect to apply to the waveform or volume\n     * @param interpolation interpolation method for frequency scaling\n     */\n    //% blockId=soundExpression_createSoundEffect\n    //% help=music/create-sound-effect\n    //% block=\"$waveShape|| start frequency $startFrequency end frequency $endFrequency duration $duration start volume $startVolume end volume $endVolume effect $effect interpolation $interpolation\"\n    //% waveShape.defl=WaveShape.Sine\n    //% waveShape.fieldEditor=soundeffect\n    //% startFrequency.defl=5000\n    //% startFrequency.min=0\n    //% startFrequency.max=5000\n    //% endFrequency.defl=0\n    //% endFrequency.min=0\n    //% endFrequency.max=5000\n    //% startVolume.defl=255\n    //% startVolume.min=0\n    //% startVolume.max=255\n    //% endVolume.defl=0\n    //% endVolume.min=0\n    //% endVolume.max=255\n    //% duration.defl=500\n    //% duration.min=1\n    //% duration.max=9999\n    //% effect.defl=SoundExpressionEffect.None\n    //% interpolation.defl=InterpolationCurve.Linear\n    //% compileHiddenArguments=true\n    //% inlineInputMode=\"variable\"\n    //% inlineInputModeLimit=3\n    //% expandableArgumentBreaks=\"3,5\"\n    //% group=\"micro:bit (V2)\"\n    //% deprecated=1\n    export function createSoundEffect(waveShape: WaveShape, startFrequency: number, endFrequency: number, startVolume: number, endVolume: number, duration: number, effect: SoundExpressionEffect, interpolation: InterpolationCurve): string {\n        let src = \"000000000000000000000000000000000000000000000000000000000000000000000000\";\n        src = setValue(src, 0, Math.constrain(waveShape, 0, 4), 1);\n        src = setValue(src, 1, Math.constrain(((startVolume / 255) * 1023) | 0, 0, 1023), 4);\n        src = setValue(src, 5, startFrequency, 4);\n        src = setValue(src, 9, duration, 4);\n        src = setValue(src, 18, endFrequency, 4);\n        src = setValue(src, 26, Math.constrain(((endVolume / 255) * 1023) | 0, 0, 1023), 4);\n        src = setValue(src, 34, Math.constrain(effect, 0, 3), 2);\n\n\n        switch (interpolation) {\n            case InterpolationCurve.Linear:\n                src = setValue(src, 13, soundExpression.InterpolationEffect.Linear, 2);\n                src = setValue(src, 30, 128, 4);\n                break;\n            case InterpolationCurve.Curve:\n                src = setValue(src, 13, soundExpression.InterpolationEffect.Curve, 2);\n                src = setValue(src, 30, 90, 4);\n                break;\n            case InterpolationCurve.Logarithmic:\n                src = setValue(src, 13, soundExpression.InterpolationEffect.Logarithmic, 2);\n                src = setValue(src, 30, 90, 4);\n                break;\n        }\n\n        switch (effect) {\n            case SoundExpressionEffect.Vibrato:\n                src = setValue(src, 36, DAL.SFX_DEFAULT_VIBRATO_PARAM, 4);\n                src = setValue(src, 40, DAL.SFX_DEFAULT_VIBRATO_STEPS, 4);\n                break;\n            case SoundExpressionEffect.Tremolo:\n                src = setValue(src, 36, DAL.SFX_DEFAULT_TREMOLO_PARAM, 4);\n                src = setValue(src, 40, DAL.SFX_DEFAULT_TREMOLO_STEPS, 4);\n                break;\n            case SoundExpressionEffect.Warble:\n                src = setValue(src, 36, DAL.SFX_DEFAULT_WARBLE_PARAM, 4);\n                src = setValue(src, 40, DAL.SFX_DEFAULT_WARBLE_STEPS, 4);\n                break;\n        }\n\n        return src;\n    }\n\n    /**\n     * Create a sound expression from a set of sound effect parameters.\n     * @param waveShape waveform of the sound effect\n     * @param startFrequency starting frequency for the sound effect waveform\n     * @param endFrequency ending frequency for the sound effect waveform\n     * @param startVolume starting volume of the sound, or starting amplitude\n     * @param endVolume ending volume of the sound, or ending amplitude\n     * @param duration the amount of time in milliseconds (ms) that sound will play for\n     * @param effect the effect to apply to the waveform or volume\n     * @param interpolation interpolation method for frequency scaling\n     */\n    //% blockId=soundExpression_createSoundExpression\n    //% help=music/create-sound-expression\n    //% block=\"$waveShape|| start frequency $startFrequency end frequency $endFrequency duration $duration start volume $startVolume end volume $endVolume effect $effect interpolation $interpolation\"\n    //% waveShape.defl=WaveShape.Sine\n    //% waveShape.fieldEditor=soundeffect\n    //% startFrequency.defl=5000\n    //% startFrequency.min=0\n    //% startFrequency.max=5000\n    //% endFrequency.defl=0\n    //% endFrequency.min=0\n    //% endFrequency.max=5000\n    //% startVolume.defl=255\n    //% startVolume.min=0\n    //% startVolume.max=255\n    //% endVolume.defl=0\n    //% endVolume.min=0\n    //% endVolume.max=255\n    //% duration.defl=500\n    //% duration.min=1\n    //% duration.max=9999\n    //% effect.defl=SoundExpressionEffect.None\n    //% interpolation.defl=InterpolationCurve.Linear\n    //% compileHiddenArguments=true\n    //% inlineInputMode=\"variable\"\n    //% inlineInputModeLimit=3\n    //% expandableArgumentBreaks=\"3,5\"\n    //% duplicateWithToolboxParent=music_playable_play\n    //% duplicateWithToolboxParentArgument=toPlay\n    //% duplicateShadowOnDrag\n    //% group=\"micro:bit (V2)\"\n    export function createSoundExpression(waveShape: WaveShape, startFrequency: number, endFrequency: number, startVolume: number, endVolume: number, duration: number, effect: SoundExpressionEffect, interpolation: InterpolationCurve): SoundExpression {\n        return new SoundExpression(createSoundEffect(waveShape, startFrequency, endFrequency, startVolume, endVolume, duration, effect, interpolation));\n    }\n\n    function setValue(src: string, offset: number, value: number, length: number) {\n        value = Math.constrain(value | 0, 0, Math.pow(10, length) - 1);\n        return src.substr(0, offset) + formatNumber(value, length) + src.substr(offset + length);\n    }\n\n    function formatNumber(num: number, length: number) {\n        let result = num + \"\";\n        while (result.length < length) result = \"0\" + result;\n        return result;\n    }\n\n    /**\n     * Get the sound expression string for a built-in a sound effect.\n     * @param soundExpression a sound expression for a built-in sound effect\n     */\n    //% blockId=soundExpression_builtinSoundEffect\n    //% block=\"$soundExpression\"\n    //% blockGap=8\n    //% group=\"micro:bit (V2)\"\n    //% toolboxParent=soundExpression_playSoundEffect\n    //% toolboxParentArgument=sound\n    //% weight=98 help=music/builtin-sound-effect\n    //% deprecated=1\n    export function builtinSoundEffect(soundExpression: SoundExpression) {\n        return soundExpression.getNotes();\n    }\n\n    /**\n     * Get the sound expression string for a built-in sound effect.\n     * @param soundExpression a sound expression for a built-in sound effect\n     */\n    //% blockId=soundExpression_builtinPlayableSoundEffect\n    //% block=\"$soundExpression\"\n    //% blockGap=8\n    //% group=\"micro:bit (V2)\"\n    //% toolboxParent=music_playable_play\n    //% toolboxParentArgument=toPlay\n    //% duplicateShadowOnDrag\n    //% weight=98 help=music/builtin-sound-effect\n    export function builtinPlayableSoundEffect(soundExpression: SoundExpression) {\n        return soundExpression;\n    }\n}","templates.ts":"/**\n * Tagged hex literal converter\n */\n//% shim=@hex\nfunction hex(lits: any, ...args: any[]): Buffer { return null }\n","touchmode.cpp":"#include \"pxt.h\"\n\n#if MICROBIT_CODAL\n#else\n#define MICROBIT_ID_LOGO 121\n#endif\n\nenum class TouchTargetMode {\n    //% block=\"capacitive\"\n    Capacitive = 1,\n    //% block=\"resistive\"\n    Resistive = 0\n};\n\nenum class TouchTarget {\n    //% block=\"P0\"\n    P0 = MICROBIT_ID_IO_P0,\n    //% block=\"P1\"\n    P1 = MICROBIT_ID_IO_P1,\n    //% block=\"P2\"\n    P2 = MICROBIT_ID_IO_P2,\n    //% block=\"logo\"\n    LOGO = MICROBIT_ID_LOGO\n};\n\nnamespace pins {\n\n   /**\n    * Configure the touch detection for the pins and logo.\n    * P0, P1, P2 use resistive touch by default.\n    * The logo uses capacitative touch by default.\n    * @param name target to change the touch mode for\n    * @param mode the touch mode to use\n    */\n    //% weight=60\n    //% blockId=device_touch_set_type block=\"set %name to touch mode %mode\"\n    //% advanced=true\n    //% group=\"micro:bit (V2)\"\n    //% help=pins/touch-set-mode\n    void touchSetMode(TouchTarget name, TouchTargetMode mode) {\n    #if MICROBIT_CODAL\n        const auto pin = name == TouchTarget::LOGO \n            ? &uBit.io.logo : getPin((int)name);\n        if (pin) {\n            pin->isTouched(mode == TouchTargetMode::Capacitive \n                ? codal::TouchMode::Capacitative : codal::TouchMode::Resistive);\n        }\n    #else\n        target_panic(PANIC_VARIANT_NOT_SUPPORTED);\n    #endif\n    }\n\n}","trig.cpp":"#include \"pxtbase.h\"\n#include <limits.h>\n#include <stdlib.h>\n\nusing namespace std;\n\nnamespace Math_ {\n\n#define SINGLE(op) return fromDouble(::op(toDouble(x)));\n\n//%\nTNumber atan2(TNumber y, TNumber x) {\n    return fromDouble(::atan2(toDouble(y), toDouble(x)));\n}\n\n//%\nTNumber tan(TNumber x){SINGLE(tan)}\n\n//%\nTNumber sin(TNumber x){SINGLE(sin)}\n\n//%\nTNumber cos(TNumber x){SINGLE(cos)}\n\n//%\nTNumber atan(TNumber x){SINGLE(atan)}\n\n//%\nTNumber asin(TNumber x){SINGLE(asin)}\n\n//%\nTNumber acos(TNumber x){SINGLE(acos)}\n\n//%\nTNumber sqrt(TNumber x){SINGLE(sqrt)}\n\n}"},"audio-samples":{"pxt.json":"{\n    \"name\": \"audio-samples\",\n    \"description\": \"Play audio samples. micro:bit (V2) only\",\n    \"dependencies\": {\n        \"core\": \"*\"\n    },\n    \"files\": [\n        \"samples.ts\",\n        \"samples.cpp\",\n        \"shims.d.ts\"\n    ],\n    \"testFiles\": [\n        \"test.ts\"\n    ],\n    \"public\": true,\n    \"targetVersions\": {\n        \"target\": \"7.1.42\",\n        \"pxt\": \"11.4.28\"\n    },\n    \"weight\": 10,\n    \"searchOnly\": true\n}\n","samples.cpp":"#include \"pxt.h\"\n#include \"MicroBit.h\"\n\n#if MICROBIT_CODAL\n#include \"SampleSource.h\"\n#endif\n\nusing namespace pxt;\n\nnamespace samples {\n\n/**\n * Enable audio\n */\n//%\nvoid enable() {\n    #if MICROBIT_CODAL\n        uBit.audio.enable();\n    #else\n        target_panic(PANIC_VARIANT_NOT_SUPPORTED);\n    #endif\n}\n\n\n/**\n *  Disable audio\n */\n//%\nvoid disable() {\n    #if MICROBIT_CODAL\n        uBit.audio.disable();\n    #else\n        target_panic(PANIC_VARIANT_NOT_SUPPORTED);\n    #endif\n}\n\n/**\n * Set the sample rate\n */\n//%\nvoid setSampleRate(int src, int sampleRate) {\n    #if MICROBIT_CODAL\n        if (0 <= src && src < 4)\n            uBit.audio.sampleSource[src]->setSampleRate(sampleRate);\n    #else\n        target_panic(PANIC_VARIANT_NOT_SUPPORTED);\n    #endif\n}\n\nbool isValidSample(Buffer buf) {\n    if (!buf)\n        return false;\n\n    // TODO: other checks here\n    return true;\n}\n\n/**\n * Play a sample\n */\n//%\nvoid playAsync(int src, Buffer buf) {\n    #if MICROBIT_CODAL\n        if (0 <= src && src < 4 && isValidSample(buf))\n            uBit.audio.sampleSource[src]->playAsync(buf->data, buf->length);\n    #else\n        target_panic(PANIC_VARIANT_NOT_SUPPORTED);\n    #endif\n}\n\n}\n","samples.ts":"","shims.d.ts":"// Auto-generated. Do not edit.\ndeclare namespace samples {\n\n    /**\n     * Enable audio\n     */\n    //% shim=samples::enable\n    function enable(): void;\n\n    /**\n     *  Disable audio\n     */\n    //% shim=samples::disable\n    function disable(): void;\n\n    /**\n     * Set the sample rate\n     */\n    //% shim=samples::setSampleRate\n    function setSampleRate(src: int32, sampleRate: int32): void;\n\n    /**\n     * Play a sample\n     */\n    //% shim=samples::playAsync\n    function playAsync(src: int32, buf: Buffer): void;\n}\n\n// Auto-generated. Do not edit. Really.\n","test.ts":"let strings9 = hex`524946467406000057415645666d74201000000001000100602200006022000001000800646174615006000092a8515977939aae6a4a708998a98e47678297a29d4a5b78939bad7349738a9aa97a426b7d999fa95a587e92a0a4584f73899ba8934b6a8697a78b416277949cae7a4d788d9ca763446f809ba0aa5f5a8391a5944657748b9ca89a516c8b96a8723e6876979caf7f4f7d8ca19d4f4c6f819ca0ad675c8991a87e3f5e728d9da99d55708c99a459436978989caf8554828ca58b42546e849ca1af6f5f8c91a7643f61738f9da8a45b738e9e96464d687b969faf9158868da7713d5b6d859ca2b374638c94a04d4862768f9fa8ab62778da2813c55687f96a0b1965c878fa55c415d70869da1b67e688c9990404f61778ea0a9b0687a8ea16b3c5a667f97a0b39e6287949847495e71869da2ba856c8c9c7b3958607b8ea1aab77079929a54415d6a8196a1b5a7698698873b515d73869ea4be8c6e8e9b623a5c617c8da2abbc7978958d42495c6b8196a3b8ab6e859b7036585d76859ea7c2976f91924b415c637d8da2afc181779b7838525c6e8197a5bbb4738698553b5b5f77869faac4a06f96833c495c667c8da4b1c788769c6038565e6f8198a8bebd74888d40445a627788a0acc8a86e996a35515c697c8fa6b4cd8f7a95473f5760708297aac0c5768c7b354c5a667787a0b0cdb16f955137555d6a7d8fa8b8d3927c88364657636f8397b0c3cd7b8b6531525b677688a2b4d1b4738e3e3f56606b7d8eabb9da967f742d4e5666708498b3c7d380874c34565c697588a5b7d6ba797c2f4655636b7e8eafbede9b7f5a2c5456686f849ab6ccd4857c393c555e6a778aa6badabd7e63294d55666c7f90b2c3e0a278423156596a70859cb9cfd790652c4455626b778aaabfddc27d4a2b5156696b7f92b5c8e0ad68313a555d6a7184a0bdd4d9924c2a4a55646b788cacc5dccb7633345159686c7e95b7cde0b5532941545f6a7286a1c2d5df9334304b58646c778eadc9dcd368243c515d686e7f99bcd1e1b73b294655616a7289a3c7d5e58d1f384c5b656d7892b1cedbd8511e435060686e809cbfd2e5b7262e4757636b738ba7ccd5e97c143f4b5e656e7996b4d2dcdc3e1f4750626970839ec4d2e9ac1436475a626d738fa9cfd5ed690f454b61656f7a98b8d3ded52b244954636a7187a1c8d2ed9a0b3d485d636e7592aed3d6ea5613494c6266707d9bbdd2e3c51f2c4855636b738aa5cbd4ec860e41495e646e7794b1d2dbdf441a484f636772809ec0d4e6b11e314858636c748ca9ccd7e47415414b60656f7a98b7d1e0cb4023475263677384a3c2d5e39b24344a5a646c778eafcadcd56820404e60666f7e9abad1e1b24327475563697586a7c3dada892d334c59666c7b91b3cae0c064293e525f6772819dbad4dd9d492a485464697889acc1dfc77d3c305059686d7e95b6c9e2a7672f3d5360687583a4bbd8d089582a4b55646a7c8db0c0e1af78442f535968708399b8ccda8e71333e5560697888a7badcbb7e632a4d55656b7f91b3c2e0967f4c30555a6972869eb6d0cb7e7d354056606a7a8baabadca27c6e2a4f56666e8395b2c5d580885232565a697689a2b6d3b37488364255616c7f91acbdd78d81752d50576772869ab1c8c374905534555a6a798ea5b8d19c768f3b4257616f8197abc2c8798979314e58667489a0b1ccac6f985a35545c6c7b92a5bbc9877d924142586173849cabc5b571917c354d5968788ea2b3c892739b6037555c707f98a6beba77849547415a627788a0abc69c7095823a4d5b6b7d93a3b6bd7d7c9d6737575d73839ea4c3a1708b964f3f5b637b8ca1aec1817698863c4d5c6e7f99a1bbab6f849c6f37575e7787a0a5c188728f99543e5c667e91a1b1b26f7f968d3e4c5d70849da3bc926b8b9b7538575f7a8ca1a9b87179909d573e5c688197a2b49e65889595424b5e74889ea4b8786f8e9c7b3957637d91a2ada8628190a25e3f5d6b849ba2b585648d9598444c60768e9fa9af67768e9f803a57658096a1b0915c8890a4603f5e6e8b9ca6b070688f979d484a6479949ead9a597e8ea2853d576a8499a2b0795d8d90a7663e62718f9caaa25d6f8f99a04d4a697c989eaf8255848fa5883f586e8a9ba6a762638d91a86c3f6475959bae8b53778e9ca04f4a6c7f9aa1ac68598591a58e415a708e9aab96516c8d95a971406878989cb071527c909da4564c6f859aa4a254618593a590435e74929aae7f4b738b99aa77406a7c9aa0a95c577e919fa55b4d74889ca88f466a8498a496465f7b93997c837d827e837e817e817f`\n\nsamples.enable()\nmusic.setVolume(100)\n\nwhile(1)\n{\nbasic.pause(2000)\n\nsamples.setSampleRate(0,11000)\nsamples.playAsync(0, strings9)\nsamples.setSampleRate(1,11000);\nsamples.playAsync(1, strings9)\nsamples.setSampleRate(2,6000);\nsamples.playAsync(2, strings9)\nsamples.setSampleRate(3,13000);\nsamples.playAsync(3, strings9)\n}\n"},"radio":{"README.md":"# radio\n\nThe radio library.\n\n","enums.d.ts":"// Auto-generated. Do not edit.\ndeclare namespace radio {\n}\n\n// Auto-generated. Do not edit. Really.\n","pxt.json":"{\n    \"name\": \"radio\",\n    \"description\": \"The radio services\",\n    \"dependencies\": {\n        \"core\": \"*\"\n    },\n    \"files\": [\n        \"README.md\",\n        \"shims.d.ts\",\n        \"enums.d.ts\",\n        \"radio.cpp\",\n        \"radio.ts\",\n        \"targetoverrides.ts\"\n    ],\n    \"public\": true,\n    \"targetVersions\": {\n        \"target\": \"7.1.42\",\n        \"pxt\": \"11.4.28\"\n    },\n    \"yotta\": {\n        \"config\": {\n            \"microbit-dal\": {\n                \"bluetooth\": {\n                    \"enabled\": 0\n                }\n            }\n        }\n    },\n    \"icon\": \"/static/libs/radio.png\"\n}\n","radio.cpp":"#include \"pxt.h\"\n\n// micro:bit dal\n#if defined(MICROBIT_H) \n\n#define CODAL_RADIO MicroBitRadio\n#define DEVICE_OK MICROBIT_OK\n#define DEVICE_NOT_SUPPORTED MICROBIT_NOT_SUPPORTED\n#define CODAL_EVENT MicroBitEvent\n#define CODAL_RADIO_MICROBIT_DAL 1\n\n// any other NRF52 board\n#elif defined(NRF52_SERIES)\n\n#include \"NRF52Radio.h\"\n#define CODAL_RADIO codal::NRF52Radio\n#define CODAL_EVENT codal::Event\n\n#endif\n\nusing namespace pxt;\n\n#ifndef MICROBIT_RADIO_MAX_PACKET_SIZE\n#define MICROBIT_RADIO_MAX_PACKET_SIZE          32\n#endif\n\n#ifndef DEVICE_RADIO_MAX_PACKET_SIZE\n#define DEVICE_RADIO_MAX_PACKET_SIZE MICROBIT_RADIO_MAX_PACKET_SIZE\n#endif\n\n#ifndef MICROBIT_ID_RADIO\n#define MICROBIT_ID_RADIO               29\n#endif\n\n#ifndef DEVICE_ID_RADIO\n#define DEVICE_ID_RADIO MICROBIT_ID_RADIO\n#endif\n\n#ifndef MICROBIT_RADIO_EVT_DATAGRAM\n#define MICROBIT_RADIO_EVT_DATAGRAM             1       // Event to signal that a new datagram has been received.\n#endif\n\n#ifndef DEVICE_RADIO_EVT_DATAGRAM\n#define DEVICE_RADIO_EVT_DATAGRAM MICROBIT_RADIO_EVT_DATAGRAM\n#endif\n\n//% color=#E3008C weight=96 icon=\"\\uf012\"\nnamespace radio {\n    \n#if CODAL_RADIO_MICROBIT_DAL\n    CODAL_RADIO* getRadio() {\n        return &uBit.radio;\n    }\n#elif defined(CODAL_RADIO)\nclass RadioWrap {\n    CODAL_RADIO radio;\n    public:\n        RadioWrap() \n            : radio()\n        {}\n\n    CODAL_RADIO* getRadio() {\n        return &radio;\n    }\n};\nSINGLETON(RadioWrap);\nCODAL_RADIO* getRadio() {\n    auto wrap = getRadioWrap();\n    if (NULL != wrap)\n        return wrap->getRadio();    \n    return NULL;\n}\n#endif // #else\n\n    bool radioEnabled = false;\n    bool init = false;\n    int radioEnable() {\n#ifdef CODAL_RADIO\n        auto radio = getRadio();\n        if (NULL == radio) \n            return DEVICE_NOT_SUPPORTED;\n\n        if (init && !radioEnabled) {\n            //If radio was explicitly disabled from a call to off API\n            //We don't want to enable it here. User needs to call on API first.\n            return DEVICE_NOT_SUPPORTED;\n        }\n\n        int r = radio->enable();\n        if (r != DEVICE_OK) {\n            target_panic(43);\n            return r;\n        }\n        if (!init) {\n            getRadio()->setGroup(0); //Default group zero. This used to be pxt::programHash()\n            getRadio()->setTransmitPower(6); // start with high power by default\n            init = true;\n        }\n        radioEnabled = true;\n        return r;\n#else\n        return DEVICE_NOT_SUPPORTED;\n#endif\n    }\n\n    /**\n    * Disables the radio for use as a multipoint sender/receiver.\n    * Disabling radio will help conserve battery power when it is not in use.\n    */\n    //% help=radio/off\n    void off() {\n#ifdef CODAL_RADIO\n        auto radio = getRadio();\n        if (NULL == radio)\n            return;\n\n        int r = radio->disable();\n        if (r != DEVICE_OK) {\n            target_panic(43);\n        } else {\n            radioEnabled = false;\n        }\n#else\n        return;\n#endif\n    }\n\n    /**\n    * Initialises the radio for use as a multipoint sender/receiver\n    * Only useful when the radio.off() is used beforehand.\n    */\n    //% help=radio/on\n    void on() {\n#ifdef CODAL_RADIO\n        auto radio = getRadio();\n        if (NULL == radio)\n            return;\n\n        int r = radio->enable();\n        if (r != DEVICE_OK) {\n            target_panic(43);\n        } else {\n            radioEnabled = true;\n        }\n#else\n        return;\n#endif\n    }\n\n    /**\n    * Sends an event over radio to neigboring devices\n    */\n    //% blockId=radioRaiseEvent block=\"radio raise event|from source %src=control_event_source_id|with value %value=control_event_value_id\"\n    //% blockExternalInputs=1\n    //% advanced=true\n    //% weight=1\n    //% help=radio/raise-event\n    void raiseEvent(int src, int value) {\n#ifdef CODAL_RADIO        \n        if (radioEnable() != DEVICE_OK) return;\n\n        getRadio()->event.eventReceived(CODAL_EVENT(src, value, CREATE_ONLY));\n#endif        \n    }\n\n    /**\n     * Internal use only. Takes the next packet from the radio queue and returns its contents + RSSI in a Buffer.\n     * @returns NULL if no packet available\n     */\n    //%\n    Buffer readRawPacket() {\n#ifdef CODAL_RADIO        \n        if (radioEnable() != DEVICE_OK) return NULL;\n\n        auto p = getRadio()->datagram.recv();\n#if CODAL_RADIO_MICROBIT_DAL\n        if (p == PacketBuffer::EmptyPacket)\n            return NULL;\n        int rssi = p.getRSSI();\n        auto length = p.length();\n        auto bytes = p.getBytes();\n#else\n        // TODO: RSSI support\n        int rssi = -73;        \n        auto length = p.length();\n        auto bytes = p.getBytes();\n        if (length == 0)\n            return NULL;\n#endif\n\n        uint8_t buf[DEVICE_RADIO_MAX_PACKET_SIZE + sizeof(int)]; // packet length + rssi\n        memset(buf, 0, sizeof(buf));\n        memcpy(buf, bytes, length); // data\n        memcpy(buf + DEVICE_RADIO_MAX_PACKET_SIZE, &rssi, sizeof(int)); // RSSi - assumes Int32LE layout\n        return mkBuffer(buf, sizeof(buf));\n#else\n        return NULL;\n#endif        \n    }\n\n    /**\n     * Internal use only. Sends a raw packet through the radio (assumes RSSI appened to packet)\n     */\n    //% async\n    void sendRawPacket(Buffer msg) {\n#ifdef CODAL_RADIO        \n        if (radioEnable() != DEVICE_OK || NULL == msg) return;\n\n        // don't send RSSI data; and make sure no buffer underflow\n        int len = msg->length - sizeof(int);\n        if (len > 0)\n            getRadio()->datagram.send(msg->data, len);\n#endif            \n    }\n\n    /**\n     * Used internally by the library.\n     */\n    //% help=radio/on-data-received\n    //% weight=0\n    //% blockId=radio_datagram_received_event block=\"radio on data received\" blockGap=8\n    //% deprecated=true blockHidden=1\n    void onDataReceived(Action body) {\n#ifdef CODAL_RADIO        \n        if (radioEnable() != DEVICE_OK) return;\n\n        registerWithDal(DEVICE_ID_RADIO, DEVICE_RADIO_EVT_DATAGRAM, body);\n        getRadio()->datagram.recv(); // wake up read code\n#endif       \n    }\n\n    /**\n     * Sets the group id for radio communications. A micro:bit can only listen to one group ID at any time.\n     * @param id the group id between ``0`` and ``255``, eg: 1\n     */\n    //% help=radio/set-group\n    //% weight=100\n    //% blockId=radio_set_group block=\"radio set group %ID\"\n    //% id.min=0 id.max=255\n    //% group=\"Group\"\n    void setGroup(int id) {\n#ifdef CODAL_RADIO        \n        if (radioEnable() != DEVICE_OK) return;\n\n        getRadio()->setGroup(id);\n#endif       \n    }\n\n    /**\n     * Change the output power level of the transmitter to the given value.\n    * @param power a value in the range 0..7, where 0 is the lowest power and 7 is the highest. eg: 7\n    */\n    //% help=radio/set-transmit-power\n    //% weight=9 blockGap=8\n    //% blockId=radio_set_transmit_power block=\"radio set transmit power %power\"\n    //% power.min=0 power.max=7\n    //% advanced=true\n    void setTransmitPower(int power) {\n#ifdef CODAL_RADIO        \n        if (radioEnable() != DEVICE_OK) return;\n\n        getRadio()->setTransmitPower(power);\n#endif        \n    }\n\n    /**\n    * Change the transmission and reception band of the radio to the given channel\n    * @param band a frequency band in the range 0 - 83. Each step is 1MHz wide, based at 2400MHz.\n    **/\n    //% help=radio/set-frequency-band\n    //% weight=8 blockGap=8\n    //% blockId=radio_set_frequency_band block=\"radio set frequency band %band\"\n    //% band.min=0 band.max=83\n    //% advanced=true\n    void setFrequencyBand(int band) {\n#ifdef CODAL_RADIO        \n        if (radioEnable() != DEVICE_OK) return;\n        getRadio()->setFrequencyBand(band);\n#endif        \n    }\n}\n","radio.ts":"\nenum RadioPacketProperty {\n    //% blockIdentity=radio._packetProperty\n    //% block=\"signal strength\"\n    SignalStrength = 2,\n    //% blockIdentity=radio._packetProperty\n    //% block=\"time\"\n    Time = 0,\n    //% block=\"serial number\"\n    //% blockIdentity=radio._packetProperty\n    SerialNumber = 1\n}\n\n/**\n * Communicate data using radio packets\n */\n//% color=#E3008C weight=96 icon=\"\\uf012\" groups='[\"Group\", \"Broadcast\", \"Send\", \"Receive\"]'\nnamespace radio {\n\n    // keep in sync with CODAL\n    const RADIO_MAX_PACKET_SIZE = 32;\n    const MAX_FIELD_DOUBLE_NAME_LENGTH = 8;\n    const MAX_PAYLOAD_LENGTH = 20;\n    const PACKET_PREFIX_LENGTH = 9;\n    const VALUE_PACKET_NAME_LEN_OFFSET = 13;\n    const DOUBLE_VALUE_PACKET_NAME_LEN_OFFSET = 17;\n\n    // Packet Spec:\n    // | 0              | 1 ... 4       | 5 ... 8           | 9 ... 28\n    // ----------------------------------------------------------------\n    // | packet type    | system time   | serial number     | payload\n    //\n    // Serial number defaults to 0 unless enabled by user\n\n    // payload: number (9 ... 12)\n    export const PACKET_TYPE_NUMBER = 0;\n    // payload: number (9 ... 12), name length (13), name (14 ... 26)\n    export const PACKET_TYPE_VALUE = 1;\n    // payload: string length (9), string (10 ... 28)\n    export const PACKET_TYPE_STRING = 2;\n    // payload: buffer length (9), buffer (10 ... 28)\n    export const PACKET_TYPE_BUFFER = 3;\n    // payload: number (9 ... 16)\n    export const PACKET_TYPE_DOUBLE = 4;\n    // payload: number (9 ... 16), name length (17), name (18 ... 26)\n    export const PACKET_TYPE_DOUBLE_VALUE = 5;\n\n    let transmittingSerial: boolean;\n    let initialized = false;\n\n    export let lastPacket: RadioPacket;\n    let onReceivedNumberHandler: (receivedNumber: number) => void;\n    let onReceivedValueHandler: (name: string, value: number) => void;\n    let onReceivedStringHandler: (receivedString: string) => void;\n    let onReceivedBufferHandler: (receivedBuffer: Buffer) => void;\n\n    function init() {\n        if (initialized) return;\n        initialized = true;\n        onDataReceived(handleDataReceived);\n    }\n\n    function handleDataReceived() {\n        let buffer: Buffer = readRawPacket();\n        while (buffer) {\n            lastPacket = RadioPacket.getPacket(buffer);\n            switch (lastPacket.packetType) {\n                case PACKET_TYPE_NUMBER:\n                case PACKET_TYPE_DOUBLE:\n                    if (onReceivedNumberHandler)\n                        onReceivedNumberHandler(lastPacket.numberPayload);\n                    break;\n                case PACKET_TYPE_VALUE:\n                case PACKET_TYPE_DOUBLE_VALUE:\n                    if (onReceivedValueHandler)\n                        onReceivedValueHandler(lastPacket.stringPayload, lastPacket.numberPayload);\n                    break;\n                case PACKET_TYPE_BUFFER:\n                    if (onReceivedBufferHandler)\n                        onReceivedBufferHandler(lastPacket.bufferPayload);\n                    break;\n                case PACKET_TYPE_STRING:\n                    if (onReceivedStringHandler)\n                        onReceivedStringHandler(lastPacket.stringPayload);\n                    break;\n            }\n            // read next packet if any\n            buffer = readRawPacket();\n        }\n    }\n\n    /**\n     * Registers code to run when the radio receives a number.\n     */\n    //% help=radio/on-received-number\n    //% blockId=radio_on_number_drag block=\"on radio received\" blockGap=16\n    //% useLoc=\"radio.onDataPacketReceived\" draggableParameters=reporter\n    //% group=\"Receive\"\n    //% weight=20\n    export function onReceivedNumber(cb: (receivedNumber: number) => void) {\n        init();\n        onReceivedNumberHandler = cb;\n    }\n\n    /**\n     * Registers code to run when the radio receives a key value pair.\n     */\n    //% help=radio/on-received-value\n    //% blockId=radio_on_value_drag block=\"on radio received\" blockGap=16\n    //% useLoc=\"radio.onDataPacketReceived\" draggableParameters=reporter\n    //% group=\"Receive\"\n    //% weight=19\n    export function onReceivedValue(cb: (name: string, value: number) => void) {\n        init();\n        onReceivedValueHandler = cb;\n    }\n\n    /**\n     * Registers code to run when the radio receives a string.\n     */\n    //% help=radio/on-received-string\n    //% blockId=radio_on_string_drag block=\"on radio received\" blockGap=16\n    //% useLoc=\"radio.onDataPacketReceived\" draggableParameters=reporter\n    //% group=\"Receive\"\n    //% weight=18\n    export function onReceivedString(cb: (receivedString: string) => void) {\n        init();\n        onReceivedStringHandler = cb;\n    }\n\n    /**\n     * Registers code to run when the radio receives a buffer.\n     */\n    //% help=radio/on-received-buffer blockHidden=1\n    //% blockId=radio_on_buffer_drag block=\"on radio received\" blockGap=16\n    //% useLoc=\"radio.onDataPacketReceived\" draggableParameters=reporter\n    export function onReceivedBuffer(cb: (receivedBuffer: Buffer) => void) {\n        init();\n        onReceivedBufferHandler = cb;\n    }\n\n    /**\n     * Returns properties of the last radio packet received.\n     * @param type the type of property to retrieve from the last packet\n     */\n    //% help=radio/received-packet\n    //% blockGap=8\n    //% blockId=radio_received_packet block=\"received packet %type=radio_packet_property\" blockGap=16\n    //% group=\"Receive\"\n    //% weight=16\n    export function receivedPacket(type: number) {\n        if (lastPacket) {\n            switch (type) {\n                case RadioPacketProperty.Time: return lastPacket.time;\n                case RadioPacketProperty.SerialNumber: return lastPacket.serial;\n                case RadioPacketProperty.SignalStrength: return lastPacket.signal;\n            }\n        }\n        return 0;\n    }\n\n    /**\n     * Gets a packet property.\n     * @param type the packet property type, eg: PacketProperty.time\n     */\n    //% blockId=radio_packet_property block=\"%note\"\n    //% shim=TD_ID blockHidden=1\n    export function _packetProperty(type: RadioPacketProperty): number {\n        return type;\n    }\n\n    export class RadioPacket {\n        public static getPacket(data: Buffer) {\n            if (!data) return undefined;\n            // last 4 bytes is RSSi\n            return new RadioPacket(data);\n        }\n\n        public static mkPacket(packetType: number) {\n            const res = new RadioPacket();\n            res.data[0] = packetType;\n            return res;\n        }\n\n        private constructor(public readonly data?: Buffer) {\n            if (!data) this.data = control.createBuffer(RADIO_MAX_PACKET_SIZE + 4);\n        }\n\n        get signal() {\n            return this.data.getNumber(NumberFormat.Int32LE, this.data.length - 4);\n        }\n\n        get packetType() {\n            return this.data[0];\n        }\n\n        get time() {\n            return this.data.getNumber(NumberFormat.Int32LE, 1);\n        }\n\n        set time(val: number) {\n            this.data.setNumber(NumberFormat.Int32LE, 1, val);\n        }\n\n        get serial() {\n            return this.data.getNumber(NumberFormat.Int32LE, 5);\n        }\n\n        set serial(val: number) {\n            this.data.setNumber(NumberFormat.Int32LE, 5, val);\n        }\n\n        get stringPayload() {\n            const offset = getStringOffset(this.packetType) as number;\n            return offset ? this.data.slice(offset + 1, this.data[offset]).toString() : undefined;\n        }\n\n        set stringPayload(val: string) {\n            const offset = getStringOffset(this.packetType) as number;\n            if (offset) {\n                const buf = control.createBufferFromUTF8(truncateString(val, getMaxStringLength(this.packetType)));\n                this.data[offset] = buf.length;\n                this.data.write(offset + 1, buf);\n            }\n        }\n\n        get numberPayload() {\n            switch (this.packetType) {\n                case PACKET_TYPE_NUMBER:\n                case PACKET_TYPE_VALUE:\n                    return this.data.getNumber(NumberFormat.Int32LE, PACKET_PREFIX_LENGTH);\n                case PACKET_TYPE_DOUBLE:\n                case PACKET_TYPE_DOUBLE_VALUE:\n                    return this.data.getNumber(NumberFormat.Float64LE, PACKET_PREFIX_LENGTH);\n            }\n            return undefined;\n        }\n\n        set numberPayload(val: number) {\n            switch (this.packetType) {\n                case PACKET_TYPE_NUMBER:\n                case PACKET_TYPE_VALUE:\n                    this.data.setNumber(NumberFormat.Int32LE, PACKET_PREFIX_LENGTH, val);\n                    break;\n                case PACKET_TYPE_DOUBLE:\n                case PACKET_TYPE_DOUBLE_VALUE:\n                    this.data.setNumber(NumberFormat.Float64LE, PACKET_PREFIX_LENGTH, val);\n                    break;\n            }\n        }\n\n        get bufferPayload() {\n            const len = this.data[PACKET_PREFIX_LENGTH];\n            return this.data.slice(PACKET_PREFIX_LENGTH + 1, len);\n        }\n\n        set bufferPayload(b: Buffer) {\n            const len = Math.min(b.length, MAX_PAYLOAD_LENGTH - 1);\n            this.data[PACKET_PREFIX_LENGTH] = len;\n            this.data.write(PACKET_PREFIX_LENGTH + 1, b.slice(0, len));\n        }\n\n        hasString() {\n            return this.packetType === PACKET_TYPE_STRING ||\n                this.packetType === PACKET_TYPE_VALUE ||\n                this.packetType === PACKET_TYPE_DOUBLE_VALUE;\n        }\n\n        hasNumber() {\n            return this.packetType === PACKET_TYPE_NUMBER ||\n                this.packetType === PACKET_TYPE_DOUBLE ||\n                this.packetType === PACKET_TYPE_VALUE ||\n                this.packetType === PACKET_TYPE_DOUBLE_VALUE;\n        }\n    }\n\n    /**\n     * Broadcasts a number over radio to any connected micro:bit in the group.\n     */\n    //% help=radio/send-number\n    //% weight=60\n    //% blockId=radio_datagram_send block=\"radio send number %value\" blockGap=8\n    //% group=\"Send\"\n    export function sendNumber(value: number) {\n        let packet: RadioPacket;\n\n        if (value === (value | 0)) {\n            packet = RadioPacket.mkPacket(PACKET_TYPE_NUMBER);\n        }\n        else {\n            packet = RadioPacket.mkPacket(PACKET_TYPE_DOUBLE);\n        }\n\n        packet.numberPayload = value;\n        sendPacket(packet);\n    }\n\n    /**\n    * Broadcasts a name / value pair along with the device serial number\n    * and running time to any connected micro:bit in the group. The name can\n    * include no more than 8 characters.\n    * @param name the field name (max 8 characters), eg: \"name\"\n    * @param value the numeric value\n    */\n    //% help=radio/send-value\n    //% weight=59\n    //% blockId=radio_datagram_send_value block=\"radio send|value %name|= %value\" blockGap=8\n    //% group=\"Send\"\n    export function sendValue(name: string, value: number) {\n        let packet: RadioPacket;\n\n        if (value === (value | 0)) {\n            packet = RadioPacket.mkPacket(PACKET_TYPE_VALUE);\n        }\n        else {\n            packet = RadioPacket.mkPacket(PACKET_TYPE_DOUBLE_VALUE);\n        }\n\n        packet.numberPayload = value;\n        packet.stringPayload = name;\n        sendPacket(packet);\n    }\n\n    /**\n     * Broadcasts a string along with the device serial number\n     * and running time to any connected micro:bit in the group.\n     */\n    //% help=radio/send-string\n    //% weight=58\n    //% blockId=radio_datagram_send_string block=\"radio send string %msg\"\n    //% msg.shadowOptions.toString=true\n    //% group=\"Send\"\n    export function sendString(value: string) {\n        const packet = RadioPacket.mkPacket(PACKET_TYPE_STRING);\n        packet.stringPayload = value;\n        sendPacket(packet);\n    }\n\n    /**\n     * Broadcasts a buffer (up to 19 bytes long) along with the device serial number\n     * and running time to any connected micro:bit in the group.\n     */\n    //% help=radio/send-buffer\n    //% weight=57\n    //% advanced=true\n    export function sendBuffer(msg: Buffer) {\n        const packet = RadioPacket.mkPacket(PACKET_TYPE_BUFFER);\n        packet.bufferPayload = msg;\n        sendPacket(packet);\n    }\n\n    /**\n    * Set the radio to transmit the serial number in each message.\n    * @param transmit value indicating if the serial number is transmitted, eg: true\n    */\n    //% help=radio/set-transmit-serial-number\n    //% weight=8 blockGap=8\n    //% blockId=radio_set_transmit_serial_number block=\"radio set transmit serial number %transmit\"\n    //% advanced=true\n    export function setTransmitSerialNumber(transmit: boolean) {\n        transmittingSerial = transmit;\n    }\n\n    function sendPacket(packet: RadioPacket) {\n        packet.time = control.millis();\n        packet.serial = transmittingSerial ? control.deviceSerialNumber() : 0;\n        radio.sendRawPacket(packet.data);\n    }\n\n    function truncateString(str: string, bytes: number) {\n        str = str.substr(0, bytes);\n        let buff = control.createBufferFromUTF8(str);\n\n        while (buff.length > bytes) {\n            str = str.substr(0, str.length - 1);\n            buff = control.createBufferFromUTF8(str);\n        }\n\n        return str;\n    }\n\n    function getStringOffset(packetType: number) {\n        switch (packetType) {\n            case PACKET_TYPE_STRING:\n                return PACKET_PREFIX_LENGTH;\n            case PACKET_TYPE_VALUE:\n                return VALUE_PACKET_NAME_LEN_OFFSET;\n            case PACKET_TYPE_DOUBLE_VALUE:\n                return DOUBLE_VALUE_PACKET_NAME_LEN_OFFSET;\n            default:\n                return undefined;\n        }\n    }\n\n    function getMaxStringLength(packetType: number) {\n        switch (packetType) {\n            case PACKET_TYPE_STRING:\n                return MAX_PAYLOAD_LENGTH - 1;\n            case PACKET_TYPE_VALUE:\n            case PACKET_TYPE_DOUBLE_VALUE:\n                return MAX_FIELD_DOUBLE_NAME_LENGTH;\n            default:\n                return undefined;\n        }\n    }\n}","shims.d.ts":"// Auto-generated. Do not edit.\n\n\n\n    //% color=#E3008C weight=96 icon=\"\\uf012\"\ndeclare namespace radio {\n\n    /**\n     * Disables the radio for use as a multipoint sender/receiver.\n     * Disabling radio will help conserve battery power when it is not in use.\n     */\n    //% help=radio/off shim=radio::off\n    function off(): void;\n\n    /**\n     * Initialises the radio for use as a multipoint sender/receiver\n     * Only useful when the radio.off() is used beforehand.\n     */\n    //% help=radio/on shim=radio::on\n    function on(): void;\n\n    /**\n     * Sends an event over radio to neigboring devices\n     */\n    //% blockId=radioRaiseEvent block=\"radio raise event|from source %src=control_event_source_id|with value %value=control_event_value_id\"\n    //% blockExternalInputs=1\n    //% advanced=true\n    //% weight=1\n    //% help=radio/raise-event shim=radio::raiseEvent\n    function raiseEvent(src: int32, value: int32): void;\n\n    /**\n     * Internal use only. Takes the next packet from the radio queue and returns its contents + RSSI in a Buffer.\n     * @returns NULL if no packet available\n     */\n    //% shim=radio::readRawPacket\n    function readRawPacket(): Buffer;\n\n    /**\n     * Internal use only. Sends a raw packet through the radio (assumes RSSI appened to packet)\n     */\n    //% async shim=radio::sendRawPacket\n    function sendRawPacket(msg: Buffer): void;\n\n    /**\n     * Used internally by the library.\n     */\n    //% help=radio/on-data-received\n    //% weight=0\n    //% blockId=radio_datagram_received_event block=\"radio on data received\" blockGap=8\n    //% deprecated=true blockHidden=1 shim=radio::onDataReceived\n    function onDataReceived(body: () => void): void;\n\n    /**\n     * Sets the group id for radio communications. A micro:bit can only listen to one group ID at any time.\n     * @param id the group id between ``0`` and ``255``, eg: 1\n     */\n    //% help=radio/set-group\n    //% weight=100\n    //% blockId=radio_set_group block=\"radio set group %ID\"\n    //% id.min=0 id.max=255\n    //% group=\"Group\" shim=radio::setGroup\n    function setGroup(id: int32): void;\n\n    /**\n     * Change the output power level of the transmitter to the given value.\n     * @param power a value in the range 0..7, where 0 is the lowest power and 7 is the highest. eg: 7\n     */\n    //% help=radio/set-transmit-power\n    //% weight=9 blockGap=8\n    //% blockId=radio_set_transmit_power block=\"radio set transmit power %power\"\n    //% power.min=0 power.max=7\n    //% advanced=true shim=radio::setTransmitPower\n    function setTransmitPower(power: int32): void;\n\n    /**\n     * Change the transmission and reception band of the radio to the given channel\n     * @param band a frequency band in the range 0 - 83. Each step is 1MHz wide, based at 2400MHz.\n     **/\n    //% help=radio/set-frequency-band\n    //% weight=8 blockGap=8\n    //% blockId=radio_set_frequency_band block=\"radio set frequency band %band\"\n    //% band.min=0 band.max=83\n    //% advanced=true shim=radio::setFrequencyBand\n    function setFrequencyBand(band: int32): void;\n}\n\n// Auto-generated. Do not edit. Really.\n","targetoverrides.ts":"namespace radio {\n    export class Packet {\n        /**\n         * The number payload if a number was sent in this packet (via ``sendNumber()`` or ``sendValue()``)\n         * or 0 if this packet did not contain a number.\n         */\n        public receivedNumber: number;\n        /**\n         * The string payload if a string was sent in this packet (via ``sendString()`` or ``sendValue()``)\n         * or the empty string if this packet did not contain a string.\n         */\n        public receivedString: string;\n        /**\n         * The buffer payload if a buffer was sent in this packet\n         * or the empty buffer\n         */\n        public receivedBuffer: Buffer;\n        /**\n         * The system time of the sender of the packet at the time the packet was sent.\n         */\n        public time: number;\n        /**\n         * The serial number of the sender of the packet or 0 if the sender did not sent their serial number.\n         */\n        public serial: number;\n        /**\n         * The received signal strength indicator (RSSI) of the packet.\n         */\n        public signal: number;\n    }\n\n    /**\n     * Deprecated. Use onDataReceived() instead\n     * Registers code to run when the radio receives a packet. Also takes the\n     * received packet from the radio queue.\n     */\n    //% help=radio/on-data-packet-received blockHandlerKey=\"radioreceived\" deprecated=true\n    //% mutate=objectdestructuring\n    //% mutateText=Packet\n    //% mutateDefaults=\"receivedNumber;receivedString:name,receivedNumber:value;receivedString\"\n    //% blockId=radio_on_packet block=\"on radio received\" blockGap=8\n    export function onDataPacketReceived(cb: (packet: Packet) => void) {\n        onDataReceived(() => {\n            receiveNumber();\n            const packet = new Packet();\n            packet.receivedNumber = receivedNumber();\n            packet.time = receivedTime();\n            packet.serial = receivedSerial();\n            packet.receivedString = receivedString();\n            packet.receivedBuffer = receivedBuffer();\n            packet.signal = receivedSignalStrength();\n            cb(packet)\n        });\n    }\n\n    /**\n     * Registers code to run when the radio receives a number. Deprecated, use\n     * onReceivedNumber instead.\n     */\n    //% help=radio/on-received-number blockHandlerKey=\"radioreceived\"\n    //% blockId=radio_on_number block=\"on radio received\" blockGap=16\n    //% useLoc=\"radio.onDataPacketReceived\" deprecated=1\n    export function onReceivedNumberDeprecated(cb: (receivedNumber: number) => void) {\n        onReceivedNumber(cb);\n    }\n\n    /**\n     * Registers code to run when the radio receives a key value pair. Deprecated, use\n     * onReceivedValue instead.\n     */\n    //% help=radio/on-received-value blockHandlerKey=\"radioreceived\"\n    //% blockId=radio_on_value block=\"on radio received\" blockGap=16\n    //% useLoc=\"radio.onDataPacketReceived\" deprecated=1\n    export function onReceivedValueDeprecated(cb: (name: string, value: number) => void) {\n        onReceivedValue(cb);\n    }\n\n    /**\n     * Registers code to run when the radio receives a string. Deprecated, use\n     * onReceivedString instead.\n     */\n    //% help=radio/on-received-string blockHandlerKey=\"radioreceived\"\n    //% blockId=radio_on_string block=\"on radio received\" blockGap=16\n    //% useLoc=\"radio.onDataPacketReceived\" deprecated=1\n    export function onReceivedStringDeprecated(cb: (receivedString: string) => void) {\n        onReceivedString(cb);\n    }\n\n    /**\n     * Registers code to run when the radio receives a buffer. Deprecated, use\n     * onReceivedBuffer instead.\n     */\n    //% help=radio/on-received-buffer blockHandlerKey=\"radioreceived\" blockHidden=1\n    //% blockId=radio_on_buffer block=\"on radio received\" blockGap=16\n    //% useLoc=\"radio.onDataPacketReceived\" deprecated=1\n    export function onReceivedBufferDeprecated(cb: (receivedBuffer: Buffer) => void) {\n        onReceivedBuffer(cb);\n    }\n\n    /**\n     * Returns the number payload from the last packet taken from the radio queue\n     * (via ``receiveNumber``, ``receiveString``, etc) or 0 if that packet did not\n     * contain a number.\n     */\n    //% help=radio/received-number deprecated=1\n    export function receivedNumber(): number {\n        return (lastPacket ? lastPacket.numberPayload : 0) || 0;\n    }\n\n    /**\n     * Returns the serial number of the sender micro:bit from the last packet taken\n     * from the radio queue (via ``receiveNumber``, ``receiveString``, etc) or 0 if\n     * that packet did not send a serial number.\n     */\n    //% help=radio/received-serial deprecated=1\n    export function receivedSerial(): number {\n        return lastPacket ? lastPacket.serial : 0;\n    }\n\n    /**\n     * Returns the string payload from the last packet taken from the radio queue\n     * (via ``receiveNumber``, ``receiveString``, etc) or the empty string if that\n     * packet did not contain a string.\n     */\n    //% help=radio/received-string deprecated=1\n    export function receivedString(): string {\n        return (lastPacket ? lastPacket.stringPayload : \"\") || \"\";\n    }\n\n    /**\n     * Returns the buffer payload from the last packet taken from the radio queue\n     * (via ``receiveNumber``, ``receiveString``, etc) or the empty string if that\n     * packet did not contain a string.\n     */\n    //% help=radio/received-buffer deprecated=1\n    export function receivedBuffer(): Buffer {\n        return (lastPacket ? lastPacket.bufferPayload : null) || control.createBuffer(0);\n    }\n\n    /**\n     * Returns the system time of the sender micro:bit at the moment when it sent the\n     * last packet taken from the radio queue (via ``receiveNumber``,\n     * ``receiveString``, etc).\n     */\n    //% help=radio/received-time deprecated=1\n    export function receivedTime(): number {\n        return lastPacket ? lastPacket.time : 0;\n    }\n\n    /**\n     * Reads the next packet from the radio queue and returns the packet's number\n     * payload or 0 if the packet did not contain a number.\n     */\n    //% help=radio/receive-number\n    //% weight=46\n    //% blockId=radio_datagram_receive block=\"radio receive number\" blockGap=8\n    //% deprecated=true\n    export function receiveNumber(): number {\n        lastPacket = RadioPacket.getPacket(readRawPacket());\n        return receivedNumber();\n    }\n\n    /**\n     * Reads the next packet from the radio queue and returns the packet's string\n     * payload or the empty string if the packet did not contain a string.\n     */\n    //% blockId=radio_datagram_receive_string block=\"radio receive string\" blockGap=8\n    //% weight=44\n    //% help=radio/receive-string\n    //% deprecated=true\n    export function receiveString(): string {\n        lastPacket = RadioPacket.getPacket(readRawPacket());\n        return receivedString();\n    }\n\n    /**\n     * Gets the received signal strength indicator (RSSI) from the last packet taken\n     * from the radio queue (via ``receiveNumber``, ``receiveString``, etc). Not supported in simulator.\n     */\n    //% help=radio/received-signal-strength\n    //% weight=40\n    //% blockId=radio_datagram_rssi block=\"radio received signal strength\"\n    //% deprecated=true blockHidden=true\n    export function receivedSignalStrength(): number {\n        return lastPacket ? lastPacket.signal : 0;\n    }\n\n    /**\n    * Reads the next packet from the radio queue and and writes it to serial\n    * as JSON.\n    */\n    //% help=radio/write-value-to-serial\n    //% weight=3\n    //% blockId=radio_write_value_serial block=\"radio write value to serial\"\n    //% deprecated=true\n    export function writeValueToSerial() {\n        const p = RadioPacket.getPacket(radio.readRawPacket());\n        if(p)\n            writeToSerial(p);\n    }\n\n    /**\n    * Writes the last received packet to serial as JSON. This should be called\n    * within an ``onDataPacketReceived`` callback.\n    */\n    //% help=radio/write-received-packet-to-serial\n    //% weight=3\n    //% blockId=radio_write_packet_serial block=\"radio write received packet to serial\"\n    //% advanced=true deprecated=true\n    export function writeReceivedPacketToSerial() {\n        if (lastPacket) writeToSerial(lastPacket)\n    }\n\n    function writeToSerial(packet: RadioPacket) {\n        serial.writeString(\"{\");\n        serial.writeString(\"\\\"t\\\":\");\n        serial.writeString(\"\" + packet.time);\n        serial.writeString(\",\\\"s\\\":\");\n        serial.writeString(\"\" + packet.serial);\n\n        if (packet.hasString()) {\n            serial.writeString(\",\\\"n\\\":\\\"\");\n            serial.writeString(packet.stringPayload);\n            serial.writeString(\"\\\"\");\n        }\n        if (packet.packetType == PACKET_TYPE_BUFFER) {\n            serial.writeString(\",\\\"b\\\":\\\"\");\n            // TODO: proper base64 encoding\n            serial.writeString(packet.bufferPayload.toString());\n            serial.writeString(\"\\\"\");\n        }\n        if (packet.hasNumber()) {\n            serial.writeString(\",\\\"v\\\":\");\n            serial.writeString(\"\" + packet.numberPayload);\n        }\n\n        serial.writeString(\"}\\r\\n\");\n    }\n}"},"devices":{"README.md":"# devices\n","devices.cpp":"#include \"pxt.h\"\n#include \"MESEvents.h\"\n\nusing namespace pxt;\n\nenum class MesCameraEvent {\n    //% block=\"take photo\"\n    TakePhoto = MES_CAMERA_EVT_TAKE_PHOTO,\n    //% block=\"start video capture\"\n    StartVideoCapture = MES_CAMERA_EVT_START_VIDEO_CAPTURE,\n    //% block=\"stop video capture\"\n    StopVideoCapture = MES_CAMERA_EVT_STOP_VIDEO_CAPTURE,\n    //% block=\"toggle front-rear\"\n    ToggleFrontRear = MES_CAMERA_EVT_TOGGLE_FRONT_REAR,\n    //% block=\"launch photo mode\"\n    LaunchPhotoMode = MES_CAMERA_EVT_LAUNCH_PHOTO_MODE,\n    //% block=\"launch video mode\"\n    LaunchVideoMode = MES_CAMERA_EVT_LAUNCH_VIDEO_MODE,\n    //% block=\"stop photo mode\"\n    StopPhotoMode = MES_CAMERA_EVT_STOP_PHOTO_MODE,\n    //% block=\"stop video mode\"\n    StopVideoMode = MES_CAMERA_EVT_STOP_VIDEO_MODE,\n};\n\nenum class MesAlertEvent {\n    //% block=\"display toast\"\n    DisplayToast = MES_ALERT_EVT_DISPLAY_TOAST,\n    //% block=\"vibrate\"\n    Vibrate = MES_ALERT_EVT_VIBRATE,\n    //% block=\"play sound\"\n    PlaySound = MES_ALERT_EVT_PLAY_SOUND,\n    //% block=\"play ring tone\"\n    PlayRingtone = MES_ALERT_EVT_PLAY_RINGTONE,\n    //% block=\"find my phone\"\n    FindMyPhone = MES_ALERT_EVT_FIND_MY_PHONE,\n    //% block=\"ring alarm\"\n    RingAlarm = MES_ALERT_EVT_ALARM1,\n    //% block=\"ring alarm 2\"\n    RingAlarm2 = MES_ALERT_EVT_ALARM2,\n    //% block=\"ring alarm 3\"\n    RingAlarm3 = MES_ALERT_EVT_ALARM3,\n    //% block=\"ring alarm 4\"\n    RingAlarm4 = MES_ALERT_EVT_ALARM4,\n    //% block=\"ring alarm 5\"\n    RingAlarm5 = MES_ALERT_EVT_ALARM5,\n    //% block=\"ring alarm 6\"\n    RingAlarm6 = MES_ALERT_EVT_ALARM6,\n};\n\nenum class MesDeviceInfo {\n    //% block=\"incoming call\"\n    IncomingCall = MES_DEVICE_INCOMING_CALL,\n    //% block=\"incoming message\"\n    IncomingMessage = MES_DEVICE_INCOMING_MESSAGE,\n    //% block=\"orientation landscape\"\n    OrientationLandscape = MES_DEVICE_ORIENTATION_LANDSCAPE,\n    //% block=\"orientation portrait\"\n    OrientationPortrait = MES_DEVICE_ORIENTATION_PORTRAIT,\n    //% block=\"shaken\"\n    Shaken = MES_DEVICE_GESTURE_DEVICE_SHAKEN,\n    //% block=\"display off\"\n    DisplayOff = MES_DEVICE_DISPLAY_OFF,\n    //% block=\"display on\"\n    DisplayOn = MES_DEVICE_DISPLAY_ON,\n};\n\nenum class MesRemoteControlEvent {\n    //% block=\"play\"\n    play = MES_REMOTE_CONTROL_EVT_PLAY,\n    //% block=\"pause\"\n    pause = MES_REMOTE_CONTROL_EVT_PAUSE,\n    //% block=\"stop\"\n    stop = MES_REMOTE_CONTROL_EVT_STOP,\n    //% block=\"next track\"\n    nextTrack = MES_REMOTE_CONTROL_EVT_NEXTTRACK,\n    //% block=\"previous track\"\n    previousTrack = MES_REMOTE_CONTROL_EVT_PREVTRACK,\n    //% block=\"forward\"\n    forward = MES_REMOTE_CONTROL_EVT_FORWARD,\n    //% block=\"rewind\"\n    rewind = MES_REMOTE_CONTROL_EVT_REWIND,\n    //% block=\"volume up\"\n    volumeUp = MES_REMOTE_CONTROL_EVT_VOLUMEUP,\n    //% block=\"volume down\"\n    volumeDown = MES_REMOTE_CONTROL_EVT_VOLUMEDOWN,\n};\n\n/**\n * Control a phone with the BBC micro:bit via Bluetooth.\n */\n//% color=#008272 weight=80 icon=\"\\uf10b\"\nnamespace devices {\n\n    static int _signalStrength = -1;\n    static void signalStrengthHandler(MicroBitEvent ev) { \n        // keep in sync with MESEvents.h\n        _signalStrength = ev.value - 1; \n    }\n    static void initSignalStrength() {\n        if (_signalStrength < 0) {\n            _signalStrength = 0;\n            uBit.messageBus.listen(MES_SIGNAL_STRENGTH_ID, MICROBIT_EVT_ANY, signalStrengthHandler);\n        }        \n    }\n    \n    /**\n     * Returns the last signal strength reported by the paired device.\n     */\n    //% help=devices/signal-strength weight=24\n    //% blockId=devices_signal_strength block=\"signal strength\" blockGap=14 icon=\"\\uf012\" blockGap=14\n    int signalStrength() {\n        initSignalStrength();\n        return _signalStrength;\n    }\n\n    /**\n     * Registers code to run when the device notifies about a change of signal strength.\n     * @param body Code run when the signal strength changes.\n     */\n    //% weight=23 help=devices/on-signal-strength-changed\n    //% blockId=devices_signal_strength_changed_event block=\"on signal strength changed\" icon=\"\\uf012\"\n    void onSignalStrengthChanged(Action body) {\n        initSignalStrength();    \n        registerWithDal(MES_SIGNAL_STRENGTH_ID, MICROBIT_EVT_ANY, body);\n    }\n}\n","devices.ts":"\nnamespace devices {\n    /**\n     * Sends a ``camera`` command to the parent device.\n     * @param event event description\n     */\n    //% weight=30 help=devices/tell-camera-to\n    //% blockId=devices_camera icon=\"\\uf030\" block=\"tell camera to|%property\" blockGap=8\n    export function tellCameraTo(event: MesCameraEvent) {\n        control.raiseEvent(DAL.MES_CAMERA_ID, event);\n    }\n\n    /**\n     * Sends a ``remote control`` command to the parent device.\n     * @param event event description\n     */\n    //% weight=29 help=devices/tell-remote-control-to\n    //% blockId=devices_remote_control block=\"tell remote control to|%property\" blockGap=14 icon=\"\\uf144\"\n    export function tellRemoteControlTo(event: MesRemoteControlEvent) {\n        control.raiseEvent(DAL.MES_REMOTE_CONTROL_ID, event);\n    }\n\n    /**\n     * Sends an ``alert`` command to the parent device.\n     * @param event event description\n     */\n    //% weight=27 help=devices/raise-alert-to\n    //% blockId=devices_alert block=\"raise alert to|%property\" icon=\"\\uf0f3\"\n    export function raiseAlertTo(event: MesAlertEvent) {\n        control.raiseEvent(DAL.MES_ALERTS_ID, event);\n    }\n\n    /**\n     * Registers code to run when the device notifies about a particular event.\n     * @param event event description\n     * @param body code handler when event is triggered\n     */\n    //% help=devices/on-notified weight=26\n    //% blockId=devices_device_info_event block=\"on notified|%event\" icon=\"\\uf10a\"\n    export function onNotified(event: MesDeviceInfo, body: () => void) {\n        control.onEvent(DAL.MES_DEVICE_INFO_ID, event, body);\n    }\n\n    /**\n     * Register code to run when the micro:bit receives a command from the paired gamepad.\n     * @param name button name\n     * @param body code to run when button is pressed\n     */\n    //% help=devices/on-gamepad-button weight=40\n    //% weight=25\n    //% blockId=devices_gamepad_event block=\"on gamepad button|%NAME\" icon=\"\\uf11b\"\n    export function onGamepadButton(name: MesDpadButtonInfo, body: () => void) {\n        control.onEvent(DAL.MES_DPAD_CONTROLLER_ID, name, body);\n    }\n}","enums.d.ts":"// Auto-generated. Do not edit.\n\n\n    declare const enum MesCameraEvent {\n    //% block=\"take photo\"\n    TakePhoto = 3,  // MES_CAMERA_EVT_TAKE_PHOTO\n    //% block=\"start video capture\"\n    StartVideoCapture = 4,  // MES_CAMERA_EVT_START_VIDEO_CAPTURE\n    //% block=\"stop video capture\"\n    StopVideoCapture = 5,  // MES_CAMERA_EVT_STOP_VIDEO_CAPTURE\n    //% block=\"toggle front-rear\"\n    ToggleFrontRear = 8,  // MES_CAMERA_EVT_TOGGLE_FRONT_REAR\n    //% block=\"launch photo mode\"\n    LaunchPhotoMode = 1,  // MES_CAMERA_EVT_LAUNCH_PHOTO_MODE\n    //% block=\"launch video mode\"\n    LaunchVideoMode = 2,  // MES_CAMERA_EVT_LAUNCH_VIDEO_MODE\n    //% block=\"stop photo mode\"\n    StopPhotoMode = 6,  // MES_CAMERA_EVT_STOP_PHOTO_MODE\n    //% block=\"stop video mode\"\n    StopVideoMode = 7,  // MES_CAMERA_EVT_STOP_VIDEO_MODE\n    }\n\n\n    declare const enum MesAlertEvent {\n    //% block=\"display toast\"\n    DisplayToast = 1,  // MES_ALERT_EVT_DISPLAY_TOAST\n    //% block=\"vibrate\"\n    Vibrate = 2,  // MES_ALERT_EVT_VIBRATE\n    //% block=\"play sound\"\n    PlaySound = 3,  // MES_ALERT_EVT_PLAY_SOUND\n    //% block=\"play ring tone\"\n    PlayRingtone = 4,  // MES_ALERT_EVT_PLAY_RINGTONE\n    //% block=\"find my phone\"\n    FindMyPhone = 5,  // MES_ALERT_EVT_FIND_MY_PHONE\n    //% block=\"ring alarm\"\n    RingAlarm = 6,  // MES_ALERT_EVT_ALARM1\n    //% block=\"ring alarm 2\"\n    RingAlarm2 = 7,  // MES_ALERT_EVT_ALARM2\n    //% block=\"ring alarm 3\"\n    RingAlarm3 = 8,  // MES_ALERT_EVT_ALARM3\n    //% block=\"ring alarm 4\"\n    RingAlarm4 = 9,  // MES_ALERT_EVT_ALARM4\n    //% block=\"ring alarm 5\"\n    RingAlarm5 = 10,  // MES_ALERT_EVT_ALARM5\n    //% block=\"ring alarm 6\"\n    RingAlarm6 = 11,  // MES_ALERT_EVT_ALARM6\n    }\n\n\n    declare const enum MesDeviceInfo {\n    //% block=\"incoming call\"\n    IncomingCall = 7,  // MES_DEVICE_INCOMING_CALL\n    //% block=\"incoming message\"\n    IncomingMessage = 8,  // MES_DEVICE_INCOMING_MESSAGE\n    //% block=\"orientation landscape\"\n    OrientationLandscape = 1,  // MES_DEVICE_ORIENTATION_LANDSCAPE\n    //% block=\"orientation portrait\"\n    OrientationPortrait = 2,  // MES_DEVICE_ORIENTATION_PORTRAIT\n    //% block=\"shaken\"\n    Shaken = 4,  // MES_DEVICE_GESTURE_DEVICE_SHAKEN\n    //% block=\"display off\"\n    DisplayOff = 5,  // MES_DEVICE_DISPLAY_OFF\n    //% block=\"display on\"\n    DisplayOn = 6,  // MES_DEVICE_DISPLAY_ON\n    }\n\n\n    declare const enum MesRemoteControlEvent {\n    //% block=\"play\"\n    play = 1,  // MES_REMOTE_CONTROL_EVT_PLAY\n    //% block=\"pause\"\n    pause = 2,  // MES_REMOTE_CONTROL_EVT_PAUSE\n    //% block=\"stop\"\n    stop = 3,  // MES_REMOTE_CONTROL_EVT_STOP\n    //% block=\"next track\"\n    nextTrack = 4,  // MES_REMOTE_CONTROL_EVT_NEXTTRACK\n    //% block=\"previous track\"\n    previousTrack = 5,  // MES_REMOTE_CONTROL_EVT_PREVTRACK\n    //% block=\"forward\"\n    forward = 6,  // MES_REMOTE_CONTROL_EVT_FORWARD\n    //% block=\"rewind\"\n    rewind = 7,  // MES_REMOTE_CONTROL_EVT_REWIND\n    //% block=\"volume up\"\n    volumeUp = 8,  // MES_REMOTE_CONTROL_EVT_VOLUMEUP\n    //% block=\"volume down\"\n    volumeDown = 9,  // MES_REMOTE_CONTROL_EVT_VOLUMEDOWN\n    }\ndeclare namespace devices {\n}\n\n// Auto-generated. Do not edit. Really.\n","pxt.json":"{\n    \"name\": \"devices\",\n    \"description\": \"BETA -  Camera, remote control and other Bluetooth services. App required.\",\n    \"dependencies\": {\n        \"core\": \"*\",\n        \"bluetooth\": \"*\"\n    },\n    \"files\": [\n        \"README.md\",\n        \"enums.d.ts\",\n        \"shims.d.ts\",\n        \"devices.cpp\",\n        \"devices.ts\"\n    ],\n    \"public\": true,\n    \"targetVersions\": {\n        \"target\": \"7.1.42\",\n        \"pxt\": \"11.4.28\"\n    },\n    \"icon\": \"./static/packages/devices/icon.png\",\n    \"hidden\": true\n}\n","shims.d.ts":"// Auto-generated. Do not edit.\n\n\n    /**\n     * Control a phone with the BBC micro:bit via Bluetooth.\n     */\n    //% color=#008272 weight=80 icon=\"\\uf10b\"\ndeclare namespace devices {\n\n    /**\n     * Returns the last signal strength reported by the paired device.\n     */\n    //% help=devices/signal-strength weight=24\n    //% blockId=devices_signal_strength block=\"signal strength\" blockGap=14 icon=\"\\uf012\" blockGap=14 shim=devices::signalStrength\n    function signalStrength(): int32;\n\n    /**\n     * Registers code to run when the device notifies about a change of signal strength.\n     * @param body Code run when the signal strength changes.\n     */\n    //% weight=23 help=devices/on-signal-strength-changed\n    //% blockId=devices_signal_strength_changed_event block=\"on signal strength changed\" icon=\"\\uf012\" shim=devices::onSignalStrengthChanged\n    function onSignalStrengthChanged(body: () => void): void;\n}\n\n// Auto-generated. Do not edit. Really.\n"},"bluetooth":{"BLEHF2Service.cpp":"#include \"MicroBitConfig.h\"\n#include \"BLEHF2Service.h\"\n#include \"MicroBitEvent.h\"\n\n//================================================================\n#if MICROBIT_CODAL\n//================================================================\n\nconst uint8_t  BLEHF2Service::service_base_uuid[ 16] =\n{ 0xb1,0x12,0x00,0x00,0x26,0x79,0x30,0xda,0xa2,0x6e,0x02,0x73,0xb6,0x04,0x38,0x49 };\n\nconst uint8_t  BLEHF2Service::char_base_uuid[ 16] =\n{ 0xb1,0x12,0x00,0x00,0x26,0x79,0x30,0xda,0xa2,0x6e,0x02,0x73,0xb6,0x04,0x38,0x4a };\n\nconst uint16_t BLEHF2Service::serviceUUID               = 0xf5e6;\nconst uint16_t BLEHF2Service::charUUID[ mbbs_cIdxCOUNT] = { 0xf5e6 };\n\n\nBLEHF2Service::BLEHF2Service(BLEDevice &_ble) :\n        ble(_ble)\n{\n    // Initialise our characteristic values.\n    memset(&txCharacteristicMessage, 0, sizeof(txCharacteristicMessage));\n    \n    // Register the base UUID and create the service.\n    RegisterBaseUUID( service_base_uuid);\n    CreateService( serviceUUID);\n\n    RegisterBaseUUID( char_base_uuid);\n    CreateCharacteristic( mbbs_cIdxMESSAGE, charUUID[ mbbs_cIdxMESSAGE],\n                         (uint8_t *)&txCharacteristicMessage,\n                         sizeof(txCharacteristicMessage), sizeof(txCharacteristicMessage),\n                         microbit_propNOTIFY);\n}\n\nvoid BLEHF2Service::sendSerial(const char *data, int len, bool isError) {\n    if (getConnected())\n    {\n        int32_t sent = 0;\n        while(sent < len) {\n            int32_t n = min(BLEHF2_DATA_LENGTH, len - sent);\n            txCharacteristicMessage.command = (isError ? BLEHF2_FLAG_SERIAL_OUT : BLEHF2_FLAG_SERIAL_ERR) | n;\n            memcpy(&txCharacteristicMessage.data, data + sent, n);\n            notifyChrValue(mbbs_cIdxMESSAGE,(uint8_t *)&txCharacteristicMessage, sizeof(txCharacteristicMessage));\n            sent += n;\n        }\n    }\n}\n\n//================================================================\n#else // MICROBIT_CODAL\n//================================================================\n\n#include \"ble/UUID.h\"\n\nBLEHF2Service::BLEHF2Service(BLEDevice &_ble) :\n        ble(_ble)\n{\n    GattCharacteristic  txCharacteristic(BLEHF2TxCharacteristicUUID, (uint8_t *)&txCharacteristicMessage, 0,\n    sizeof(txCharacteristicMessage), GattCharacteristic::BLE_GATT_CHAR_PROPERTIES_NOTIFY);\n\n    // Initialise our characteristic values.\n    memset(&txCharacteristicMessage, 0, sizeof(txCharacteristicMessage));\n\n    // Set default security requirements\n    txCharacteristic.requireSecurity(SecurityManager::MICROBIT_BLE_SECURITY_LEVEL);\n\n    // setup GATT table\n    GattCharacteristic *characteristics[] = {&txCharacteristic};\n    GattService service(BLEHF2ServiceUUID, characteristics, sizeof(characteristics) / sizeof(GattCharacteristic *));\n    ble.addService(service);\n\n    // retreive handles\n    txCharacteristicHandle = txCharacteristic.getValueHandle();\n\n    // initialize data\n    ble.gattServer().write(txCharacteristicHandle,(uint8_t *)&txCharacteristicMessage, sizeof(txCharacteristicMessage));\n}\n\nvoid BLEHF2Service::sendSerial(const char *data, int len, bool isError) {\n    if (ble.getGapState().connected)\n    {\n        int32_t sent = 0;\n        while(sent < len) {\n            int32_t n = min(BLEHF2_DATA_LENGTH, len - sent);\n            txCharacteristicMessage.command = (isError ? BLEHF2_FLAG_SERIAL_OUT : BLEHF2_FLAG_SERIAL_ERR) | n;\n            memcpy(&txCharacteristicMessage.data, data + sent, n);\n            ble.gattServer().notify(txCharacteristicHandle,(uint8_t *)&txCharacteristicMessage, sizeof(txCharacteristicMessage));\n            sent += n;\n        }\n    }\n}\n\nconst uint8_t  BLEHF2ServiceUUID[] = {\n    0xb1,0x12,0xf5,0xe6,0x26,0x79,0x30,0xda,0xa2,0x6e,0x02,0x73,0xb6,0x04,0x38,0x49\n};\n\nconst uint8_t  BLEHF2TxCharacteristicUUID[] = {\n    0xb1,0x12,0xf5,0xe6,0x26,0x79,0x30,0xda,0xa2,0x6e,0x02,0x73,0xb6,0x04,0x38,0x4a\n};\n\n//================================================================\n#endif // MICROBIT_CODAL\n//================================================================\n","BLEHF2Service.h":"#ifndef BLE_HF2_SERVICE_H\n#define BLE_HF2_SERVICE_H\n\n#include \"MicroBitConfig.h\"\n#include \"MicroBitThermometer.h\"\n#include \"EventModel.h\"\n#include \"pxt.h\"\n\n#define HF2_ID 9501\n\n#define BLEHF2_FLAG_SERIAL_OUT 0x80\n#define BLEHF2_FLAG_SERIAL_ERR 0xC0\n#define BLEHF2_DATA_LENGTH 19\n\n// UUIDs for our service and characteristics\nextern const uint8_t  BLEHF2ServiceUUID[];\nextern const uint8_t  BLEHF2TxCharacteristicUUID[];\n\nstruct BLEHF2Packet {\n  uint8_t command;\n  uint8_t data[BLEHF2_DATA_LENGTH];\n};\n\n//================================================================\n#if MICROBIT_CODAL\n//================================================================\n\n#include \"MicroBitBLEManager.h\"\n#include \"MicroBitBLEService.h\"\n\nclass BLEHF2Service : public MicroBitBLEService\n{\n    public:\n\n    /**\n      * Constructor.\n      * Create a representation of the TemperatureService\n      * @param _ble The instance of a BLE device that we're running on.\n      */\n    BLEHF2Service(BLEDevice &_ble);\n\n    /**\n    * Sends text\n    */\n    void sendSerial(const char *data, int len, bool isError);\n\n    private:\n\n    // Bluetooth stack we're running on.\n    BLEDevice &ble;\n\n    // memory for buffers.\n    BLEHF2Packet txCharacteristicMessage;\n    \n    // Index for each charactersitic in arrays of handles and UUIDs\n    typedef enum mbbs_cIdx\n    {\n        mbbs_cIdxMESSAGE,\n        mbbs_cIdxCOUNT\n    } mbbs_cIdx;\n    \n    // UUIDs for our service and characteristics\n    static const uint8_t  service_base_uuid[ 16];\n    static const uint8_t  char_base_uuid[ 16];\n    static const uint16_t serviceUUID;\n    static const uint16_t charUUID[ mbbs_cIdxCOUNT];\n    \n    // Data for each characteristic when they are held by Soft Device.\n    MicroBitBLEChar      chars[ mbbs_cIdxCOUNT];\n\n    public:\n    \n    int              characteristicCount()          { return mbbs_cIdxCOUNT; };\n    MicroBitBLEChar *characteristicPtr( int idx)    { return &chars[ idx]; };\n};\n\n//================================================================\n#else // MICROBIT_CODAL\n//================================================================\n\n#include \"ble/BLE.h\"\n\nclass BLEHF2Service\n{\n    public:\n\n    /**\n      * Constructor.\n      * Create a representation of the TemperatureService\n      * @param _ble The instance of a BLE device that we're running on.\n      */\n    BLEHF2Service(BLEDevice &_ble);\n\n    /**\n    * Sends text\n    */\n    void sendSerial(const char *data, int len, bool isError); \n\n    private:\n\n    // Bluetooth stack we're running on.\n    BLEDevice &ble;\n\n    // memory for buffers.\n    BLEHF2Packet txCharacteristicMessage;\n\n    // Handles to access each characteristic when they are held by Soft Device.\n    GattAttribute::Handle_t txCharacteristicHandle;\n};\n\n//================================================================\n#endif // MICROBIT_CODAL\n//================================================================\n\n#endif\n","README.md":"# Bluetooth services\n","bluetooth.cpp":"#include \"pxt.h\"\n#include \"MESEvents.h\"\n#include \"MicroBitUARTService.h\"\n#include \"BLEHF2Service.h\"\n\nusing namespace pxt;\n\n/**\n * Support for additional Bluetooth services.\n */\n//% color=#0082FB weight=96 icon=\"\\uf294\"\nnamespace bluetooth {\n    MicroBitUARTService *uart = NULL;\n    BLEHF2Service* pHF2 = NULL;\n\n    //%\n    void __log(int priority, String msg) {\n        if (NULL == pHF2)\n            pHF2 = new BLEHF2Service(*uBit.ble);\n        pHF2->sendSerial(msg->getUTF8Data(), msg->getUTF8Size(), false);\n    }\n\n    /**\n    *  Starts the Bluetooth accelerometer service\n    */\n    //% help=bluetooth/start-accelerometer-service\n    //% blockId=bluetooth_start_accelerometer_service block=\"bluetooth accelerometer service\"\n    //% parts=\"bluetooth\" weight=90 blockGap=8\n    void startAccelerometerService() {\n        new MicroBitAccelerometerService(*uBit.ble, uBit.accelerometer);        \n    }   \n\n    /**\n    *  Starts the Bluetooth button service\n    */\n    //% help=bluetooth/start-button-service\n    //% blockId=bluetooth_start_button_service block=\"bluetooth button service\" blockGap=8\n    //% parts=\"bluetooth\" weight=89\n    void startButtonService() {\n        new MicroBitButtonService(*uBit.ble);      \n    }\n\n    /**\n    *  Starts the Bluetooth IO pin service.\n    */\n    //% help=bluetooth/start-io-pin-service\n    //% blockId=bluetooth_start_io_pin_service block=\"bluetooth io pin service\" blockGap=8\n    //% parts=\"bluetooth\" weight=88\n    void startIOPinService() {\n        new MicroBitIOPinService(*uBit.ble, uBit.io);\n    }\n\n    /**\n    *  Starts the Bluetooth LED service\n    */\n    //% help=bluetooth/start-led-service\n    //% blockId=bluetooth_start_led_service block=\"bluetooth led service\" blockGap=8\n    //% parts=\"bluetooth\" weight=87\n    void startLEDService() {\n        new MicroBitLEDService(*uBit.ble, uBit.display);\n    }\n\n    /**\n    *  Starts the Bluetooth temperature service\n    */\n    //% help=bluetooth/start-temperature-service\n    //% blockId=bluetooth_start_temperature_service block=\"bluetooth temperature service\" blockGap=8\n    //% parts=\"bluetooth\" weight=86\n    void startTemperatureService() {    \n        new MicroBitTemperatureService(*uBit.ble, uBit.thermometer);        \n    }\n\n    /**\n    *  Starts the Bluetooth magnetometer service\n    */\n    //% help=bluetooth/start-magnetometer-service\n    //% blockId=bluetooth_start_magnetometer_service block=\"bluetooth magnetometer service\"\n    //% parts=\"bluetooth\" weight=85\n    void startMagnetometerService() {    \n        new MicroBitMagnetometerService(*uBit.ble, uBit.compass); \n    }\n\n\n    /**\n    *  Starts the Bluetooth UART service\n    */\n    //% help=bluetooth/start-uart-service\n    //% blockId=bluetooth_start_uart_service block=\"bluetooth uart service\"\n    //% parts=\"bluetooth\" advanced=true\n    void startUartService() {\n        if (uart) return;\n        // 61 octet buffer size is 3 x (MTU - 3) + 1\n        // MTU on nRF51822 is 23 octets. 3 are used by Attribute Protocol header data leaving 20 octets for payload\n        // So we allow a RX buffer that can contain 3 x max length messages plus one octet for a terminator character\n        uart = new MicroBitUARTService(*uBit.ble, 61, 60);\n    }\n    \n    //%\n    void uartWriteString(String data) {\n        startUartService();\n    \tuart->send(MSTR(data));\n    }    \n\n    //%\n    String uartReadUntil(String del) {\n        startUartService();\n        return PSTR(uart->readUntil(MSTR(del)));\n    }    \n\n\n    /**\n    * Sends a buffer of data via Bluetooth UART\n    */\n    //%\n    void uartWriteBuffer(Buffer buffer) {\n        startUartService();\n        uart->send(buffer->data, buffer->length);\n    }\n\n    /**\n    * Reads buffered UART data into a buffer\n    */\n    //%\n    Buffer uartReadBuffer() {\n        startUartService();\n        int bytes = uart->rxBufferedSize();\n        auto buffer = mkBuffer(NULL, bytes);\n        auto res = buffer;\n        registerGCObj(buffer);\n        int read = uart->read(buffer->data, buffer->length);\n        // read failed\n        if (read < 0) {\n            res = mkBuffer(NULL, 0);\n        } else if (read != buffer->length) {\n            // could not fill the buffer\n            res = mkBuffer(buffer->data, read); \n        }\n        unregisterGCObj(buffer);\n        return res;\n    }\n\n    /**\n    * Registers an event to be fired when one of the delimiter is matched.\n    * @param delimiters the characters to match received characters against.\n    */\n    //% help=bluetooth/on-uart-data-received\n    //% weight=18 blockId=bluetooth_on_data_received block=\"bluetooth|on data received %delimiters=serial_delimiter_conv\"\n    void onUartDataReceived(String delimiters, Action body) {\n      startUartService();\n      uart->eventOn(MSTR(delimiters));\n      registerWithDal(MICROBIT_ID_BLE_UART, MICROBIT_UART_S_EVT_DELIM_MATCH, body);\n    }\n\n    /**\n     * Register code to run when the micro:bit is connected to over Bluetooth\n     * @param body Code to run when a Bluetooth connection is established\n     */\n    //% help=bluetooth/on-bluetooth-connected weight=20\n    //% blockId=bluetooth_on_connected block=\"on bluetooth connected\" blockGap=8\n    //% parts=\"bluetooth\"\n    void onBluetoothConnected(Action body) {\n        registerWithDal(MICROBIT_ID_BLE, MICROBIT_BLE_EVT_CONNECTED, body);\n    }    \n\n     /**\n     * Register code to run when a bluetooth connection to the micro:bit is lost\n     * @param body Code to run when a Bluetooth connection is lost\n     */\n    //% help=bluetooth/on-bluetooth-disconnected weight=19\n    //% blockId=bluetooth_on_disconnected block=\"on bluetooth disconnected\"\n    //% parts=\"bluetooth\"\n    void onBluetoothDisconnected(Action body) {\n        registerWithDal(MICROBIT_ID_BLE, MICROBIT_BLE_EVT_DISCONNECTED, body);\n    } \n\n    const int8_t CALIBRATED_POWERS[] = {-49, -37, -33, -28, -25, -20, -15, -10};\n    /**\n    * Advertise an Eddystone URL\n\t* @param url the url to transmit. Must be no longer than the supported eddystone url length, eg: \"https://makecode.com\"\n\t* @param power power level between 0 and 7, eg: 7\n    * @param connectable true to keep bluetooth connectable for other services, false otherwise.\n    */\n    //% blockId=eddystone_advertise_url block=\"bluetooth advertise url %url|with power %power|connectable %connectable\"\n    //% parts=bluetooth weight=11 blockGap=8\n    //% help=bluetooth/advertise-url blockExternalInputs=1\n    //% hidden=1 deprecated=1\n    void advertiseUrl(String url, int power, bool connectable) {\n#if CONFIG_ENABLED(MICROBIT_BLE_EDDYSTONE_URL)\n        power = min(MICROBIT_BLE_POWER_LEVELS-1, max(0, power));\n        int8_t level = CALIBRATED_POWERS[power];\n        uBit.bleManager.advertiseEddystoneUrl(MSTR(url), level, connectable);\n        uBit.bleManager.setTransmitPower(power);\n#endif\n    }\n\n    /**\n    * Advertise an Eddystone UID\n\t* @param nsAndInstance 16 bytes buffer of namespace (bytes 0-9) and instance (bytes 10-15)\n\t* @param power power level between 0 and 7, eg: 7\n    * @param connectable true to keep bluetooth connectable for other services, false otherwise.\n    */\n    //% parts=bluetooth weight=12 advanced=true deprecated=1\n    void advertiseUidBuffer(Buffer nsAndInstance, int power, bool connectable) {\n#if CONFIG_ENABLED(MICROBIT_BLE_EDDYSTONE_UID)        \n        auto buf = nsAndInstance;\n        if (buf->length != 16) return;\n\n        power = min(MICROBIT_BLE_POWER_LEVELS-1, max(0, power));\n        int8_t level = CALIBRATED_POWERS[power];\n        uBit.bleManager.advertiseEddystoneUid((const char*)buf->data, (const char*)buf->data + 10, level, connectable);\n#endif\n    }\n\n    /**\n    * Sets the bluetooth transmit power between 0 (minimal) and 7 (maximum).\n    * @param power power level between 0 (minimal) and 7 (maximum), eg: 7.\n    */\n    //% parts=bluetooth weight=5 help=bluetooth/set-transmit-power advanced=true\n    //% blockId=bluetooth_settransmitpower block=\"bluetooth set transmit power %power\"\n    void setTransmitPower(int power) {\n        uBit.bleManager.setTransmitPower(min(MICROBIT_BLE_POWER_LEVELS-1, max(0, power)));\n    }\n\n    /**\n    * Stops advertising Eddystone end points\n    */\n    //% blockId=eddystone_stop_advertising block=\"bluetooth stop advertising\"\n    //% parts=bluetooth weight=10\n    //% help=bluetooth/stop-advertising advanced=true\n    //% hidden=1 deprecated=1\n    void stopAdvertising() {\n        uBit.bleManager.stopAdvertising();\n    } \n}","bluetooth.ts":"/// <reference no-default-lib=\"true\"/>\n/**\n * Support for additional Bluetooth services.\n */\n//% color=#007EF4 weight=96 icon=\"\\uf294\"\nnamespace bluetooth {\n    export let NEW_LINE = \"\\r\\n\";\n\n    /**\n     * Internal use\n     */\n    //% shim=bluetooth::__log\n    export function __log(priority: number, msg: string) {\n        return;\n    }\n    console.addListener(function (_pri, msg) { __log(_pri, msg) });\n\n    /**\n    *  Writes to the Bluetooth UART service buffer. From there the data is transmitted over Bluetooth to a connected device.\n    */\n    //% help=bluetooth/uart-write-string weight=80\n    //% blockId=bluetooth_uart_write block=\"bluetooth uart|write string %data\" blockGap=8\n    //% parts=\"bluetooth\" shim=bluetooth::uartWriteString advanced=true\n    export function uartWriteString(data: string): void {\n        console.log(data)\n    }\n\n    /**\n    *  Writes to the Bluetooth UART service buffer. From there the data is transmitted over Bluetooth to a connected device.\n    */\n    //% help=bluetooth/uart-write-line weight=79\n    //% blockId=bluetooth_uart_line block=\"bluetooth uart|write line %data\" blockGap=8\n    //% parts=\"bluetooth\" advanced=true\n    export function uartWriteLine(data: string): void {\n        uartWriteString(data + serial.NEW_LINE);\n    }\n\n    /**\n     * Prints a numeric value to the serial\n     */\n    //% help=bluetooth/uart-write-number weight=79\n    //% weight=89 blockGap=8 advanced=true\n    //% blockId=bluetooth_uart_writenumber block=\"bluetooth uart|write number %value\"\n    export function uartWriteNumber(value: number): void {\n        uartWriteString(value.toString());\n    }\n\n    /**\n     * Writes a ``name: value`` pair line to the serial.\n     * @param name name of the value stream, eg: x\n     * @param value to write\n     */\n    //% weight=88 weight=78\n    //% help=bluetooth/uart-write-value advanced=true\n    //% blockId=bluetooth_uart_writevalue block=\"bluetooth uart|write value %name|= %value\"\n    export function uartWriteValue(name: string, value: number): void {\n        uartWriteString((name ? name + \":\" : \"\") + value + NEW_LINE);\n    }\n\n    /**\n     *  Reads from the Bluetooth UART service buffer, returning its contents when the specified delimiter character is encountered.\n     */\n    //% help=bluetooth/uart-read-until weight=75\n    //% blockId=bluetooth_uart_read block=\"bluetooth uart|read until %del=serial_delimiter_conv\"\n    //% parts=\"bluetooth\" shim=bluetooth::uartReadUntil advanced=true\n    export function uartReadUntil(del: string): string {\n        // dummy implementation for simulator\n        return \"\"\n    }\n\n    /**\n    * Advertise an Eddystone UID\n    * @param ns 4 last bytes of the namespace uid\n    * @param instance 4 last bytes of the instance uid\n    * @param power power level between 0 and 7, eg: 7\n    * @param connectable true to keep bluetooth connectable for other services, false otherwise.\n    */\n    //% blockId=eddystone_advertise_uid block=\"bluetooth advertise UID|namespace (bytes 6-9)%ns|instance (bytes 2-6)%instance|with power %power|connectable %connectable\"\n    //% parts=bluetooth weight=12 blockGap=8\n    //% help=bluetooth/advertise-uid blockExternalInputs=1\n    //% hidden=1 deprecated=1\n    export function advertiseUid(ns: number, instance: number, power: number, connectable: boolean) {\n        const buf = pins.createBuffer(16);\n        buf.setNumber(NumberFormat.Int32BE, 6, ns);\n        buf.setNumber(NumberFormat.Int32BE, 12, instance);\n        bluetooth.advertiseUidBuffer(buf, power, connectable);\n    }\n}\n","enums.d.ts":"// Auto-generated. Do not edit.\ndeclare namespace bluetooth {\n}\n\n// Auto-generated. Do not edit. Really.\n","pxt.json":"{\n    \"name\": \"bluetooth\",\n    \"description\": \"Bluetooth services\",\n    \"dependencies\": {\n        \"core\": \"*\"\n    },\n    \"files\": [\n        \"README.md\",\n        \"enums.d.ts\",\n        \"shims.d.ts\",\n        \"bluetooth.ts\",\n        \"bluetooth.cpp\",\n        \"BLEHF2Service.h\",\n        \"BLEHF2Service.cpp\"\n    ],\n    \"public\": true,\n    \"targetVersions\": {\n        \"target\": \"7.1.42\",\n        \"pxt\": \"11.4.28\"\n    },\n    \"weight\": 10,\n    \"searchOnly\": true,\n    \"icon\": \"./static/packages/bluetooth/icon.png\",\n    \"yotta\": {\n        \"config\": {\n            \"microbit-dal\": {\n                \"bluetooth\": {\n                    \"enabled\": 1\n                }\n            }\n        },\n        \"optionalConfig\": {\n            \"microbit-dal\": {\n                \"stack_size\": 1280,\n                \"gatt_table_size\": \"0x700\"\n            }\n        },\n        \"userConfigs\": [\n            {\n                \"description\": \"Disable Bluetooth Event Service\",\n                \"config\": {\n                    \"microbit-dal\": {\n                        \"bluetooth\": {\n                            \"event_service\": 0\n                        }\n                    }\n                }\n            }\n        ]\n    }\n}\n","shims.d.ts":"// Auto-generated. Do not edit.\n\n\n    /**\n     * Support for additional Bluetooth services.\n     */\n    //% color=#0082FB weight=96 icon=\"\\uf294\"\ndeclare namespace bluetooth {\n\n    /**\n     *  Starts the Bluetooth accelerometer service\n     */\n    //% help=bluetooth/start-accelerometer-service\n    //% blockId=bluetooth_start_accelerometer_service block=\"bluetooth accelerometer service\"\n    //% parts=\"bluetooth\" weight=90 blockGap=8 shim=bluetooth::startAccelerometerService\n    function startAccelerometerService(): void;\n\n    /**\n     *  Starts the Bluetooth button service\n     */\n    //% help=bluetooth/start-button-service\n    //% blockId=bluetooth_start_button_service block=\"bluetooth button service\" blockGap=8\n    //% parts=\"bluetooth\" weight=89 shim=bluetooth::startButtonService\n    function startButtonService(): void;\n\n    /**\n     *  Starts the Bluetooth IO pin service.\n     */\n    //% help=bluetooth/start-io-pin-service\n    //% blockId=bluetooth_start_io_pin_service block=\"bluetooth io pin service\" blockGap=8\n    //% parts=\"bluetooth\" weight=88 shim=bluetooth::startIOPinService\n    function startIOPinService(): void;\n\n    /**\n     *  Starts the Bluetooth LED service\n     */\n    //% help=bluetooth/start-led-service\n    //% blockId=bluetooth_start_led_service block=\"bluetooth led service\" blockGap=8\n    //% parts=\"bluetooth\" weight=87 shim=bluetooth::startLEDService\n    function startLEDService(): void;\n\n    /**\n     *  Starts the Bluetooth temperature service\n     */\n    //% help=bluetooth/start-temperature-service\n    //% blockId=bluetooth_start_temperature_service block=\"bluetooth temperature service\" blockGap=8\n    //% parts=\"bluetooth\" weight=86 shim=bluetooth::startTemperatureService\n    function startTemperatureService(): void;\n\n    /**\n     *  Starts the Bluetooth magnetometer service\n     */\n    //% help=bluetooth/start-magnetometer-service\n    //% blockId=bluetooth_start_magnetometer_service block=\"bluetooth magnetometer service\"\n    //% parts=\"bluetooth\" weight=85 shim=bluetooth::startMagnetometerService\n    function startMagnetometerService(): void;\n\n    /**\n     *  Starts the Bluetooth UART service\n     */\n    //% help=bluetooth/start-uart-service\n    //% blockId=bluetooth_start_uart_service block=\"bluetooth uart service\"\n    //% parts=\"bluetooth\" advanced=true shim=bluetooth::startUartService\n    function startUartService(): void;\n\n    /**\n     * Sends a buffer of data via Bluetooth UART\n     */\n    //% shim=bluetooth::uartWriteBuffer\n    function uartWriteBuffer(buffer: Buffer): void;\n\n    /**\n     * Reads buffered UART data into a buffer\n     */\n    //% shim=bluetooth::uartReadBuffer\n    function uartReadBuffer(): Buffer;\n\n    /**\n     * Registers an event to be fired when one of the delimiter is matched.\n     * @param delimiters the characters to match received characters against.\n     */\n    //% help=bluetooth/on-uart-data-received\n    //% weight=18 blockId=bluetooth_on_data_received block=\"bluetooth|on data received %delimiters=serial_delimiter_conv\" shim=bluetooth::onUartDataReceived\n    function onUartDataReceived(delimiters: string, body: () => void): void;\n\n    /**\n     * Register code to run when the micro:bit is connected to over Bluetooth\n     * @param body Code to run when a Bluetooth connection is established\n     */\n    //% help=bluetooth/on-bluetooth-connected weight=20\n    //% blockId=bluetooth_on_connected block=\"on bluetooth connected\" blockGap=8\n    //% parts=\"bluetooth\" shim=bluetooth::onBluetoothConnected\n    function onBluetoothConnected(body: () => void): void;\n\n    /**\n     * Register code to run when a bluetooth connection to the micro:bit is lost\n     * @param body Code to run when a Bluetooth connection is lost\n     */\n    //% help=bluetooth/on-bluetooth-disconnected weight=19\n    //% blockId=bluetooth_on_disconnected block=\"on bluetooth disconnected\"\n    //% parts=\"bluetooth\" shim=bluetooth::onBluetoothDisconnected\n    function onBluetoothDisconnected(body: () => void): void;\n\n    /**\n     * Advertise an Eddystone URL\n     * @param url the url to transmit. Must be no longer than the supported eddystone url length, eg: \"https://makecode.com\"\n     * @param power power level between 0 and 7, eg: 7\n     * @param connectable true to keep bluetooth connectable for other services, false otherwise.\n     */\n    //% blockId=eddystone_advertise_url block=\"bluetooth advertise url %url|with power %power|connectable %connectable\"\n    //% parts=bluetooth weight=11 blockGap=8\n    //% help=bluetooth/advertise-url blockExternalInputs=1\n    //% hidden=1 deprecated=1 shim=bluetooth::advertiseUrl\n    function advertiseUrl(url: string, power: int32, connectable: boolean): void;\n\n    /**\n     * Advertise an Eddystone UID\n     * @param nsAndInstance 16 bytes buffer of namespace (bytes 0-9) and instance (bytes 10-15)\n     * @param power power level between 0 and 7, eg: 7\n     * @param connectable true to keep bluetooth connectable for other services, false otherwise.\n     */\n    //% parts=bluetooth weight=12 advanced=true deprecated=1 shim=bluetooth::advertiseUidBuffer\n    function advertiseUidBuffer(nsAndInstance: Buffer, power: int32, connectable: boolean): void;\n\n    /**\n     * Sets the bluetooth transmit power between 0 (minimal) and 7 (maximum).\n     * @param power power level between 0 (minimal) and 7 (maximum), eg: 7.\n     */\n    //% parts=bluetooth weight=5 help=bluetooth/set-transmit-power advanced=true\n    //% blockId=bluetooth_settransmitpower block=\"bluetooth set transmit power %power\" shim=bluetooth::setTransmitPower\n    function setTransmitPower(power: int32): void;\n\n    /**\n     * Stops advertising Eddystone end points\n     */\n    //% blockId=eddystone_stop_advertising block=\"bluetooth stop advertising\"\n    //% parts=bluetooth weight=10\n    //% help=bluetooth/stop-advertising advanced=true\n    //% hidden=1 deprecated=1 shim=bluetooth::stopAdvertising\n    function stopAdvertising(): void;\n}\n\n// Auto-generated. Do not edit. Really.\n"},"servo":{"README.md":"# Servo\n\nA small micro-servo library.","ns.ts":"/**\n * Control micro servos\n */\n//% color=\"#03AA74\" weight=88 icon=\"\\uf021\"\nnamespace servos {\n}","pxt.json":"{\n    \"name\": \"servo\",\n    \"description\": \"A micro-servo library\",\n    \"dependencies\": {\n        \"core\": \"*\"\n    },\n    \"files\": [\n        \"README.md\",\n        \"servo.ts\",\n        \"ns.ts\",\n        \"targetoverrides.ts\"\n    ],\n    \"public\": true,\n    \"targetVersions\": {\n        \"target\": \"7.1.42\",\n        \"pxt\": \"11.4.28\"\n    },\n    \"icon\": \"/static/libs/servo.png\"\n}\n","servo.ts":"/**\n * Control micro servos\n */\n//% color=\"#03AA74\" weight=88 icon=\"\\uf021\" blockGap=8\n//% groups='[\"Positional\", \"Continuous\", \"Configuration\"]'\nnamespace servos {\n    //% fixedInstances\n    export class Servo {\n        private _minAngle: number;\n        private _maxAngle: number;\n        private _stopOnNeutral: boolean;\n        private _angle: number;\n\n        constructor() {\n            this._angle = undefined;\n            this._minAngle = 0;\n            this._maxAngle = 180;\n            this._stopOnNeutral = false;\n        }\n\n        private clampDegrees(degrees: number): number {\n            degrees = degrees | 0;\n            degrees = Math.clamp(this._minAngle, this._maxAngle, degrees);\n            return degrees;\n        }\n\n        /**\n         * Set the servo angle\n         */\n        //% weight=100 help=servos/set-angle\n        //% blockId=servoservosetangle block=\"set %servo angle to %degrees=protractorPicker °\"\n        //% degrees.defl=90\n        //% servo.fieldEditor=\"gridpicker\"\n        //% servo.fieldOptions.width=220\n        //% servo.fieldOptions.columns=2\n        //% blockGap=8\n        //% parts=microservo trackArgs=0\n        //% group=\"Positional\"\n        setAngle(degrees: number) {\n            degrees = this.clampDegrees(degrees);\n            this.internalSetContinuous(false);\n            this._angle = this.internalSetAngle(degrees);\n        }\n\n        get angle() {\n            return this._angle || 90;\n        }\n\n        protected internalSetContinuous(continuous: boolean): void {\n\n        }\n\n        protected internalSetAngle(angle: number): number {\n            return 0;\n        }\n\n        /**\n         * Set the throttle on a continuous servo\n         * @param speed the throttle of the motor from -100% to 100%\n         */\n        //% weight=99 help=servos/run\n        //% blockId=servoservorun block=\"continuous %servo run at %speed=speedPicker \\\\%\"\n        //% servo.fieldEditor=\"gridpicker\"\n        //% servo.fieldOptions.width=220\n        //% servo.fieldOptions.columns=2\n        //% parts=microservo trackArgs=0\n        //% group=\"Continuous\"\n        //% blockGap=8\n        run(speed: number): void {\n            const degrees = this.clampDegrees(Math.map(speed, -100, 100, this._minAngle, this._maxAngle));\n            const neutral = (this.maxAngle - this.minAngle) >> 1;\n            this.internalSetContinuous(true);\n            if (this._stopOnNeutral && degrees == neutral)\n                this.stop();\n            else\n                this._angle = this.internalSetAngle(degrees);\n        }\n\n        /**\n         * Set the pulse width to the servo in microseconds\n         * @param micros the width of the pulse in microseconds\n         */\n\n        //% weight=10 help=servos/set-pulse\n        //% blockId=servoservosetpulse block=\"set %servo pulse to %micros μs\"\n        //% micros.min=500 micros.max=2500\n        //% micros.defl=1500\n        //% servo.fieldEditor=\"gridpicker\"\n        //% servo.fieldOptions.width=220\n        //% servo.fieldOptions.columns=2\n        //% parts=microservo trackArgs=0\n        //% group=\"Configuration\"\n        //% blockGap=8\n        setPulse(micros: number) {\n            micros = micros | 0;\n            micros = Math.clamp(500, 2500, micros);\n            this.internalSetPulse(micros);\n        }\n\n        protected internalSetPulse(micros: number): void {\n\n        }\n\n        /**\n         * Stop sending commands to the servo so that its rotation will stop at the current position.\n         */\n        // On a normal servo this will stop the servo where it is, rather than return it to neutral position.\n        // It will also not provide any holding force.\n        //% weight=10 help=servos/stop\n        //% blockId=servoservostop block=\"stop %servo\"\n        //% servo.fieldEditor=\"gridpicker\"\n        //% servo.fieldOptions.width=220\n        //% servo.fieldOptions.columns=2\n        //% parts=microservo trackArgs=0\n        //% group=\"Continuous\"\n        //% blockGap=8\n        stop() {\n            if (this._angle !== undefined)\n                this.internalStop();\n        }\n\n        /**\n         * Gets the minimum angle for the servo\n         */\n        public get minAngle() {\n            return this._minAngle;\n        }\n\n        /**\n         * Gets the maximum angle for the servo\n         */\n        public get maxAngle() {\n            return this._maxAngle;\n        }\n\n        /**\n         * Set the possible rotation range angles for the servo between 0 and 180\n         * @param minAngle the minimum angle from 0 to 90\n         * @param maxAngle the maximum angle from 90 to 180\n         */\n        //% help=servos/set-range\n        //% blockId=servosetrange block=\"set %servo range from %minAngle to %maxAngle\"\n        //% minAngle.min=0 minAngle.max=90\n        //% maxAngle.min=90 maxAngle.max=180 maxAngle.defl=180\n        //% servo.fieldEditor=\"gridpicker\"\n        //% servo.fieldOptions.width=220\n        //% servo.fieldOptions.columns=2\n        //% parts=microservo trackArgs=0\n        //% group=\"Configuration\"\n        //% blockGap=8\n        public setRange(minAngle: number, maxAngle: number) {\n            this._minAngle = Math.max(0, Math.min(90, minAngle | 0));\n            this._maxAngle = Math.max(90, Math.min(180, maxAngle | 0));\n        }\n\n        /**\n         * Set a servo stop mode so it will stop when the rotation angle is in the neutral position, 90 degrees.\n         * @param on true to enable this mode\n         */\n        //% help=servos/set-stop-on-neutral\n        //% blockId=servostoponneutral block=\"set %servo stop on neutral %enabled\"\n        //% enabled.shadow=toggleOnOff\n        //% group=\"Configuration\"\n        //% blockGap=8\n        //% servo.fieldEditor=\"gridpicker\"\n        //% servo.fieldOptions.width=220\n        //% servo.fieldOptions.columns=2\n        public setStopOnNeutral(enabled: boolean) {\n            this._stopOnNeutral = enabled;\n        }\n\n        protected internalStop() { }\n    }\n\n    export class PinServo extends Servo {\n        private _pin: PwmOnlyPin;\n\n        constructor(pin: PwmOnlyPin) {\n            super();\n            this._pin = pin;\n        }\n\n        protected internalSetAngle(angle: number): number {\n            this._pin.servoWrite(angle);\n            return angle;\n        }\n\n        protected internalSetContinuous(continuous: boolean): void {\n            this._pin.servoSetContinuous(continuous);\n        }\n\n        protected internalSetPulse(micros: number): void {\n            this._pin.servoSetPulse(micros);\n        }\n\n        protected internalStop() {\n            this._pin.digitalRead();\n            this._pin.setPull(PinPullMode.PullNone);\n        }\n    }\n}\n","targetoverrides.ts":"namespace servos {\n    //% block=\"servo P0\" fixedInstance whenUsed\n    export const P0 = new servos.PinServo(pins.P0);\n    //% block=\"servo P1\" fixedInstance whenUsed\n    export const P1 = new servos.PinServo(pins.P1);\n    //% block=\"servo P2\" fixedInstance whenUsed\n    export const P2 = new servos.PinServo(pins.P2);\n}"},"radio-broadcast":{"pxt.json":"{\n    \"name\": \"radio-broadcast\",\n    \"description\": \"Adds new blocks for message communication in the radio category\",\n    \"dependencies\": {\n        \"core\": \"*\",\n        \"radio\": \"*\"\n    },\n    \"files\": [\n        \"radio-broadcast.ts\"\n    ],\n    \"targetVersions\": {\n        \"target\": \"7.1.42\",\n        \"pxt\": \"11.4.28\"\n    },\n    \"icon\": \"/static/libs/radio-broadcast.png\"\n}\n","radio-broadcast.ts":"namespace radio {\n    const BROADCAST_GENERAL_ID = 2000;\n\n    /**\n     * Gets the message code\n     */\n    //% blockHidden=1 shim=ENUM_GET\n    //% blockId=radioMessageCode block=\"$msg\" enumInitialMembers=\"message1\"\n    //% enumName=RadioMessage enumMemberName=msg enumPromptHint=\"e.g. Start, Stop, Jump...\"\n    //% enumIsHash=1\n    export function __message(msg: number): number {\n        return msg;\n    }\n\n    /**\n     * Broadcasts a message over radio\n     * @param msg \n     */\n    //% blockId=radioBroadcastMessage block=\"radio send $msg\"\n    //% msg.shadow=radioMessageCode draggableParameters\n    //% weight=200\n    //% blockGap=8\n    //% help=radio/send-message\n    //% group=\"Broadcast\"\n    export function sendMessage(msg: number): void {\n        // 0 is MICROBIT_EVT_ANY, shifting by 1\n        radio.raiseEvent(BROADCAST_GENERAL_ID, msg + 1);\n    }\n\n    /**\n     * Registers code to run for a particular message\n     * @param msg \n     * @param handler \n     */\n    //% blockId=radioOnMessageReceived block=\"on radio $msg received\"\n    //% msg.shadow=radioMessageCode draggableParameters\n    //% weight=199\n    //% help=radio/on-received-message\n    //% group=\"Broadcast\"\n    export function onReceivedMessage(msg: number, handler: () => void) {\n        control.onEvent(BROADCAST_GENERAL_ID, msg + 1, handler);\n    }\n}"},"microphone":{"README.md":"# microphone\n\nThe microphone library.\n\n","enums.d.ts":"// Auto-generated. Do not edit.\n\n\n    declare const enum DetectedSound {\n    //% block=\"loud\"\n    Loud = 2,\n    //% block=\"quiet\"\n    Quiet = 1,\n    }\n\n\n    declare const enum SoundThreshold {\n    //% block=\"loud\"\n    Loud = 2,\n    //% block=\"quiet\"\n    Quiet = 1,\n    }\n\n// Auto-generated. Do not edit. Really.\n","microphone.cpp":"#include \"pxt.h\"\n\n#if MICROBIT_CODAL\n#include \"LevelDetector.h\"\n#include \"LevelDetectorSPL.h\"\n#endif\n\nenum class DetectedSound {\n    //% block=\"loud\"\n    Loud = 2,\n    //% block=\"quiet\"\n    Quiet = 1\n};\n\nenum class SoundThreshold {\n    //% block=\"loud\"\n    Loud = 2,\n    //% block=\"quiet\"\n    Quiet = 1\n};\nnamespace input {\n\n#if MICROBIT_CODAL\nbool didInit;\n\nvoid init() {\n    if (didInit) {\n        return;\n    }\n\n    didInit = true;\n    uBit.audio.levelSPL->setUnit(LEVEL_DETECTOR_SPL_8BIT);\n}\n\n#endif\n\n/**\n* Registers an event that runs when a sound is detected\n*/\n//% help=input/on-sound\n//% blockId=input_on_sound block=\"on %sound sound\"\n//% parts=\"microphone\"\n//% weight=88 blockGap=12\n//% group=\"micro:bit (V2)\"\nvoid onSound(DetectedSound sound, Action handler) {\n#if MICROBIT_CODAL\n    init();\n    const auto thresholdType = sound == DetectedSound::Loud ? LEVEL_THRESHOLD_HIGH : LEVEL_THRESHOLD_LOW;\n    registerWithDal(DEVICE_ID_SYSTEM_LEVEL_DETECTOR, thresholdType, handler);\n#else\n    target_panic(PANIC_VARIANT_NOT_SUPPORTED);\n#endif\n}\n\n/**\n* Reads the loudness through the microphone from 0 (silent) to 255 (loud)\n*/\n//% help=input/sound-level\n//% blockId=device_get_sound_level block=\"sound level\"\n//% parts=\"microphone\"\n//% weight=34 blockGap=8\n//% group=\"micro:bit (V2)\"\nint soundLevel() {\n#if MICROBIT_CODAL\n    init();\n    return uBit.audio.levelSPL->getValue();\n#else\n    target_panic(PANIC_VARIANT_NOT_SUPPORTED);\n    return 0;\n#endif\n}\n\n/**\n* Sets the threshold for a sound type.\n*/\n//% help=input/set-sound-threshold\n//% blockId=input_set_sound_threshold block=\"set %sound sound threshold to %value\"\n//% parts=\"microphone\"\n//% threshold.min=0 threshold.max=255 threshold.defl=128\n//% weight=14 blockGap=8\n//% advanced=true\n//% group=\"micro:bit (V2)\"\nvoid setSoundThreshold(SoundThreshold sound, int threshold) {\n#if MICROBIT_CODAL\n    init();\n    LevelDetectorSPL* level = uBit.audio.levelSPL;\n    if (NULL == level)\n        return;\n    if (SoundThreshold::Loud == sound)\n        level->setHighThreshold(threshold);\n    else\n        level->setLowThreshold(threshold);\n#else\n    target_panic(PANIC_VARIANT_NOT_SUPPORTED);\n#endif\n}\n}","microphonehw.cpp":"// The fallback logic below still requires level detection.\n// It's only kept with a view to syncing with the common-packages in future.\n\n#include \"pxt.h\"\n\n#if MICROBIT_CODAL\n#include \"LevelDetector.h\"\n#include \"LevelDetectorSPL.h\"\n#include \"DataStream.h\"\n\n#ifndef MIC_DEVICE\n// STM?\nclass DummyDataSource : public codal::DataSource {\n  public:\n    DummyDataSource() {}\n};\nclass PanicPDM {\n  public:\n    uint8_t level;\n    DummyDataSource source;\n    codal::DataStream output;\n\n    PanicPDM(Pin &sd, Pin &sck) : output(source) { target_panic(PANIC_MICROPHONE_MISSING); }\n    void enable() {}\n    void disable() {}\n};\n#define MIC_DEVICE PanicPDM\n#endif\n\n#ifndef MIC_INIT\n#define MIC_INIT                                                                                   \\\n        : microphone(*LOOKUP_PIN(MIC_DATA), *LOOKUP_PIN(MIC_CLOCK)) \\\n        , level(microphone.output, 95.0, 75.0, 9, 52, DEVICE_ID_MICROPHONE)\n#endif\n\n#ifndef MIC_ENABLE\n#define MIC_ENABLE microphone.enable()\n#endif\n\nnamespace pxt {\n\nclass WMicrophone {\n  public:\n    MIC_DEVICE microphone;\n    LevelDetectorSPL level;\n    WMicrophone() MIC_INIT { MIC_ENABLE; }\n};\nSINGLETON(WMicrophone);\n\ncodal::LevelDetectorSPL *getMicrophoneLevel() {\n    auto wmic = getWMicrophone();\n    return wmic ? &(wmic->level) : NULL;\n}\n\n} // namespace pxt\n#endif","pxt.json":"{\n    \"name\": \"microphone\",\n    \"description\": \"The microphone library\",\n    \"dependencies\": {\n        \"core\": \"*\"\n    },\n    \"files\": [\n        \"README.md\",\n        \"microphone.cpp\",\n        \"microphonehw.cpp\",\n        \"enums.d.ts\",\n        \"shims.d.ts\",\n        \"targetoverrides.ts\"\n    ],\n    \"testFiles\": [\n        \"test.ts\"\n    ],\n    \"public\": true,\n    \"targetVersions\": {\n        \"target\": \"7.1.42\",\n        \"pxt\": \"11.4.28\"\n    },\n    \"icon\": \"/static/libs/microphone.png\"\n}\n","shims.d.ts":"// Auto-generated. Do not edit.\ndeclare namespace input {\n\n    /**\n     * Registers an event that runs when a sound is detected\n     */\n    //% help=input/on-sound\n    //% blockId=input_on_sound block=\"on %sound sound\"\n    //% parts=\"microphone\"\n    //% weight=88 blockGap=12\n    //% group=\"micro:bit (V2)\" shim=input::onSound\n    function onSound(sound: DetectedSound, handler: () => void): void;\n\n    /**\n     * Reads the loudness through the microphone from 0 (silent) to 255 (loud)\n     */\n    //% help=input/sound-level\n    //% blockId=device_get_sound_level block=\"sound level\"\n    //% parts=\"microphone\"\n    //% weight=34 blockGap=8\n    //% group=\"micro:bit (V2)\" shim=input::soundLevel\n    function soundLevel(): int32;\n\n    /**\n     * Sets the threshold for a sound type.\n     */\n    //% help=input/set-sound-threshold\n    //% blockId=input_set_sound_threshold block=\"set %sound sound threshold to %value\"\n    //% parts=\"microphone\"\n    //% threshold.min=0 threshold.max=255\n    //% weight=14 blockGap=8\n    //% advanced=true\n    //% group=\"micro:bit (V2)\" threshold.defl=128 shim=input::setSoundThreshold\n    function setSoundThreshold(sound: SoundThreshold, threshold?: int32): void;\n}\n\n// Auto-generated. Do not edit. Really.\n","targetoverrides.ts":"// target specific code","test.ts":"// tests"},"settings":{"Flash.h":"#ifndef CODAL_FLASH_H\n#define CODAL_FLASH_H\n\n#include \"CodalDevice.h\"\n\nnamespace codal {\nclass Flash {\n  public:\n    /**\n     * Return page size in bytes at given address (doesn't have to be page-aligned).\n     */\n    virtual int pageSize(uintptr_t address) = 0;\n\n    /**\n     * Erase page at given page-aligned address.\n     */\n    virtual int erasePage(uintptr_t address) = 0;\n\n    /**\n     * Write given number of bytes within one page. Flash has to be erased first.\n     */\n    virtual int writeBytes(uintptr_t dst, const void *src, uint32_t len) = 0;\n\n    /**\n     * Return the total size of flash.\n     */\n    virtual int totalSize();\n};\n\nclass ZFlash : public Flash {\n  public:\n    virtual int pageSize(uintptr_t address);\n    virtual int totalSize();\n    virtual int erasePage(uintptr_t address);\n    virtual int writeBytes(uintptr_t dst, const void *src, uint32_t len);\n};\n\n#define CODAL_FLASH codal::ZFlash\n#define DEVICE_FLASH_ERROR 922\n\n\n} // namespace codal\n\n#endif\n","NRF52Flash.cpp":"#include \"pxt.h\"\n#include \"Flash.h\"\n\n//#define LOG DMESG\n#define LOG NOLOG\n\n#if defined(NRF52_SERIES)\nnamespace codal {\n\n#define waitForLast() while ((NRF_NVMC->READY & NVMC_READY_READY_Msk) == 0);\n\nstatic volatile bool flash_op_complete = false;\n\n#ifdef SOFTDEVICE_PRESENT\n#include \"nrf_sdh_soc.h\"\n#include \"nrf_sdm.h\"\n\nstatic void nvmc_event_handler(uint32_t sys_evt, void *)\n{\n    if (sys_evt == NRF_EVT_FLASH_OPERATION_SUCCESS)\n        flash_op_complete = true;\n}\n\nNRF_SDH_SOC_OBSERVER(nrfflash_soc_observer, 0, nvmc_event_handler, NULL);\n\n#ifndef MICROBIT_CODAL\nbool ble_running()\n{\n    uint8_t t = 0;\n    sd_softdevice_is_enabled(&t);\n    return t==1;\n}\n#endif\n\n#endif\n\n\nstatic inline uint32_t NRF_PAGE_SIZE() {\n#if defined(FICR_INFO_CODEPAGESIZE_CODEPAGESIZE_Msk)\n    return NRF_FICR->INFO.CODEPAGESIZE;\n#else\n    return NRF_FICR->CODEPAGESIZE;\n#endif\n}\n\nint ZFlash::pageSize(uintptr_t address) {\n    (void)address;\n#if defined(FICR_INFO_CODEPAGESIZE_CODEPAGESIZE_Msk)\n    return NRF_FICR->INFO.CODEPAGESIZE;\n#else\n    return NRF_FICR->CODEPAGESIZE;\n#endif\n}\n\nint ZFlash::totalSize() {\n#if defined(FICR_INFO_CODEPAGESIZE_CODEPAGESIZE_Msk)\n    return NRF_FICR->INFO.CODESIZE * pageSize(0);\n#else\n    return NRF_FICR->CODESIZE * pageSize(0);\n#endif\n}\n\nint ZFlash::erasePage(uintptr_t address) {\n    if (address & (pageSize(address) - 1))\n        target_panic(DEVICE_FLASH_ERROR);\n\n#ifdef SOFTDEVICE_PRESENT\n    if (ble_running())\n    {\n        flash_op_complete = false;\n        while(1)\n        {\n            if ( sd_flash_page_erase(((uint32_t)address)/NRF_PAGE_SIZE()) == NRF_SUCCESS)\n                break;\n\n            system_timer_wait_ms(10);\n        }\n\n        while(!flash_op_complete);\n    }\n    else\n#endif\n    {\n        NRF_NVMC->CONFIG = NVMC_CONFIG_WEN_Een;\n        waitForLast();\n        NRF_NVMC->ERASEPAGE = address;\n        waitForLast();\n        NRF_NVMC->CONFIG = NVMC_CONFIG_WEN_Ren;\n        waitForLast();\n    }\n    \n    return 0;\n}\n\nint ZFlash::writeBytes(uintptr_t dst, const void *src, uint32_t len) {\n    LOG(\"WR flash at %p len=%d\", (void *)dst, len);\n\n    if ((dst & 3) || ((uintptr_t)src & 3) || (len & 3))\n        return -1;\n\n    for (unsigned i = 0; i < len; ++i)\n        if (((uint8_t *)dst)[i] != 0xff && ((uint8_t *)src)[i] != 0xff)\n            return -3;\n\n    \n    volatile uint32_t *sp = (uint32_t *)src;\n    volatile uint32_t *dp = (uint32_t *)dst;\n\n    len >>= 2;\n\n#ifdef SOFTDEVICE_PRESENT\n    if (ble_running())\n    {\n        flash_op_complete = false;\n\n        while(1)\n        {\n            if (sd_flash_write((uint32_t *)dp, (uint32_t *)sp, len) == NRF_SUCCESS)\n                break;\n\n            system_timer_wait_ms(10);\n        }\n\n        while(!flash_op_complete);\n    }\n    else\n#endif\n    {\n        NRF_NVMC->CONFIG = NVMC_CONFIG_WEN_Wen;\n        waitForLast();\n\n        while (len-- > 0) {\n            uint32_t v = *sp++;\n            if (v != 0xffffffff) {\n                *dp++ = v;\n                waitForLast();\n            } else {\n                dp++;\n            }\n        }\n        \n        NRF_NVMC->CONFIG = NVMC_CONFIG_WEN_Ren;\n        waitForLast();\n    }\n\n    LOG(\"WR flash OK\");\n\n    return 0;\n}\n} // namespace codal\n#endif\n","RAFFS.cpp":"#include \"RAFFS.h\"\n#include \"CodalDmesg.h\"\n#include \"NotifyEvents.h\"\n#include \"MessageBus.h\"\n#include \"Timer.h\"\n#include \"pxtbase.h\"\n\n#include <stddef.h>\n\n#define RAFFS_MAGIC 0x7776e0da\n#define M1 0xffffffffU\n\n#define CHECK\n//#undef CHECK\n\nusing namespace codal;\n\n#define oops() target_panic(DEVICE_FLASH_ERROR)\n\n#define OFF2(v, basePtr) (uint32_t)((uint8_t *)v - (uint8_t *)basePtr)\n#define OFF(v) OFF2(v, basePtr)\n\n#define REAL_OFF(dst) (OFF(dst) <= OFF2(dst, altBasePtr()) ? OFF(dst) : OFF2(dst, altBasePtr()))\n\n#undef NOLOG\n#define NOLOG(...) ((void)0)\n#ifndef RAFFS_TEST\n#define LOG DMESG\n#define LOGV NOLOG\n#endif\n\n#define LOGVV NOLOG\n\n#if 0\n#undef LOGV\n#define LOGV DMESG\n#endif\n\n#if 0\n#undef LOGVV\n#define LOGVV DMESG\n#endif\n\nusing namespace pxt::raffs;\n\nstatic uint16_t raffs_unlocked_event;\n\nstruct FSHeader {\n    uint32_t magic;\n    uint32_t bytes;\n    uint32_t numgc;\n    uint32_t reserved;\n};\n\nstatic uint16_t fnhash(const char *fn) {\n    uint32_t h = hash_fnv1(fn, strlen(fn));\n    return h ^ (h >> 16);\n}\n\nFS::FS(Flash &flash, uintptr_t baseAddr, uint32_t bytes)\n    : flash(flash), baseAddr(baseAddr), bytes(bytes) {\n    locked = false;\n\n    basePtr = NULL;\n    endPtr = NULL;\n    freeDataPtr = NULL;\n    metaPtr = NULL;\n    readDirPtr = NULL;\n    cachedMeta = NULL;\n    flashBufAddr = 0;\n    blocked = NULL;\n    gcHorizon = -10000000;\n    minGCSpacing = 0;\n\n    if (bytes > 0x20000)\n        oops();\n\n    auto page = flash.pageSize(baseAddr);\n    // baseAddr and bytes needs to page-aligned, and we need even number of pages\n    auto numPages = bytes / page;\n    if ((baseAddr & (page - 1)) || bytes % page || numPages < 2 || (numPages & 1))\n        oops();\n\n    if (!raffs_unlocked_event)\n        raffs_unlocked_event = codal::allocateNotifyEvent();\n}\n\nvoid FS::erasePages(uintptr_t addr, uint32_t len) {\n    auto end = addr + len;\n    auto page = flash.pageSize(addr);\n    if (addr & (page - 1))\n        oops();\n    while (addr < end) {\n        if (flash.pageSize(addr) != page)\n            oops();\n        flash.erasePage(addr);\n#ifdef CHECK\n        for (int i = 0; i < page; ++i)\n            if (((uint8_t *)addr)[i] != 0xff)\n                oops();\n#endif\n        addr += page;\n    }\n}\n\nvoid FS::oopsAndClear() {\n    erasePages(baseAddr, bytes);\n    oops();\n}\n\nvoid FS::flushFlash() {\n    if (flashBufAddr) {\n        int r = flash.writeBytes(flashBufAddr, flashBuf, sizeof(flashBuf));\n        if (r)\n            oopsAndClear();\n#ifdef CHECK\n        for (unsigned i = 0; i < sizeof(flashBuf); ++i)\n            if (flashBuf[i] != 0xff && flashBuf[i] != ((uint8_t *)flashBufAddr)[i])\n                oopsAndClear();\n#endif\n        flashBufAddr = 0;\n    }\n}\n\nvoid FS::writeBytes(void *dst, const void *src, uint32_t size) {\n    LOGVV(\"write %x%s %d %x:%x:%x:%x\", REAL_OFF(dst), OFF(dst) == REAL_OFF(dst) ? \"\" : \"*\", size,\n          ((const uint8_t *)src)[0], ((const uint8_t *)src)[1], ((const uint8_t *)src)[2],\n          ((const uint8_t *)src)[3]);\n\n    while (size > 0) {\n        uint32_t off = (uintptr_t)dst & (sizeof(flashBuf) - 1);\n        uintptr_t newaddr = (uintptr_t)dst - off;\n        if (newaddr != flashBufAddr) {\n            flushFlash();\n            memset(flashBuf, 0xff, sizeof(flashBuf));\n            flashBufAddr = newaddr;\n        }\n\n        unsigned n = sizeof(flashBuf) - off;\n        if (n > size)\n            n = size;\n        memcpy(flashBuf + off, src, n);\n        size -= n;\n        src = (const uint8_t *)src + n;\n        dst = (uint8_t *)dst + n;\n    }\n}\n\n#define IS_VALID(hd) ((hd)->magic == RAFFS_MAGIC && (hd)->bytes == bytes)\n\nvoid FS::format() {\n    cachedMeta = NULL;\n    readDirPtr = NULL;\n    clearBlocked();\n\n    LOG(\"formatting...\");\n\n    FSHeader hd;\n    hd.reserved = M1;\n    hd.numgc = 1;\n\n    // in case the secondary header is valid, copy #gc\n    auto hd2 = (FSHeader *)(baseAddr + bytes / 2);\n    if (IS_VALID(hd2)) {\n        hd.numgc = hd2->numgc + 1;\n    }\n\n    // write the primary header\n    erasePages(baseAddr, bytes / 2);\n    hd.magic = RAFFS_MAGIC;\n    hd.bytes = bytes;\n    writeBytes((void *)baseAddr, &hd, sizeof(hd));\n\n    flushFlash();\n}\n\n#define NUMBLOCKED (int)(sizeof(blocked->fnptrs) / sizeof(uint16_t))\n\nbool FS::checkBlocked(MetaEntry *m) {\n    auto fnptr = m->fnptr;\n    for (auto p = blocked; p; p = p->next) {\n        for (int i = 0; i < NUMBLOCKED; ++i)\n            if (p->fnptrs[i] == fnptr) {\n                if (m->isFirst())\n                    p->fnptrs[i] = 0;\n                return true;\n            }\n    }\n    if (!m->isFirst()) {\n        for (auto p = blocked; p; p = p->next) {\n            for (int i = 0; i < NUMBLOCKED; ++i)\n                if (p->fnptrs[i] == 0) {\n                    p->fnptrs[i] = fnptr;\n                    return false;\n                }\n        }\n        auto p = new BlockedEntries;\n        memset(p, 0, sizeof(*p));\n        p->next = blocked;\n        blocked = p;\n        p->fnptrs[0] = fnptr;\n    }\n    return false;\n}\n\nvoid FS::clearBlocked() {\n    while (blocked) {\n        auto p = blocked;\n        blocked = p->next;\n        delete p;\n    }\n}\n\nbool FS::tryMount() {\n    if (basePtr)\n        return true;\n\n    auto hd0 = (FSHeader *)baseAddr;\n    auto hd1 = (FSHeader *)(baseAddr + bytes / 2);\n\n    auto v0 = IS_VALID(hd0);\n    auto v1 = IS_VALID(hd1);\n\n    if (v0 && v1) {\n        // we account for overflows\n        // they should not occur in normal operation though\n        if (hd0->numgc + 1 == hd1->numgc)\n            v0 = false;\n        else if (hd1->numgc + 1 == hd0->numgc || hd1->numgc < hd0->numgc)\n            v1 = false;\n        else\n            v0 = false;\n    }\n\n    uintptr_t addr;\n\n    if (v0)\n        addr = baseAddr;\n    else if (v1)\n        addr = baseAddr + bytes / 2;\n    else\n        return false;\n\n    basePtr = (uint8_t *)addr;\n    endPtr = (MetaEntry *)(addr + bytes / 2);\n\n    auto p = (uint32_t *)endPtr - 2;\n    while (*p != M1)\n        p -= 2;\n    metaPtr = (MetaEntry *)(p + 2);\n\n    p = (uint32_t *)metaPtr - 1;\n    while (*p == M1)\n        p--;\n    freeDataPtr = (uint8_t *)RAFFS_ROUND(p + 1);\n\n    auto fp = (uint32_t *)freeDataPtr;\n    if (fp[0] != M1 || fp[1] != M1)\n        oopsAndClear();\n\n    LOG(\"mounted, end=%x meta=%x free=%x\", OFF(endPtr), OFF(metaPtr), OFF(freeDataPtr));\n\n    return true;\n}\n\nvoid FS::mount() {\n    // if (basePtr) return;\n    if (tryMount())\n        return;\n    format();\n    if (!tryMount())\n        oopsAndClear();\n}\n\nFS::~FS() {}\n\nint FS::write(const char *keyName, const void *data, uint32_t bytes) {\n    auto isDel = data == NULL && bytes == M1;\n    if (!isDel && !data && bytes)\n        oops();\n\n    if (isDel)\n        LOGV(\"del: %s\", keyName);\n    else\n        LOGV(\"write: %s sz=%d\", keyName, bytes);\n\n    lock();\n    uint32_t szneeded = bytes;\n    auto existing = findMetaEntry(keyName);\n    auto prevBase = basePtr;\n\n    cachedMeta = NULL;\n\n    if (!existing) {\n        if (isDel) {\n            unlock();\n            return -1;\n        }\n        szneeded += strlen(keyName) + 1;\n    }\n\n    if (!tryGC(sizeof(MetaEntry) + RAFFS_ROUND(szneeded))) {\n        unlock();\n        return -1;\n    }\n\n    // if the GC happened, find the relocated meta entry\n    if (prevBase != basePtr)\n        existing = findMetaEntry(keyName);\n\n    MetaEntry newMeta;\n    if (existing) {\n        newMeta.fnhash = existing->fnhash;\n        newMeta.fnptr = existing->fnptr;\n    } else {\n        newMeta.fnhash = fnhash(keyName);\n        newMeta.fnptr = writeData(keyName, strlen(keyName) + 1);\n    }\n    newMeta.dataptr = isDel ? 0 : writeData(data, bytes);\n    newMeta._datasize = bytes;\n    if (existing)\n        newMeta._datasize |= RAFFS_FOLLOWING_MASK;\n    finishWrite();\n\n    writeBytes(--metaPtr, &newMeta, sizeof(newMeta));\n    flushFlash();\n\n    unlock();\n    return 0;\n}\n\nint FS::read(const char *keyName, void *data, uint32_t bytes) {\n    lock();\n    int r = -1;\n    MetaEntry *meta;\n    if (keyName) {\n        cachedMeta = meta = findMetaEntry(keyName);\n    } else {\n        meta = cachedMeta;\n    }\n    if (meta != NULL && meta->dataptr) {\n        r = meta->datasize();\n        if (data) {\n            if (bytes > (unsigned)r)\n                bytes = r;\n            memcpy(data, basePtr + meta->dataptr, bytes);\n        }\n    }\n    unlock();\n    return r;\n}\n\nint FS::remove(const char *keyName) {\n    return write(keyName, NULL, M1);\n}\n\nvoid FS::lock() {\n    while (locked)\n        fiber_wait_for_event(DEVICE_ID_NOTIFY, raffs_unlocked_event);\n    locked = true;\n    mount();\n}\n\nvoid FS::unlock() {\n    if (!locked)\n        oops();\n    flushFlash();\n    locked = false;\n#ifndef RAFFS_TEST\n    Event(DEVICE_ID_NOTIFY, raffs_unlocked_event);\n#endif\n}\n\nMetaEntry *FS::findMetaEntry(const char *filename) {\n    uint16_t h = fnhash(filename);\n    uint16_t buflen = strlen(filename) + 1;\n\n    for (auto p = metaPtr; p < endPtr; p++) {\n        // LOGV(\"check at %x %x %x\", OFF(p),p->fnhash,h);\n        if (p->fnhash == h && memcmp(fnptr(p), filename, buflen) == 0)\n            return p;\n    }\n\n    // LOGV(\"fail\");\n\n    return NULL;\n}\n\nvoid FS::forceGC(filename_filter filter) {\n    lock();\n    tryGC(0x7fff0000, filter);\n    unlock();\n}\n\nbool FS::tryGC(int spaceNeeded, filename_filter filter) {\n    int spaceLeft = (intptr_t)metaPtr - (intptr_t)freeDataPtr;\n\n#ifdef RAFFS_TEST\n    for (auto p = (uint32_t *)freeDataPtr; p < (uint32_t *)metaPtr; p++) {\n        if (*p != M1) {\n            LOG(\"value at %x = %x\", OFF(p), *p);\n            oopsAndClear();\n        }\n    }\n#endif\n\n    if (spaceLeft > spaceNeeded + 32)\n        return true;\n    \n    int now = (int)system_timer_current_time();\n    if (minGCSpacing) {\n        gcHorizon += minGCSpacing;\n        int nextGC = now - minGCSpacing * 2;\n        // LOG(\"now=%d n=%d gch=%d\", now, nextGC, gcHorizon);\n        if (nextGC > gcHorizon)\n            gcHorizon = nextGC;\n        if (gcHorizon > now)\n            target_panic(921);\n    }\n\n    LOG(\"running flash FS GC; needed %d, left %d\", spaceNeeded, spaceLeft);\n\n    readDirPtr = NULL;\n    cachedMeta = NULL;\n\n    auto newBase = (uintptr_t)altBasePtr();\n\n    flushFlash();\n\n    erasePages(newBase, bytes / 2);\n\n    auto metaDst = (MetaEntry *)(newBase + bytes / 2);\n    auto newBaseP = (uint8_t *)newBase;\n    freeDataPtr = newBaseP + sizeof(FSHeader);\n\n    for (int iter = 0; iter < 2; ++iter) {\n        clearBlocked();\n        auto offset = sizeof(FSHeader);\n        for (auto p = metaPtr; p < endPtr; p++) {\n            MetaEntry m = *p;\n            const char *fn = fnptr(&m);\n\n            if (filter && !filter(fn))\n                continue;\n\n            if (checkBlocked(&m) || m.dataptr == 0)\n                continue;\n\n            LOGV(\"GC %s sz=%d @%x\", fn, m.datasize(), m.dataptr);\n            auto fnlen = strlen(fn) + 1;\n            auto sz = fnlen + m.datasize();\n\n            if (iter == 0) {\n                auto fd = freeDataPtr;\n                writeData(fn, fnlen);\n                writeData(basePtr + m.dataptr, m.datasize());\n                if (freeDataPtr - fd != (int)sz)\n                    oops();\n            } else {\n                m.fnptr = offset;\n                m.dataptr = offset + fnlen;\n                m._datasize &= ~RAFFS_FOLLOWING_MASK;\n                writeBytes(--metaDst, &m, sizeof(m));\n            }\n            offset += sz;\n        }\n        if (iter == 0)\n            finishWrite();\n    }\n\n    clearBlocked();\n    flushFlash();\n\n    LOG(\"GC done: %d free\", (int)((intptr_t)metaDst - (intptr_t)freeDataPtr));\n\n    FSHeader hd;\n    hd.magic = RAFFS_MAGIC;\n    hd.bytes = bytes;\n    hd.numgc = ((FSHeader*)basePtr)->numgc + 1;\n    hd.reserved = M1;\n    writeBytes(newBaseP, &hd, sizeof(hd));\n    flushFlash();\n\n    basePtr = newBaseP;\n    endPtr = (MetaEntry *)(newBase + bytes / 2);\n    metaPtr = metaDst;\n\n    if ((intptr_t)metaDst - (intptr_t)freeDataPtr <= spaceNeeded + 64) {\n        if (filter != NULL && spaceNeeded != 0x7fff0000) {\n            LOG(\"out of space! needed=%d\", spaceNeeded);\n#ifdef RAFFS_TEST\n            oops();\n#endif\n        }\n        return false;\n    }\n\n    return true;\n}\n\nDirEntry *FS::dirRead() {\n    lock();\n\n    if (readDirPtr == NULL) {\n        readDirPtr = metaPtr;\n        clearBlocked();\n    }\n\n    while (readDirPtr < endPtr) {\n        auto m = *readDirPtr++;\n        if (checkBlocked(&m) || m.dataptr == 0)\n            continue;\n        dirEnt.size = m.datasize();\n        dirEnt.flags = 0;\n        dirEnt.name = fnptr(&m);\n        unlock();\n        return &dirEnt;\n    }\n\n    readDirPtr = NULL;\n    clearBlocked();\n    unlock();\n    return NULL;\n}\n\nuint16_t FS::writeData(const void *data, uint32_t len) {\n    LOGVV(\"writeData: @%x %x:%x sz=%d\", REAL_OFF(freeDataPtr), ((const uint8_t *)data)[0],\n          ((const uint8_t *)data)[1], len);\n    writeBytes(freeDataPtr, data, len);\n    auto r = freeDataPtr - basePtr;\n    freeDataPtr += len;\n    return r;\n}\n\nvoid FS::finishWrite() {\n    auto nfp = RAFFS_ROUND(freeDataPtr);\n    int tailSz = nfp - (uintptr_t)freeDataPtr;\n    uint64_t z = 0;\n    if (tailSz) {\n        writeData(&z, tailSz);\n    } else {\n        if (((uint32_t *)nfp)[-1] == M1)\n            writeData(&z, 8);\n    }\n    flushFlash();\n}\n\nint FS::readFlashBytes(uintptr_t addr, void *buffer, uint32_t len) {\n    lock();\n    memcpy(buffer, (void *)addr, len);\n    unlock();\n    return len;\n}\n\n#ifdef RAFFS_TEST\nvoid FS::dump() {}\n\nvoid FS::debugDump() {\n    // dump();\n}\n#endif","RAFFS.h":"#ifndef CODAL_RAFFS_H\n#define CODAL_RAFFS_H\n\n#include \"Flash.h\"\n\nnamespace pxt {\nnamespace raffs {\n\nstruct DirEntry {\n    uint32_t size;\n    uint16_t flags;\n    const char *name;\n};\n\nstruct BlockedEntries {\n    BlockedEntries *next;\n    uint16_t fnptrs[32];\n};\n\n#define RAFFS_FOLLOWING_MASK 0x8000\n\n#ifdef PICO_BOARD\n#define RAFFS_FLASH_BUFFER_SIZE 256\n#else\n#define RAFFS_FLASH_BUFFER_SIZE 64\n#endif\n\nstruct MetaEntry {\n    uint16_t fnhash;    // hash of file name\n    uint16_t fnptr;     // offset in bytes; can't be 0xffff\n    uint16_t _datasize; // size in bytes; highest bit is set if this isn't first block\n    uint16_t dataptr;   // offset in bytes; 0x0 - deleted\n\n    uint16_t datasize() { return _datasize & 0x7fff; }\n    bool isFirst() { return (_datasize & RAFFS_FOLLOWING_MASK) == 0; }\n};\n\n#define RAFFS_ROUND(x) ((((uintptr_t)(x) + 7) >> 3) << 3)\n\ntypedef bool (*filename_filter)(const char *);\n\nclass FS {\n    codal::Flash &flash;\n\n    uint8_t *basePtr, *freeDataPtr;\n    MetaEntry *endPtr, *metaPtr, *readDirPtr, *cachedMeta;\n    int32_t gcHorizon;\n    DirEntry dirEnt;\n    uintptr_t flashBufAddr;\n    uint8_t flashBuf[RAFFS_FLASH_BUFFER_SIZE];\n    BlockedEntries *blocked;\n    volatile bool locked;\n\n    void erasePages(uintptr_t addr, uint32_t len);\n    void flushFlash();\n    void writeBytes(void *dst, const void *src, uint32_t size);\n    void mount();\n    void lock();\n    void unlock();\n    MetaEntry *findMetaEntry(const char *filename);\n    bool tryGC(int spaceNeeded, filename_filter filter = NULL);\n\n    bool checkBlocked(MetaEntry *m);\n    void clearBlocked();\n    void oopsAndClear();\n\n    uint16_t writeData(const void *data, uint32_t len);\n    void finishWrite();\n    const char *fnptr(MetaEntry *m) { return (const char *)(basePtr + m->fnptr); }\n\n    uint32_t *altBasePtr() {\n        if ((uintptr_t)basePtr == baseAddr)\n            return (uint32_t *)(baseAddr + bytes / 2);\n        else\n            return (uint32_t *)baseAddr;\n    }\n\n  public:\n    // Minimum time in ms that has to pass between two GCs; we shall panic 920 if GCs happen more often\n    // (avareged over 3x this time).\n    // This is usually set to around 10s (10000), so that if user writes a program that writes to flash in\n    // a loop, it doesn't wear out flash completely.\n    uint16_t minGCSpacing;\n    uintptr_t baseAddr;\n    uint32_t bytes;\n\n    FS(codal::Flash &flash, uintptr_t baseAddr, uint32_t bytes);\n    ~FS();\n\n    // returns 0 for success, negative for error\n    int write(const char *keyName, const void *data, uint32_t bytes);\n    // returns total number of bytes in key's value or -1 when file doesn't exists\n    // if keyName==NULL it will re-use last keyName\n    int read(const char *keyName, void *data, uint32_t bytes);\n    // deletes given key if it exists\n    int remove(const char *keyName);\n\n    void format();\n    bool exists(const char *keyName) { return read(keyName, NULL, 0) >= 0; }\n    uint32_t totalSize() { return bytes / 2; }\n    uint32_t freeSize() { return (uintptr_t)endPtr - (uintptr_t)freeDataPtr; }\n    void forceGC(filename_filter filter = NULL);\n    // this allow raw r/o access; will lock the instance as needed\n    int readFlashBytes(uintptr_t addr, void *buffer, uint32_t len);\n    bool tryMount();\n\n    void dirRewind() { readDirPtr = NULL; }\n    DirEntry *dirRead(); // data is only valid until next call to to any of File or FS function\n\n#ifdef RAFFS_TEST\n    void debugDump();\n    void dump();\n#else\n    void debugDump() {}\n#endif\n};\n\n} // namespace raffs\n} // namespace pxt\n\n#endif\n","README.md":"# Settings store in internal MCU flash\n\nThis packages implements a simple key-value storage, in vein of browser's `localStorage`.\nKeys are strings and values are buffers, but APIs are provided for using strings,\nnumbers and number arrays as values.\n\nKeys with names starting with `#` are _system keys_.\nUser applications should not read or write these directly.\n\nFollowing system keys are used:\n* `#run` - current run number; incremented on each reset; it's also used to seed the\n  random number generator; accessible via `settings.runNumber()`\n* `#volume` - last music volume set explicitly by user using the game menu\n* `#scope` - keeps the name of the program; if the current name of the program\n  doesn't match what is in that key, all non-system keys are cleared;\n  this happens for example when a new game (or rather a game with a new name) \n  is uploaded to a hardware device\n\nThe size of storage is typically limited to 16 kilobytes.\nThis applies in browser and in Arcade devices.\nSmaller MCUs may limit it further (eg., it's 1k on SAMD21 devices).\n\n## Panics 920, 921 and 922\n\nWhen there is no more space to write a key to storage, all non-system keys\nare deleted.\nThen, if more than 25% of space is still occupied (by system keys),\nall keys are deleted.\nFinally, a panic 920 is issued.\nThe user has to reset the device, and hopefully next run will fix things.\n\nAll flash devices have a limited number of erases (at least 10,000),\nbefore they start failing.\nThe settings storage implemented here doesn't erase on every write (typically\nit will erase every hundred writes or so);\nif your program keeps writing in a loop, you will likely\nhit 10,000 erases in about half hour.\n\nFor this reason, if erases happen too often (i.e., you're writing too much),\npanic 921 will be issued.\n\nIf flash memory is found to be inconsistent, panic 922 is issued.\nIn most cases, the entire flash memory is cleared before that, so that\na device reset will hopefully fix things.\n\n## Storage structure\n\nSettings are written using a very simple log file system.\nThe flash is divided in two equal regions.\nOne region is used for writing, and when it fills up, data is compressed\n(garbage collected) into the other region, which is to be used from now\non until next compression\n\nEach region starts with a header, followed by data section containing\nkey names and values.\nData section grows in the positive direction.\nFrom the end of the region, the meta-data section grows in the negative\ndirection.\nMeta-data entries are 8 bytes each and contain hash of key name,\nvalue size, and points to key name and value in the data sections.\nWhen a key value is overwritten, a new meta-data section for it\nis created. When a key is to be found, it is searched for from the most \nrecent meta-data entry.\n","RP2040Flash.cpp":"#include \"pxt.h\"\n#include \"Flash.h\"\n\n//#define LOG DMESG\n#define LOG NOLOG\n\n#ifdef PICO_BOARD\n#include \"hardware/flash.h\"\n\n#define XIP_BIAS 0x10000000\n\nnamespace codal {\n\nint ZFlash::pageSize(uintptr_t address) {\n  return FLASH_SECTOR_SIZE;\n}\n\nint ZFlash::totalSize() {\n#ifndef PICO_FLASH_SIZE_BYTES\n  return 2*1024*1024;\n#else\n  return PICO_FLASH_SIZE_BYTES;\n#endif\n}\n\nint ZFlash::erasePage(uintptr_t address) {\n  // address should be aligned to 4096\n  if (address % 4096 == 0){\n    target_disable_irq();\n    flash_range_erase(address - XIP_BIAS, FLASH_SECTOR_SIZE);  \n    target_enable_irq();\n  }\n  return 0;\n}\n\nint ZFlash::writeBytes(uintptr_t dst, const void *src, uint32_t len) {\n  if (len != FLASH_PAGE_SIZE || (dst & (FLASH_PAGE_SIZE - 1))) return -1;\n  // should be aligned to 256\n  target_disable_irq();\n  flash_range_program(dst - XIP_BIAS, (const uint8_t*)src, FLASH_PAGE_SIZE);\n  target_enable_irq();\n  \n  return 0;\n}\n\n\n\n\n}\n\n#endif\n","SAMDFlash.cpp":"#include \"pxt.h\"\n#include \"Flash.h\"\n\n//#define LOG DMESG\n#define LOG NOLOG\n\n#if defined(SAMD51) || defined(SAMD21)\nnamespace codal {\n\n#ifdef SAMD51\n#define waitForLast()                                                                              \\\n    while (NVMCTRL->STATUS.bit.READY == 0)                                                         \\\n        ;\n#else\n#define waitForLast()                                                                              \\\n    while (NVMCTRL->INTFLAG.bit.READY == 0)                                                        \\\n        ;\n#endif\n\nstatic void unlock() {\n#ifdef SAMD51\n    // see errata 2.14.1\n    NVMCTRL->CTRLA.bit.CACHEDIS0 = true;\n    NVMCTRL->CTRLA.bit.CACHEDIS1 = true;\n\n    CMCC->CTRL.bit.CEN = 0;\n    while (CMCC->SR.bit.CSTS) {\n    }\n    CMCC->MAINT0.bit.INVALL = 1;\n#endif\n}\n\nstatic void lock() {\n#ifdef SAMD51\n    // re-enable cache\n    NVMCTRL->CTRLA.bit.CACHEDIS0 = false;\n    NVMCTRL->CTRLA.bit.CACHEDIS1 = false;\n\n    // re-enable cortex-m cache - it's a separate one\n    CMCC->CTRL.bit.CEN = 0;\n    while (CMCC->SR.bit.CSTS) {\n    }\n    CMCC->MAINT0.bit.INVALL = 1;\n    CMCC->CTRL.bit.CEN = 1;\n#endif\n}\n\nint ZFlash::totalSize() {\n    return (8 << NVMCTRL->PARAM.bit.PSZ) * NVMCTRL->PARAM.bit.NVMP;\n}\n\n// this returns the size of \"page\" that can be erased (\"row\" in datasheet)\nint ZFlash::pageSize(uintptr_t address) {\n#ifdef SAMD51\n    if (address < (uintptr_t)totalSize())\n        return NVMCTRL_BLOCK_SIZE; // 8k\n#else\n    if (address < (uintptr_t)totalSize())\n        return 256;\n#endif\n    target_panic(DEVICE_FLASH_ERROR);\n    return 0;\n}\n\n#ifdef SAMD51\n#define CMD(D21, D51) NVMCTRL->CTRLB.reg = NVMCTRL_CTRLB_CMDEX_KEY | D51\n#else\n#define CMD(D21, D51) NVMCTRL->CTRLA.reg = NVMCTRL_CTRLA_CMDEX_KEY | D21\n#endif\n\nint ZFlash::erasePage(uintptr_t address) {\n    LOG(\"Erase %x\", address);\n#ifdef SAMD51\n    NVMCTRL->CTRLA.bit.WMODE = NVMCTRL_CTRLA_WMODE_MAN_Val;\n#else\n    NVMCTRL->CTRLB.bit.MANW = 1;\n#endif\n    waitForLast();\n    unlock();\n#ifdef SAMD51\n    NVMCTRL->ADDR.reg = address;\n#else\n    // yeah... /2\n    NVMCTRL->ADDR.reg = address / 2;\n#endif\n    CMD(NVMCTRL_CTRLA_CMD_ER, NVMCTRL_CTRLB_CMD_EB);\n    waitForLast();\n    lock();\n    return 0;\n}\n\n#if 0\n#define CHECK_ECC()                                                                                \\\n    if (NVMCTRL->INTFLAG.bit.ECCSE || NVMCTRL->INTFLAG.bit.ECCDE)                                  \\\n    return -10\n#else\n#define CHECK_ECC() ((void)0)\n#endif\n\nint ZFlash::writeBytes(uintptr_t dst, const void *src, uint32_t len) {\n#ifdef SAMD51\n    CHECK_ECC();\n\n    // only allow writing double word at a time\n    if (len & 7)\n        return -1;\n    if (dst & 7)\n        return -2;\n\n    // every double-word can only be written once, otherwise we get ECC errors\n    // and no, ECC cannot be disabled\n    for (unsigned i = 0; i < (len >> 3); ++i)\n        if (((uint64_t *)dst)[i] != 0xffffffffffffffff &&\n            ((uint64_t *)src)[i] != 0xffffffffffffffff)\n            return -3;\n#define WRITE_SIZE 16\n#else\n    if ((dst & 3) || (len & 3))\n        return -1;\n\n    for (unsigned i = 0; i < len; ++i)\n        if (((uint8_t *)dst)[i] != 0xff && ((uint8_t *)src)[i] != 0xff)\n            return -3;\n#define WRITE_SIZE 64\n#endif\n\n    uint32_t writeBuf[WRITE_SIZE >> 2];\n    uint32_t idx = 0;\n\n    waitForLast();\n    unlock();\n    __DMB();\n\n    while (idx < len) {\n        uint32_t off = dst & (WRITE_SIZE - 1);\n        uint32_t n = WRITE_SIZE - off;\n        if (n > len - idx)\n            n = len - idx;\n        uint32_t *sp;\n        volatile uint32_t *dp;\n        if (n != WRITE_SIZE) {\n            memset(writeBuf, 0xff, WRITE_SIZE);\n            memcpy((uint8_t *)writeBuf + off, src, n);\n            sp = writeBuf;\n            dp = (uint32_t *)(dst - off);\n        } else {\n            sp = (uint32_t *)src;\n            dp = (uint32_t *)dst;\n        }\n\n        bool need = false;\n        for (unsigned i = 0; i < (WRITE_SIZE >> 2); ++i)\n            if (sp[i] != 0xffffffff) {\n                need = true;\n                break;\n            }\n\n        if (need) {\n            CMD(NVMCTRL_CTRLA_CMD_PBC, NVMCTRL_CTRLB_CMD_PBC);\n            waitForLast();\n\n            uint32_t q = WRITE_SIZE >> 2;\n\n            target_disable_irq();\n            while (q--) {\n                auto v = *sp++;\n                *dp = v;\n                dp++;\n            }\n\n            CMD(NVMCTRL_CTRLA_CMD_WP, NVMCTRL_CTRLB_CMD_WQW);\n            target_enable_irq();\n            waitForLast();\n        }\n\n        src = (uint8_t *)src + n;\n        dst += n;\n        idx += n;\n    }\n\n    CHECK_ECC();\n\n    lock();\n\n    return 0;\n}\n} // namespace codal\n#endif\n","STM32Flash.cpp":"#include \"pxt.h\"\n#include \"Flash.h\"\n\n//#define LOG DMESG\n#define LOG NOLOG\n\n#ifdef STM32F4\nnamespace codal {\nstatic void waitForLast() {\n    while ((FLASH->SR & FLASH_SR_BSY) == FLASH_SR_BSY)\n        ;\n}\n\nstatic void unlock() {\n    FLASH->CR |= FLASH_CR_LOCK;\n    FLASH->KEYR = FLASH_KEY1;\n    FLASH->KEYR = FLASH_KEY2;\n}\n\nstatic void lock() {\n    FLASH->CR |= FLASH_CR_LOCK;\n}\n\nint ZFlash::pageSize(uintptr_t address) {\n    address |= 0x08000000;\n    if (address < 0x08010000)\n        return 16 * 1024;\n    if (address < 0x08020000)\n        return 64 * 1024;\n    if (address < 0x08100000)\n        return 128 * 1024;\n    target_panic(DEVICE_FLASH_ERROR);\n    return 0;\n}\n\nint ZFlash::totalSize() {\n    return *((uint16_t *)0x1FFF7A22) * 1024;\n}\n\nint ZFlash::erasePage(uintptr_t address) {\n    waitForLast();\n    unlock();\n\n    address |= 0x08000000;\n    uintptr_t ptr = 0x08000000;\n    int sectNum = 0;\n    while (1) {\n        ptr += pageSize(ptr);\n        if (ptr > address)\n            break;\n        sectNum++;\n    }\n\n    FLASH->CR = FLASH_CR_PSIZE_1 | (sectNum << FLASH_CR_SNB_Pos) | FLASH_CR_SER;\n    FLASH->CR |= FLASH_CR_STRT;\n\n    waitForLast();\n\n    FLASH->CR = FLASH_CR_PSIZE_1;\n    lock();\n\n    // cache flushing only required after erase, not programming (3.5.4)\n    __HAL_FLASH_DATA_CACHE_DISABLE();\n    __HAL_FLASH_DATA_CACHE_RESET();\n    __HAL_FLASH_DATA_CACHE_ENABLE();\n\n    // we skip instruction cache, as we're not expecting to erase that\n\n    return 0;\n}\n\nint ZFlash::writeBytes(uintptr_t dst, const void *src, uint32_t len) {\n    LOG(\"WR flash at %p len=%d\", (void *)dst, len);\n\n    if ((dst & 3) || ((uintptr_t)src & 3) || (len & 3))\n        return -1;\n\n    for (unsigned i = 0; i < len; ++i)\n        if (((uint8_t *)dst)[i] != 0xff && ((uint8_t *)src)[i] != 0xff)\n            return -3;\n\n    waitForLast();\n    unlock();\n\n    dst |= 0x08000000;\n\n    FLASH->CR = FLASH_CR_PSIZE_1 | FLASH_CR_PG;\n\n    volatile uint32_t *sp = (uint32_t *)src;\n    volatile uint32_t *dp = (uint32_t *)dst;\n    len >>= 2;\n\n    while (len-- > 0) {\n        uint32_t v = *sp++;\n        if (v != 0xffffffff) {\n            *dp++ = v;\n            waitForLast();\n        } else {\n            dp++;\n        }\n    }\n\n    FLASH->CR = FLASH_CR_PSIZE_1;\n    lock();\n\n    LOG(\"WR flash OK\");\n\n    return 0;\n}\n} // namespace codal\n#endif\n","pxt.json":"{\n    \"name\": \"settings\",\n    \"description\": \"Settings storage in internal flash\",\n    \"dependencies\": {\n        \"core\": \"*\"\n    },\n    \"files\": [\n        \"README.md\",\n        \"RAFFS.cpp\",\n        \"RAFFS.h\",\n        \"Flash.h\",\n        \"STM32Flash.cpp\",\n        \"SAMDFlash.cpp\",\n        \"NRF52Flash.cpp\",\n        \"RP2040Flash.cpp\",\n        \"settings.cpp\",\n        \"settings.ts\",\n        \"targetoverrides.ts\",\n        \"shims.d.ts\"\n    ],\n    \"public\": true,\n    \"targetVersions\": {\n        \"target\": \"7.1.42\",\n        \"pxt\": \"11.4.28\"\n    },\n    \"hidden\": true,\n    \"disablesVariants\": [\n        \"mbdal\"\n    ]\n}\n","settings.cpp":"\n#include \"pxt.h\"\n#include \"RAFFS.h\"\n#include \"GhostFAT.h\"\n\nusing namespace pxt::raffs;\nusing namespace codal;\n\nnamespace settings {\n\n#if defined(SAMD21)\n#define SETTINGS_SIZE (2 * 1024)\n#else\n#define SETTINGS_SIZE (32 * 1024)\n#endif\n\nclass WStorage {\n  public:\n    CODAL_FLASH flash;\n    FS fs;\n    bool isMounted;\n\n    WStorage(uint32_t size)\n        : flash(),\n#if defined(STM32F4)\n          fs(flash, 0x8008000, size),\n#elif defined(SAMD51)\n          fs(flash, 512 * 1024 - size, size),\n#elif defined(SAMD21)\n          fs(flash, 256 * 1024 - size, size),\n#elif defined(MICROBIT_CODAL) && MICROBIT_CODAL\n          fs(flash, FLASH_TOP - size, size),\n#elif defined(NRF52_SERIES)\n#define NRF_BOOTLOADER_START *(uint32_t *)0x10001014\n          fs(flash,\n             128 * 1024 < NRF_BOOTLOADER_START && NRF_BOOTLOADER_START < (uint32_t)flash.totalSize()\n                 ? NRF_BOOTLOADER_START - size\n                 : flash.totalSize() - size,\n                 size),\n#elif defined(PICO_BOARD)\n          // XIP bias 0x10000000\n          fs(flash, 0x10000000 + flash.totalSize() - size - 4096, size),\n#else\n          fs(flash),\n#endif\n          isMounted(false) {\n        fs.minGCSpacing = 10000;\n    }\n};\n\nstatic WStorage *instWStorage;\nWStorage *getWStorage() {\n    if (!instWStorage) {       \n        uint32_t size = getConfig(CFG_SETTINGS_SIZE_DEFL, SETTINGS_SIZE);\n        uint32_t new_size = getConfig(CFG_SETTINGS_SIZE, 0);\n        if (new_size > 0)\n            size = new_size;\n        instWStorage = new WStorage(size);    \n    }\n    return instWStorage;\n}\n\nstatic WStorage *mountedStorage() {\n    auto s = getWStorage();\n    if (s->fs.tryMount())\n        return s;\n    s->fs.exists(\"foobar\"); // forces mount and possibly format\n    return s;\n}\n\n// large store is area for storing large binary objects, eg ML models\n// it may be already occupied by the user program, in which case largeStoreStart() will return 0\nsize_t largeStoreSize() {\n#if defined(SAMD21)\n    return 64 * 1024;\n#else\n    return 128 * 1024;\n#endif\n}\n\nuintptr_t largeStoreStart() {\n    auto s = getWStorage();\n    uintptr_t r;\n#if defined(STM32F4)\n    r = 0x08000000 + s->flash.totalSize() - largeStoreSize();\n#else\n    r = s->fs.baseAddr - s->fs.bytes - largeStoreSize();\n#endif\n\n    if (r < afterProgramPage())\n        return 0;\n\n    return r;\n}\n\nCODAL_FLASH *largeStoreFlash() {\n    return &getWStorage()->flash;\n}\n\n//%\nint _set(String key, Buffer data) {\n    auto s = mountedStorage();\n    return s->fs.write(key->getUTF8Data(), data->data, data->length);\n}\n\n//%\nint _remove(String key) {\n    auto s = mountedStorage();\n    return s->fs.remove(key->getUTF8Data());\n}\n\n//%\nbool _exists(String key) {\n    auto s = mountedStorage();\n    return s->fs.exists(key->getUTF8Data());\n}\n\n//%\nBuffer _get(String key) {\n    auto s = mountedStorage();\n    auto sz = s->fs.read(key->getUTF8Data(), NULL, 0);\n    if (sz < 0)\n        return NULL;\n    auto ret = mkBuffer(NULL, sz);\n    registerGCObj(ret);\n    s->fs.read(NULL, ret->data, ret->length);\n    unregisterGCObj(ret);\n    return ret;\n}\n\nstatic bool isSystem(const char *fn) {\n    return fn[0] == '#';\n}\n\n//%\nvoid _userClean() {\n    auto s = mountedStorage();\n    DMESG(\"clearing user files\");\n    s->fs.forceGC(isSystem);\n    // if system files take more than 25% of storage size, we reformat\n    // it likely means user code has written some 'system' files\n    if (s->fs.freeSize() < 3 * s->fs.totalSize() / 4) {\n        s->fs.format();\n    }\n}\n\n//%\nRefCollection *_list(String prefix) {\n    auto st = mountedStorage();\n    st->fs.dirRewind();\n    auto res = Array_::mk();\n    registerGCObj(res);\n\n    auto prefData = prefix->getUTF8Data();\n    auto prefLen = prefix->getUTF8Size();\n    auto wantsInternal = prefData[0] == '#';\n\n    for (;;) {\n        auto d = st->fs.dirRead();\n        if (!d)\n            break;\n        if (!wantsInternal && d->name[0] == '#')\n            continue;\n        if (memcmp(d->name, prefData, prefLen) != 0)\n            continue;\n        auto str = mkString(d->name, -1);\n        registerGCObj(str);\n        res->head.push((TValue)str);\n        unregisterGCObj(str);\n    }\n    unregisterGCObj(res);\n    return res;\n}\n\n} // namespace settings\n","settings.ts":"namespace settings {\n    const RUN_KEY = \"#run\";\n    const SCOPE_KEY = \"#scope\";\n    const DEVICE_SECRETS_KEY = \"#secrets\";\n    const SECRETS_KEY = \"__secrets\";\n\n    //% shim=pxt::seedAddRandom\n    declare function seedAddRandom(n: number): void;\n\n    //% shim=settings::_set\n    declare function _set(key: string, data: Buffer): int32;\n\n    //% shim=settings::_remove\n    declare function _remove(key: string): int32;\n\n    //% shim=settings::_exists\n    declare function _exists(key: string): boolean;\n\n    //% shim=settings::_get\n    declare function _get(key: string): Buffer;\n\n    //% shim=settings::_userClean\n    declare function _userClean(): void;\n\n    //% shim=settings::_list\n    declare function _list(prefix: string): string[];\n\n    export function runNumber() {\n        return readNumber(RUN_KEY) || 0\n    }\n\n    function setScope(scope: string) {\n        if (!scope || scope.length > 100)\n            control.panic(922)\n        const currScope = readString(SCOPE_KEY)\n        if (currScope != scope) {\n            _userClean()\n            writeString(SCOPE_KEY, scope)\n        }\n    }\n\n    function initScopes() {\n        const rn = runNumber() + 1\n        writeNumber(RUN_KEY, rn)\n\n        seedAddRandom(control.deviceSerialNumber() & 0x7fffffff)\n        seedAddRandom(rn)\n\n        setScope(control.programName())\n    }\n\n    initScopes()\n\n    /** \n     * Delete all non-system settings.\n     */\n    export function clear(): void {\n        _userClean()\n    }\n\n    /**\n     * Set named setting to a given buffer.\n     */\n    export function writeBuffer(key: string, value: Buffer) {\n        if (_set(key, value)) {\n            // if we're out of space, clear user storage\n            _userClean()\n            // and panic - reset should hopefully recreate needed files\n            control.panic(920)\n        }\n    }\n\n    /**\n     * Set named settings to a given string.\n     */\n    export function writeString(key: string, value: string) {\n        writeBuffer(key, control.createBufferFromUTF8(value))\n    }\n\n    /**\n     * Set named settings to a given JSON object.\n     */\n    export function writeJSON(key: string, value: any) {\n        writeString(key, JSON.stringify(value))\n    }\n\n    /**\n     * Set named settings to a given number.\n     */\n    export function writeNumber(key: string, value: number) {\n        writeBuffer(key, msgpack.packNumberArray([value]))\n    }\n\n    /**\n     * Set named settings to a given array of numbers.\n     */\n    export function writeNumberArray(key: string, value: number[]) {\n        writeBuffer(key, msgpack.packNumberArray(value))\n    }\n\n    /**\n     * Read named setting as a buffer. Returns undefined when setting not found.\n     */\n    export function readBuffer(key: string) {\n        return _get(key)\n    }\n\n    /**\n     * Read named setting as a string.\n     */\n    export function readString(key: string) {\n        const buf = readBuffer(key)\n        if (!buf)\n            return undefined\n        else\n            return buf.toString()\n    }\n\n    /**\n     * Read named setting as a JSON object.\n     */\n    export function readJSON(key: string) {\n        const s = readString(key)\n        if (s)\n            return JSON.parse(s)\n        return undefined\n    }\n\n    /**\n     * Read named setting as a number.\n     */\n    export function readNumber(key: string) {\n        const buf = readBuffer(key)\n        if (!buf)\n            return undefined\n        else {\n            const nums = msgpack.unpackNumberArray(buf)\n            if (nums && nums.length >= 1)\n                return nums[0]\n            return undefined\n        }\n    }\n\n    /**\n     * Read named setting as a number.\n     */\n    export function readNumberArray(key: string) {\n        const buf = readBuffer(key)\n        if (!buf)\n            return undefined\n        else\n            return msgpack.unpackNumberArray(buf)\n    }\n\n    /**\n     * Return a list of settings starting with a given prefix.\n     */\n    export function list(prefix?: string) {\n        if (!prefix) prefix = \"\"\n        return _list(prefix)\n    }\n\n    /**\n     * Remove named setting.\n     */\n    export function remove(key: string) {\n        _remove(key)\n    }\n\n    /**\n     * Check if a named setting exists.\n     */\n    export function exists(key: string) {\n        return _exists(key)\n    }\n\n    function clone(v: any): any {\n        if (v == null) return null\n        return JSON.parse(JSON.stringify(v))\n    }\n\n    function isKV(v: any) {\n        return !!v && typeof v === \"object\" && !Array.isArray(v)\n    }\n\n    function jsonMergeFrom(trg: any, src: any) {\n        if (!src) return;\n        const keys = Object.keys(src)\n        keys.forEach(k => {\n            const srck = src[k];\n            if (isKV(trg[k]) && isKV(srck))\n                jsonMergeFrom(trg[k], srck);\n            else\n                trg[k] = clone(srck);\n        });\n    }\n\n    //% fixedInstances\n    export class SecretStore {\n        constructor(private key: string) { }\n\n        setSecret(name: string, value: any) {\n            const secrets = this.readSecrets();\n            secrets[name] = value;\n            writeJSON(this.key, secrets);\n        }\n\n        updateSecret(name: string, value: any) {\n            const secrets = this.readSecrets();\n            const secret = secrets[name];\n            if (secret === undefined)\n                secrets[name] = value;\n            else jsonMergeFrom(secret, value);\n            writeJSON(this.key, secrets)\n        }\n\n        readSecret(name: string, ensure: boolean = false): any {\n            const secrets = this.readSecrets();\n            const secret = secrets[name];\n            if (ensure && !secret)\n                throw \"missing secret \" + name;\n            return secret;\n        }\n\n        clearSecrets() {\n            writeString(this.key, \"{}\");\n        }\n\n        readSecrets(): any {\n            try {\n                return readJSON(this.key) || {}\n            } catch {\n                control.dmesg(\"invalid secret format\")\n                return {};\n            }\n        }\n    }\n\n    /**\n     * Secrets shared by any program on the device\n     */\n    //% fixedInstance whenUsed block=\"device secrets\"\n    export const deviceSecrets = new SecretStore(DEVICE_SECRETS_KEY);\n\n    /**\n     * Program secrets\n     */\n    //% fixedInstance whenUsed block=\"program secrets\"\n    export const programSecrets = new SecretStore(SECRETS_KEY);\n}\n","shims.d.ts":"\n","targetoverrides.ts":"namespace config {\n    // this is the smallest setting possible on NRF\n    export const SETTINGS_SIZE_DEFL = (8*1024)\n}\n"},"flashlog":{"README.md":"# datalog\n","enums.d.ts":"// Auto-generated. Do not edit.\n\n\n    declare const enum FlashLogTimeStampFormat\n    {\n    //% block=\"none\"\n    None = 0,\n    //% block=\"milliseconds\"\n    Milliseconds = 1,\n    //% block=\"seconds\"\n    Seconds = 10,\n    //% block=\"minutes\"\n    Minutes = 600,\n    //% block=\"hours\"\n    Hours = 36000,\n    //% block=\"days\"\n    Days = 864000,\n    }\ndeclare namespace flashlog {\n}\n\n// Auto-generated. Do not edit. Really.\n","flashlog.cpp":"#include \"pxt.h\"\n\n#if MICROBIT_CODAL\n#include \"MicroBitLog.h\"\n#endif\n\nenum class FlashLogTimeStampFormat\n{\n    //% block=\"none\"\n    None = 0,\n    //% block=\"milliseconds\"\n    Milliseconds = 1,\n    //% block=\"seconds\"\n    Seconds = 10,\n    //% block=\"minutes\"\n    Minutes = 600,\n    //% block=\"hours\"\n    Hours = 36000,\n    //% block=\"days\"\n    Days = 864000\n};\n\n/**\n * Storing structured data in flash.\n */\n//%\nnamespace flashlog {\n\n/**\n* Creates a new row in the log, ready to be populated by logData()\n**/\n//% help=flashlog/begin-row\n//% parts=\"flashlog\"\n//% blockGap=8\n//% group=\"micro:bit (V2)\"\nint beginRow() {\n#if MICROBIT_CODAL\n    return uBit.log.beginRow();\n#else\n    return DEVICE_NOT_SUPPORTED;\n#endif\n}\n\n/**\n* Populates the current row with the given key/value pair.\n**/\n//% help=flashlog/log-data\n//% parts=\"flashlog\"\n//% blockGap=8\n//% group=\"micro:bit (V2)\"\nint logData(String key, String value) {\n    if (NULL == key || NULL == value)\n        return DEVICE_INVALID_PARAMETER;\n#if MICROBIT_CODAL\n    return uBit.log.logData(MSTR(key), MSTR(value));\n#else\n    return DEVICE_NOT_SUPPORTED;\n#endif\n}\n\n/**\n* Inject the given row into the log as text, ignoring key/value pairs.\n**/\n//% help=flashlog/log-string\n//% parts=\"flashlog\"\n//% blockGap=8\n//% group=\"micro:bit (V2)\"\nint logString(String value) {\n    if (NULL == value)\n        return DEVICE_INVALID_PARAMETER;\n#if MICROBIT_CODAL\n    return uBit.log.logString(MSTR(value));\n#else\n    return DEVICE_NOT_SUPPORTED;\n#endif\n}\n\n/**\n* Complete a row in the log, and pushes to persistent storage.\n**/\n//% help=flashlog/end-row\n//% parts=\"flashlog\"\n//% blockGap=8\n//% group=\"micro:bit (V2)\"\nint endRow() {\n#if MICROBIT_CODAL\n    return uBit.log.endRow();\n#else\n    return DEVICE_NOT_SUPPORTED;\n#endif\n}\n\n/**\n* Resets all data stored in persistent storage.\n**/\n//% help=flashlog/clear\n//% parts=\"flashlog\"\n//% blockGap=8\n//% group=\"micro:bit (V2)\"\nvoid clear(bool fullErase) {\n#if MICROBIT_CODAL\n    uBit.log.clear(fullErase);\n#endif\n}\n\n/**\n* Determines the format of the timestamp data to be added (if any).\n* If requested, time stamps will be automatically added to each row of data\n* as an integer value rounded down to the unit specified.\n*\n* @param format The format of timestamp to use.\n*/\n//% help=flashlog/set-timestamp\n//% parts=\"flashlog\"\n//% blockGap=8\n//% group=\"micro:bit (V2)\"\nvoid setTimeStamp(FlashLogTimeStampFormat format) {\n#if MICROBIT_CODAL\n    return uBit.log.setTimeStamp((codal::TimeStampFormat)format);\n#endif\n}\n\n/**\n * Defines if data logging should also be streamed over the serial port.\n *\n * @param enable True to enable serial port streaming, false to disable.\n*/\n//% help=flashlog/set-serial-mirroring\n//% parts=\"flashlog\"\n//% blockGap=8\n//% group=\"micro:bit (V2)\"\nvoid setSerialMirroring(bool enable) {\n#if MICROBIT_CODAL\n    return uBit.log.setSerialMirroring(enable);\n#endif\n}\n\n/**\n* Number of rows currently used by the datalogger, start counting at fromRowIndex\n* Treats the header as the first row\n* @param fromRowIndex 0-based index of start: Default value of 0\n* @returns header + rows\n*/\n//%\nint getNumberOfRows(int fromRowIndex = 0) {\n#if MICROBIT_CODAL\n    return uBit.log.getNumberOfRows(fromRowIndex);\n#else\n    return DEVICE_NOT_SUPPORTED;\n#endif\n}\n\n/**\n* Get all rows separated by a newline & each column separated by a comma.\n* Starting at the 0-based index fromRowIndex & counting inclusively until nRows.\n* @param fromRowIndex 0-based index of start\n* @param nRows inclusive count from fromRowIndex\n* @returns String where newlines denote rows & commas denote columns\n*/\n//%\nString getRows(int fromRowIndex, int nRows) {\n#if MICROBIT_CODAL\n    return PSTR(uBit.log.getRows(fromRowIndex, nRows));\n#else\n    return DEVICE_NOT_SUPPORTED;\n#endif\n}\n\n}\n","pxt.json":"{\n    \"name\": \"flashlog\",\n    \"description\": \"Data logging to flash.\",\n    \"dependencies\": {\n        \"core\": \"*\"\n    },\n    \"files\": [\n        \"README.md\",\n        \"flashlog.cpp\",\n        \"shims.d.ts\",\n        \"enums.d.ts\"\n    ],\n    \"testFiles\": [\n        \"test.ts\"\n    ],\n    \"public\": true,\n    \"targetVersions\": {\n        \"target\": \"7.1.42\",\n        \"pxt\": \"11.4.28\"\n    },\n    \"searchOnly\": true,\n    \"disablesVariants\": [\n        \"mbdal\"\n    ],\n    \"icon\": \"/static/libs/flashlog.png\"\n}\n","shims.d.ts":"// Auto-generated. Do not edit.\n\n\n    /**\n     * Storing structured data in flash.\n     */\n    //%\ndeclare namespace flashlog {\n\n    /**\n     * Creates a new row in the log, ready to be populated by logData()\n     **/\n    //% help=flashlog/begin-row\n    //% parts=\"flashlog\"\n    //% blockGap=8\n    //% group=\"micro:bit (V2)\" shim=flashlog::beginRow\n    function beginRow(): int32;\n\n    /**\n     * Populates the current row with the given key/value pair.\n     **/\n    //% help=flashlog/log-data\n    //% parts=\"flashlog\"\n    //% blockGap=8\n    //% group=\"micro:bit (V2)\" shim=flashlog::logData\n    function logData(key: string, value: string): int32;\n\n    /**\n     * Inject the given row into the log as text, ignoring key/value pairs.\n     **/\n    //% help=flashlog/log-string\n    //% parts=\"flashlog\"\n    //% blockGap=8\n    //% group=\"micro:bit (V2)\" shim=flashlog::logString\n    function logString(value: string): int32;\n\n    /**\n     * Complete a row in the log, and pushes to persistent storage.\n     **/\n    //% help=flashlog/end-row\n    //% parts=\"flashlog\"\n    //% blockGap=8\n    //% group=\"micro:bit (V2)\" shim=flashlog::endRow\n    function endRow(): int32;\n\n    /**\n     * Resets all data stored in persistent storage.\n     **/\n    //% help=flashlog/clear\n    //% parts=\"flashlog\"\n    //% blockGap=8\n    //% group=\"micro:bit (V2)\" shim=flashlog::clear\n    function clear(fullErase: boolean): void;\n\n    /**\n     * Determines the format of the timestamp data to be added (if any).\n     * If requested, time stamps will be automatically added to each row of data\n     * as an integer value rounded down to the unit specified.\n     *\n     * @param format The format of timestamp to use.\n     */\n    //% help=flashlog/set-timestamp\n    //% parts=\"flashlog\"\n    //% blockGap=8\n    //% group=\"micro:bit (V2)\" shim=flashlog::setTimeStamp\n    function setTimeStamp(format: FlashLogTimeStampFormat): void;\n\n    /**\n     * Defines if data logging should also be streamed over the serial port.\n     *\n     * @param enable True to enable serial port streaming, false to disable.\n     */\n    //% help=flashlog/set-serial-mirroring\n    //% parts=\"flashlog\"\n    //% blockGap=8\n    //% group=\"micro:bit (V2)\" shim=flashlog::setSerialMirroring\n    function setSerialMirroring(enable: boolean): void;\n\n    /**\n     * Number of rows currently used by the datalogger, start counting at fromRowIndex\n     * Treats the header as the first row\n     * @param fromRowIndex 0-based index of start: Default value of 0\n     * @returns header + rows\n     */\n    //% fromRowIndex.defl=0 shim=flashlog::getNumberOfRows\n    function getNumberOfRows(fromRowIndex?: int32): int32;\n\n    /**\n     * Get all rows separated by a newline & each column separated by a comma.\n     * Starting at the 0-based index fromRowIndex & counting inclusively until nRows.\n     * @param fromRowIndex 0-based index of start\n     * @param nRows inclusive count from fromRowIndex\n     * @returns String where newlines denote rows & commas denote columns\n     */\n    //% shim=flashlog::getRows\n    function getRows(fromRowIndex: int32, nRows: int32): string;\n}\n\n// Auto-generated. Do not edit. Really.\n","test.ts":"input.onButtonPressed(Button.AB, function() {\n    flashlog.clear()\n})\nflashlog.setTimeStamp(FlashLogTimeStampFormat.Milliseconds)\nbasic.forever(function () {\n    led.toggle(0, 0)\n    const ax = input.acceleration(Dimension.X)\n\tflashlog.beginRow()\n    flashlog.logData(`a.x`, ax)\n    flashlog.logData(`a.y`, input.acceleration(Dimension.Y))\n    flashlog.endRow()\n})\n"},"datalogger":{"datalogger.ts":"/**\n * Log data to flash storage\n */\n//% block=\"Data Logger\"\n//% icon=\"\\uf0ce\"\n//% color=\"#378273\"\nnamespace datalogger {\n    export enum DeleteType {\n        //% block=\"fast\"\n        Fast,\n        //% block=\"full\"\n        Full\n    }\n\n    let onLogFullHandler: () => void;\n    let _disabled = false;\n\n    let initialized = false;\n    function init() {\n        if (initialized)\n            return;\n        initialized = true;\n\n        includeTimestamp(FlashLogTimeStampFormat.Seconds);\n        mirrorToSerial(false);\n\n        control.onEvent(DAL.MICROBIT_ID_LOG, DAL.MICROBIT_LOG_EVT_LOG_FULL, () => {\n            _disabled = true;\n            if (onLogFullHandler) {\n                onLogFullHandler();\n            } else {\n                basic.showLeds(`\n                    # . . . #\n                    # # . # #\n                    . . . . .\n                    . # # # .\n                    # . . . #\n                `);\n                basic.pause(1000);\n                basic.clearScreen();\n                basic.showString(\"928\");\n            }\n        });\n    }\n\n\n    export class ColumnValue {\n        public value: string;\n        constructor(\n            public column: string,\n            value: any\n        ) {\n            this.value = \"\" + value;\n        }\n    }\n\n    /**\n     * A column and value to log to flash storage\n     * @param column the column to set\n     * @param value the value to set.\n     * @returns A new value that can be stored in flash storage using log data\n     */\n    //% block=\"column $column value $value\"\n    //% value.shadow=math_number\n    //% column.shadow=datalogger_columnfield\n    //% blockId=dataloggercreatecolumnvalue\n    //% group=\"micro:bit (V2)\"\n    //% weight=80 help=datalogger/create-cv\n    export function createCV(column: string, value: any): ColumnValue {\n        return new ColumnValue(column, value);\n    }\n\n    //% block=\"$column\"\n    //% blockId=datalogger_columnfield\n    //% group=\"micro:bit (V2)\"\n    //% blockHidden=true shim=TD_ID\n    //% column.fieldEditor=\"autocomplete\" column.fieldOptions.decompileLiterals=true\n    //% column.fieldOptions.key=\"dataloggercolumn\"\n    export function _columnField(column: string) {\n        return column\n    }\n\n    /**\n     * Log data to flash storage\n     * @param data Array of data to be logged to flash storage\n     */\n    //% block=\"log data array $data\"\n    //% blockId=dataloggerlogdata\n    //% data.shadow=lists_create_with\n    //% data.defl=dataloggercreatecolumnvalue\n    //% group=\"micro:bit (V2)\"\n    //% blockHidden=true\n    //% weight=100\n    export function logData(data: ColumnValue[]): void {\n        if (!data || !data.length)\n            return;\n        init();\n\n        if (_disabled)\n            return;\n\n        flashlog.beginRow();\n        for (const cv of data) {\n            flashlog.logData(cv.column, cv.value);\n        }\n        flashlog.endRow();\n    }\n\n    /**\n     * Log data to flash storage\n     * @param data1 First column and value to be logged\n     * @param data2 [optional] second column and value to be logged\n     * @param data3 [optional] third column and value to be logged\n     * @param data4 [optional] fourth column and value to be logged\n     * @param data5 [optional] fifth column and value to be logged\n     * @param data6 [optional] sixth column and value to be logged\n     * @param data7 [optional] seventh column and value to be logged\n     * @param data8 [optional] eighth column and value to be logged\n     * @param data9 [optional] ninth column and value to be logged\n     * @param data10 [optional] tenth column and value to be logged\n     */\n    //% block=\"log data $data1||$data2 $data3 $data4 $data5 $data6 $data7 $data8 $data9 $data10\"\n    //% blockId=dataloggerlog\n    //% data1.shadow=dataloggercreatecolumnvalue\n    //% data2.shadow=dataloggercreatecolumnvalue\n    //% data3.shadow=dataloggercreatecolumnvalue\n    //% data4.shadow=dataloggercreatecolumnvalue\n    //% data5.shadow=dataloggercreatecolumnvalue\n    //% data6.shadow=dataloggercreatecolumnvalue\n    //% data7.shadow=dataloggercreatecolumnvalue\n    //% data8.shadow=dataloggercreatecolumnvalue\n    //% data9.shadow=dataloggercreatecolumnvalue\n    //% data10.shadow=dataloggercreatecolumnvalue\n    //% inlineInputMode=\"variable\"\n    //% inlineInputModeLimit=1\n    //% group=\"micro:bit (V2)\"\n    //% weight=100 help=datalogger/log\n    export function log(\n        data1: datalogger.ColumnValue,\n        data2?: datalogger.ColumnValue,\n        data3?: datalogger.ColumnValue,\n        data4?: datalogger.ColumnValue,\n        data5?: datalogger.ColumnValue,\n        data6?: datalogger.ColumnValue,\n        data7?: datalogger.ColumnValue,\n        data8?: datalogger.ColumnValue,\n        data9?: datalogger.ColumnValue,\n        data10?: datalogger.ColumnValue\n    ): void {\n        logData(\n            [\n                data1,\n                data2,\n                data3,\n                data4,\n                data5,\n                data6,\n                data7,\n                data8,\n                data9,\n                data10,\n            ].filter(el => !!el)\n        );\n    }\n\n    /**\n     * Set the columns for future data logging\n     * @param cols Array of the columns that will be logged.\n     */\n    //% block=\"set columns $cols\"\n    //% blockId=dataloggersetcolumns\n    //% data.shadow=list_create_with\n    //% data.defl=datalogger_columnfield\n    //% group=\"micro:bit (V2)\"\n    //% blockHidden=true\n    //% weight=70\n    export function setColumns(cols: string[]): void {\n        if (!cols)\n            return;\n\n        logData(cols.map(col => createCV(col, \"\")));\n    }\n\n    /**\n     * Set the columns for future data logging\n     * @param col1 Title for first column to be added\n     * @param col2 Title for second column to be added\n     * @param col3 Title for third column to be added\n     * @param col4 Title for fourth column to be added\n     * @param col5 Title for fifth column to be added\n     * @param col6 Title for sixth column to be added\n     * @param col7 Title for seventh column to be added\n     * @param col8 Title for eighth column to be added\n     * @param col9 Title for ninth column to be added\n     * @param col10 Title for tenth column to be added\n     */\n    //% block=\"set columns $col1||$col2 $col3 $col4 $col5 $col6 $col7 $col8 $col9 $col10\"\n    //% blockId=dataloggersetcolumntitles\n    //% inlineInputMode=\"variable\"\n    //% inlineInputModeLimit=1\n    //% group=\"micro:bit (V2)\"\n    //% weight=70 help=datalogger/set-column-titles\n    //% col1.shadow=datalogger_columnfield\n    //% col2.shadow=datalogger_columnfield\n    //% col3.shadow=datalogger_columnfield\n    //% col4.shadow=datalogger_columnfield\n    //% col5.shadow=datalogger_columnfield\n    //% col6.shadow=datalogger_columnfield\n    //% col7.shadow=datalogger_columnfield\n    //% col8.shadow=datalogger_columnfield\n    //% col9.shadow=datalogger_columnfield\n    //% col10.shadow=datalogger_columnfield\n    export function setColumnTitles(\n        col1: string,\n        col2?: string,\n        col3?: string,\n        col4?: string,\n        col5?: string,\n        col6?: string,\n        col7?: string,\n        col8?: string,\n        col9?: string,\n        col10?: string\n    ): void {\n        logData(\n            [col1, col2, col3, col4, col5, col6, col7, col8, col9, col10]\n                .filter(el => !!el)\n                .map(col => createCV(col, \"\"))\n        );\n    }\n\n    /**\n     * Delete all existing logs, including column headers. By default this only marks the log as\n     * overwriteable / deletable in the future.\n     * @param deleteType optional set whether a deletion will be fast or full\n     */\n    //% block=\"delete log||$deleteType\"\n    //% blockId=dataloggerdeletelog\n    //% group=\"micro:bit (V2)\"\n    //% weight=60 help=datalogger/delete-log\n    export function deleteLog(deleteType?: DeleteType): void {\n        init();\n        flashlog.clear(deleteType === DeleteType.Full);\n        _disabled = false;\n    }\n\n    /**\n     * Register an event to run when no more data can be logged.\n     * @param handler code to run when the log is full and no more data can be stored.\n     */\n    //% block=\"on log full\"\n    //% blockId=\"on log full\"\n    //% group=\"micro:bit (V2)\"\n    //% weight=40 help=datalogger/on-log-full\n    export function onLogFull(handler: () => void): void {\n        init();\n        onLogFullHandler = handler;\n    }\n\n    /**\n     * Set the format for timestamps\n     * @param format Format in which to show the timestamp. Setting FlashLogTimeStampFormat.None will disable the timestamp.\n     */\n    //% block=\"set timestamp $format\"\n    //% blockId=dataloggertoggleincludetimestamp\n    //% format.defl=FlashLogTimeStampFormat.None\n    //% group=\"micro:bit (V2)\"\n    //% weight=30 help=datalogger/include-timestamp\n    export function includeTimestamp(format: FlashLogTimeStampFormat): void {\n        init();\n        flashlog.setTimeStamp(format);\n    }\n\n    /**\n     * Set whether data is mirrored to serial or not.\n     * @param on if true, data that is logged will be mirrored to serial\n     */\n    //% block=\"mirror data to serial $on\"\n    //% blockId=dataloggertogglemirrortoserial\n    //% on.shadow=toggleOnOff\n    //% on.defl=false\n    //% weight=25 help=datalogger/mirror-to-serial\n    export function mirrorToSerial(on: boolean): void {\n        // TODO:/note intentionally does not have group, as having the same group for all\n        // blocks in a category causes the group to be elided.\n        init();\n        flashlog.setSerialMirroring(on);\n    }\n\n    /**\n     * Number of rows currently used by the datalogger, start counting at fromRowIndex\n     * Treats the header as the first row\n     * @param fromRowIndex 0-based index of start\n     * @returns header + rows\n     */\n    export function getNumberOfRows(fromRowIndex: number = 0): number {\n        return flashlog.getNumberOfRows(fromRowIndex);\n    }\n\n    /**\n     * Get all rows seperated by a newline & each column seperated by a comma.\n     * Starting at the 0-based index fromRowIndex & counting inclusively until nRows.\n     * @param fromRowIndex 0-based index of start\n     * @param nRows inclusive count from fromRowIndex\n     * @returns String where newlines denote rows & commas denote columns\n     */\n    export function getRows(fromRowIndex: number, nRows: number): string {\n        return flashlog.getRows(fromRowIndex, nRows);\n    }\n}\n","pxt.json":"{\n    \"name\": \"datalogger\",\n    \"description\": \"Data logging to flash memory. micro:bit (V2) only.\",\n    \"dependencies\": {\n        \"core\": \"*\",\n        \"flashlog\": \"*\"\n    },\n    \"files\": [\n        \"datalogger.ts\"\n    ],\n    \"public\": true,\n    \"targetVersions\": {\n        \"target\": \"7.1.42\",\n        \"pxt\": \"11.4.28\"\n    },\n    \"disablesVariants\": [\n        \"mbdal\"\n    ],\n    \"yotta\": {\n        \"config\": {\n            \"MICROBIT_BLE_UTILITY_SERVICE\": 1,\n            \"MICROBIT_BLE_UTILITY_SERVICE_PAIRING\": 1\n        }\n    },\n    \"icon\": \"/static/libs/datalogger.png\"\n}\n"},"bitmap":{"bitmap.cpp":"#include \"pxt.h\"\n\ntypedef RefImage *Bitmap_;\n\n#define IMAGE_BITS 4\n\n#if IMAGE_BITS == 1\n// OK\n#elif IMAGE_BITS == 4\n// OK\n#else\n#error \"Invalid IMAGE_BITS\"\n#endif\n\n#define XX(v) (int)(((int16_t)(v)))\n#define YY(v) (int)(((int16_t)(((int32_t)(v)) >> 16)))\n\nnamespace pxt {\n\nPXT_VTABLE(RefImage, ValType::Object)\n\nvoid RefImage::destroy(RefImage *t) {}\n\nvoid RefImage::print(RefImage *t) {\n    DMESG(\"RefImage %p size=%d x %d\", t, t->width(), t->height());\n}\n\nint RefImage::wordHeight() {\n    if (bpp() == 1)\n        oops(20);\n    return ((height() * 4 + 31) >> 5);\n}\n\nvoid RefImage::makeWritable() {\n    ++revision;\n    if (buffer->isReadOnly()) {\n        buffer = mkBuffer(data(), length());\n    }\n}\n\nuint8_t RefImage::fillMask(color c) {\n    return this->bpp() == 1 ? (c & 1) * 0xff : 0x11 * (c & 0xf);\n}\n\nbool RefImage::inRange(int x, int y) {\n    return 0 <= x && x < width() && 0 <= y && y < height();\n}\n\nvoid RefImage::clamp(int *x, int *y) {\n    *x = min(max(*x, 0), width() - 1);\n    *y = min(max(*y, 0), height() - 1);\n}\n\nRefImage::RefImage(BoxedBuffer *buf) : PXT_VTABLE_INIT(RefImage), buffer(buf) {\n    revision = 0;\n    if (!buf)\n        oops(21);\n}\n\nstatic inline int byteSize(int w, int h, int bpp) {\n    if (bpp == 1)\n        return sizeof(ImageHeader) + ((h + 7) >> 3) * w;\n    else\n        return sizeof(ImageHeader) + (((h * 4 + 31) / 32) * 4) * w;\n}\n\nBitmap_ allocImage(const uint8_t *data, uint32_t sz) {\n    auto buf = mkBuffer(data, sz);\n    registerGCObj(buf);\n    Bitmap_ r = NEW_GC(RefImage, buf);\n    unregisterGCObj(buf);\n    return r;\n}\n\nBitmap_ mkImage(int width, int height, int bpp) {\n    if (width < 0 || height < 0 || width > 2000 || height > 2000)\n        return NULL;\n    if (bpp != 1 && bpp != 4)\n        return NULL;\n    uint32_t sz = byteSize(width, height, bpp);\n    Bitmap_ r = allocImage(NULL, sz);\n    auto hd = r->header();\n    hd->magic = IMAGE_HEADER_MAGIC;\n    hd->bpp = bpp;\n    hd->width = width;\n    hd->height = height;\n    hd->padding = 0;\n    MEMDBG(\"mkImage: %d X %d => %p\", width, height, r);\n    return r;\n}\n\nbool isValidImage(Buffer buf) {\n    if (!buf || buf->length < 9)\n        return false;\n\n    auto hd = (ImageHeader *)(buf->data);\n    if (hd->magic != IMAGE_HEADER_MAGIC || (hd->bpp != 1 && hd->bpp != 4))\n        return false;\n\n    int sz = byteSize(hd->width, hd->height, hd->bpp);\n    if (sz != (int)buf->length)\n        return false;\n\n    return true;\n}\n\nbool isLegacyImage(Buffer buf) {\n    if (!buf || buf->length < 5)\n        return false;\n\n    if (buf->data[0] != 0xe1 && buf->data[0] != 0xe4)\n        return false;\n\n    int sz = byteSize(buf->data[1], buf->data[2], buf->data[0] & 0xf) - 4;\n    if (sz != (int)buf->length)\n        return false;\n\n    return true;\n}\n\n} // namespace pxt\n\nnamespace BitmapMethods {\n\n/**\n * Get underlying buffer\n */\n//% property\nBuffer __buffer(Bitmap_ img) {\n    // only for simulator\n    return NULL;\n}\n\n/**\n * Get the width of the bitmap\n */\n//% property\nint width(Bitmap_ img) {\n    return img->width();\n}\n\n/**\n * Get the height of the bitmap\n */\n//% property\nint height(Bitmap_ img) {\n    return img->height();\n}\n\n/**\n * True if the bitmap is monochromatic (black and white)\n */\n//% property\nbool isMono(Bitmap_ img) {\n    return img->bpp() == 1;\n}\n\n//% property\nbool isStatic(Bitmap_ img) {\n    return img->buffer->isReadOnly();\n}\n\n//% property\nbool revision(Bitmap_ img) {\n    return img->revision;\n}\n\n/**\n * Sets all pixels in the current bitmap from the other bitmap, which has to be of the same size and\n * bpp.\n */\n//%\nvoid copyFrom(Bitmap_ img, Bitmap_ from) {\n    if (img->width() != from->width() || img->height() != from->height() ||\n        img->bpp() != from->bpp())\n        return;\n    img->makeWritable();\n    memcpy(img->pix(), from->pix(), from->pixLength());\n}\n\nstatic void setCore(Bitmap_ img, int x, int y, int c) {\n    auto ptr = img->pix(x, y);\n    if (img->bpp() == 4) {\n        if (y & 1)\n            *ptr = (*ptr & 0x0f) | (c << 4);\n        else\n            *ptr = (*ptr & 0xf0) | (c & 0xf);\n    } else if (img->bpp() == 1) {\n        uint8_t mask = 0x01 << (y & 7);\n        if (c)\n            *ptr |= mask;\n        else\n            *ptr &= ~mask;\n    }\n}\n\nstatic int getCore(Bitmap_ img, int x, int y) {\n    auto ptr = img->pix(x, y);\n    if (img->bpp() == 4) {\n        if (y & 1)\n            return *ptr >> 4;\n        else\n            return *ptr & 0x0f;\n    } else if (img->bpp() == 1) {\n        uint8_t mask = 0x01 << (y & 7);\n        return (*ptr & mask) ? 1 : 0;\n    }\n    return 0;\n}\n\n/**\n * Set pixel color\n */\n//%\nvoid setPixel(Bitmap_ img, int x, int y, int c) {\n    if (!img->inRange(x, y))\n        return;\n    img->makeWritable();\n    setCore(img, x, y, c);\n}\n\n/**\n * Get a pixel color\n */\n//%\nint getPixel(Bitmap_ img, int x, int y) {\n    if (!img->inRange(x, y))\n        return 0;\n    return getCore(img, x, y);\n}\n\nvoid fillRect(Bitmap_ img, int x, int y, int w, int h, int c);\n\n/**\n * Fill entire bitmap with a given color\n */\n//%\nvoid fill(Bitmap_ img, int c) {\n    if (c && img->hasPadding()) {\n        fillRect(img, 0, 0, img->width(), img->height(), c);\n        return;\n    }\n    img->makeWritable();\n    memset(img->pix(), img->fillMask(c), img->pixLength());\n}\n\n/**\n * Copy row(s) of pixel from bitmap to buffer (8 bit per pixel).\n */\n//%\nvoid getRows(Bitmap_ img, int x, Buffer dst) {\n    if (img->bpp() != 4)\n        return;\n\n    int w = img->width();\n    int h = img->height();\n    if (x >= w || x < 0)\n        return;\n\n    uint8_t *sp = img->pix(x, 0);\n    uint8_t *dp = dst->data;\n    int n = min(dst->length, (w - x) * h) >> 1;\n\n    while (n--) {\n        *dp++ = *sp & 0xf;\n        *dp++ = *sp >> 4;\n        sp++;\n    }\n}\n\n/**\n * Copy row(s) of pixel from buffer to bitmap.\n */\n//%\nvoid setRows(Bitmap_ img, int x, Buffer src) {\n    if (img->bpp() != 4)\n        return;\n\n    int w = img->width();\n    int h = img->height();\n    if (x >= w || x < 0)\n        return;\n\n    img->makeWritable();\n\n    uint8_t *dp = img->pix(x, 0);\n    uint8_t *sp = src->data;\n    int n = min(src->length, (w - x) * h) >> 1;\n\n    while (n--) {\n        *dp++ = (sp[0] & 0xf) | (sp[1] << 4);\n        sp += 2;\n    }\n}\n\nvoid fillRect(Bitmap_ img, int x, int y, int w, int h, int c) {\n    if (w == 0 || h == 0 || x >= img->width() || y >= img->height())\n        return;\n\n    int x2 = x + w - 1;\n    int y2 = y + h - 1;\n\n    if (x2 < 0 || y2 < 0)\n        return;\n\n    img->clamp(&x2, &y2);\n    img->clamp(&x, &y);\n    w = x2 - x + 1;\n    h = y2 - y + 1;\n\n    if (!img->hasPadding() && x == 0 && y == 0 && w == img->width() && h == img->height()) {\n        fill(img, c);\n        return;\n    }\n\n    img->makeWritable();\n\n    auto bh = img->byteHeight();\n    uint8_t f = img->fillMask(c);\n\n    uint8_t *p = img->pix(x, y);\n    while (w-- > 0) {\n        if (img->bpp() == 1) {\n            auto ptr = p;\n            unsigned mask = 0x01 << (y & 7);\n\n            for (int i = 0; i < h; ++i) {\n                if (mask == 0x100) {\n                    if (h - i >= 8) {\n                        *++ptr = f;\n                        i += 7;\n                        continue;\n                    } else {\n                        mask = 0x01;\n                        ++ptr;\n                    }\n                }\n                if (c)\n                    *ptr |= mask;\n                else\n                    *ptr &= ~mask;\n                mask <<= 1;\n            }\n\n        } else if (img->bpp() == 4) {\n            auto ptr = p;\n            unsigned mask = 0x0f;\n            if (y & 1)\n                mask <<= 4;\n\n            for (int i = 0; i < h; ++i) {\n                if (mask == 0xf00) {\n                    if (h - i >= 2) {\n                        *++ptr = f;\n                        i++;\n                        continue;\n                    } else {\n                        mask = 0x0f;\n                        ptr++;\n                    }\n                }\n                *ptr = (*ptr & ~mask) | (f & mask);\n                mask <<= 4;\n            }\n        }\n        p += bh;\n    }\n}\n\n//%\nvoid _fillRect(Bitmap_ img, int xy, int wh, int c) {\n    fillRect(img, XX(xy), YY(xy), XX(wh), YY(wh), c);\n}\n\nvoid mapRect(Bitmap_ img, int x, int y, int w, int h, Buffer map) {\n    if (w == 0 || h == 0 || x >= img->width() || y >= img->height())\n        return;\n\n    if (img->bpp() != 4 || map->length < 16)\n        return;\n\n    int x2 = x + w - 1;\n    int y2 = y + h - 1;\n\n    if (x2 < 0 || y2 < 0)\n        return;\n\n    img->clamp(&x2, &y2);\n    img->clamp(&x, &y);\n    w = x2 - x + 1;\n    h = y2 - y + 1;\n\n    img->makeWritable();\n\n    auto bh = img->byteHeight();\n    auto m = map->data;\n    uint8_t *p = img->pix(x, y);\n    while (w-- > 0) {\n        auto ptr = p;\n        unsigned shift = y & 1;\n        for (int i = 0; i < h; i++) {\n            if (shift) {\n                *ptr = (m[*ptr >> 4] << 4) | (*ptr & 0x0f);\n                ptr++;\n                shift = 0;\n            } else {\n                *ptr = (m[*ptr & 0xf] & 0xf) | (*ptr & 0xf0);\n                shift = 1;\n            }\n        }\n        p += bh;\n    }\n}\n\n//%\nvoid _mapRect(Bitmap_ img, int xy, int wh, Buffer c) {\n    mapRect(img, XX(xy), YY(xy), XX(wh), YY(wh), c);\n}\n\n//% argsNullable\nbool equals(Bitmap_ img, Bitmap_ other) {\n    if (!other) {\n        return false;\n    }\n    auto len = img->length();\n    if (len != other->length()) {\n        return false;\n    }\n    return 0 == memcmp(img->data(), other->data(), len);\n}\n\n/**\n * Return a copy of the current bitmap\n */\n//%\nBitmap_ clone(Bitmap_ img) {\n    auto r = allocImage(img->data(), img->length());\n    MEMDBG(\"mkImageClone: %d X %d => %p\", img->width(), img->height(), r);\n    return r;\n}\n\n/**\n * Flips (mirrors) pixels horizontally in the current bitmap\n */\n//%\nvoid flipX(Bitmap_ img) {\n    img->makeWritable();\n\n    int bh = img->byteHeight();\n    auto a = img->pix();\n    auto b = img->pix(img->width() - 1, 0);\n\n    uint8_t tmp[bh];\n\n    while (a < b) {\n        memcpy(tmp, a, bh);\n        memcpy(a, b, bh);\n        memcpy(b, tmp, bh);\n        a += bh;\n        b -= bh;\n    }\n}\n\n/**\n * Flips (mirrors) pixels vertically in the current bitmap\n */\n//%\nvoid flipY(Bitmap_ img) {\n    img->makeWritable();\n\n    // this is quite slow - for small 16x16 sprite it will take in the order of 1ms\n    // something faster requires quite a bit of bit tweaking, especially for mono bitmaps\n    for (int i = 0; i < img->width(); ++i) {\n        int a = 0;\n        int b = img->height() - 1;\n        while (a < b) {\n            int tmp = getCore(img, i, a);\n            setCore(img, i, a, getCore(img, i, b));\n            setCore(img, i, b, tmp);\n            a++;\n            b--;\n        }\n    }\n}\n\n/**\n * Returns a transposed bitmap (with X/Y swapped)\n */\n//%\nBitmap_ transposed(Bitmap_ img) {\n    Bitmap_ r = mkImage(img->height(), img->width(), img->bpp());\n\n    // this is quite slow\n    for (int i = 0; i < img->width(); ++i) {\n        for (int j = 0; j < img->height(); ++i) {\n            setCore(r, j, i, getCore(img, i, j));\n        }\n    }\n\n    return r;\n}\n\nvoid drawBitmap(Bitmap_ img, Bitmap_ from, int x, int y);\n\n/**\n * Every pixel in bitmap is moved by (dx,dy)\n */\n//%\nvoid scroll(Bitmap_ img, int dx, int dy) {\n    img->makeWritable();\n    auto bh = img->byteHeight();\n    auto w = img->width();\n    if (dy != 0) {\n        // TODO one day we may want a more memory-efficient implementation\n        auto img2 = clone(img);\n        fill(img, 0);\n        drawBitmap(img, img2, dx, dy);\n    } else if (dx < 0) {\n        dx = -dx;\n        if (dx < w)\n            memmove(img->pix(), img->pix(dx, 0), (w - dx) * bh);\n        else\n            dx = w;\n        memset(img->pix(w - dx, 0), 0, dx * bh);\n    } else if (dx > 0) {\n        if (dx < w)\n            memmove(img->pix(dx, 0), img->pix(), (w - dx) * bh);\n        else\n            dx = w;\n        memset(img->pix(), 0, dx * bh);\n    }\n}\n\nconst uint8_t bitdouble[] = {0x00, 0x03, 0x0c, 0x0f, 0x30, 0x33, 0x3c, 0x3f,\n                             0xc0, 0xc3, 0xcc, 0xcf, 0xf0, 0xf3, 0xfc, 0xff};\nconst uint8_t nibdouble[] = {0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77,\n                             0x88, 0x99, 0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff};\n\n/**\n * Stretches the bitmap horizontally by 100%\n */\n//%\nBitmap_ doubledX(Bitmap_ img) {\n    if (img->width() > 126)\n        return NULL;\n\n    Bitmap_ r = mkImage(img->width() * 2, img->height(), img->bpp());\n    auto src = img->pix();\n    auto dst = r->pix();\n    auto w = img->width();\n    auto bh = img->byteHeight();\n\n    for (int i = 0; i < w; ++i) {\n        memcpy(dst, src, bh);\n        dst += bh;\n        memcpy(dst, src, bh);\n        dst += bh;\n\n        src += bh;\n    }\n\n    return r;\n}\n\n/**\n * Stretches the bitmap vertically by 100%\n */\n//%\nBitmap_ doubledY(Bitmap_ img) {\n    if (img->height() > 126)\n        return NULL;\n\n    Bitmap_ r = mkImage(img->width(), img->height() * 2, img->bpp());\n    auto src0 = img->pix();\n    auto dst = r->pix();\n\n    auto w = img->width();\n    auto sbh = img->byteHeight();\n    auto bh = r->byteHeight();\n    auto dbl = img->bpp() == 1 ? bitdouble : nibdouble;\n\n    for (int i = 0; i < w; ++i) {\n        auto src = src0 + i * sbh;\n        for (int j = 0; j < bh; j += 2) {\n            *dst++ = dbl[*src & 0xf];\n            if (j != bh - 1)\n                *dst++ = dbl[*src >> 4];\n            src++;\n        }\n    }\n\n    return r;\n}\n\n/**\n * Replaces one color in an bitmap with another\n */\n//%\nvoid replace(Bitmap_ img, int from, int to) {\n    if (img->bpp() != 4)\n        return;\n    to &= 0xf;\n    if (from == to)\n        return;\n\n    img->makeWritable();\n\n    // avoid bleeding 'to' color into the overflow areas of the picture\n    if (from == 0 && img->hasPadding()) {\n        for (int i = 0; i < img->height(); ++i)\n            for (int j = 0; j < img->width(); ++j)\n                if (getCore(img, j, i) == from)\n                    setCore(img, j, i, to);\n        return;\n    }\n\n    auto ptr = img->pix();\n    auto len = img->pixLength();\n    while (len--) {\n        auto b = *ptr;\n        if ((b & 0xf) == from)\n            b = (b & 0xf0) | to;\n        if ((b >> 4) == from)\n            b = (to << 4) | (b & 0xf);\n        *ptr++ = b;\n    }\n}\n\n/**\n * Stretches the bitmap in both directions by 100%\n */\n//%\nBitmap_ doubled(Bitmap_ img) {\n    Bitmap_ tmp = doubledX(img);\n    registerGCObj(tmp);\n    Bitmap_ r = doubledY(tmp);\n    unregisterGCObj(tmp);\n    return r;\n}\n\nbool drawBitmapCore(Bitmap_ img, Bitmap_ from, int x, int y, int color) {\n    auto w = from->width();\n    auto h = from->height();\n    auto sh = img->height();\n    auto sw = img->width();\n\n    if (x + w <= 0)\n        return false;\n    if (x >= sw)\n        return false;\n    if (y + h <= 0)\n        return false;\n    if (y >= sh)\n        return false;\n\n    auto len = y < 0 ? min(sh, h + y) : min(sh - y, h);\n    auto tbp = img->bpp();\n    auto fbp = from->bpp();\n    auto y0 = y;\n\n    if (color == -2 && x == 0 && y == 0 && tbp == fbp && w == sw && h == sh) {\n        copyFrom(img, from);\n        return false;\n    }\n\n    // DMESG(\"drawIMG(%d,%d) at (%d,%d) w=%d bh=%d len=%d\",\n    //    w,h,x, y, img->width(), img->byteHeight(), len );\n\n    auto fromH = from->byteHeight();\n    auto imgH = img->byteHeight();\n    auto fromBase = from->pix();\n    auto imgBase = img->pix(0, y);\n\n#define LOOPHD                                                                                     \\\n    for (int xx = 0; xx < w; ++xx, ++x)                                                            \\\n        if (0 <= x && x < sw)\n\n    if (tbp == 4 && fbp == 4) {\n        auto wordH = fromH >> 2;\n        LOOPHD {\n            y = y0;\n\n            auto fdata = (uint32_t *)fromBase + wordH * xx;\n            auto tdata = imgBase + imgH * x;\n\n            // DMESG(\"%d,%d xx=%d/%d - %p (%p) -- %d\",x,y,xx,w,tdata,img->pix(),\n            //    (uint8_t*)fdata - from->pix());\n\n            auto cnt = wordH;\n            auto bot = min(sh, y + h);\n\n#define COLS(s) ((v >> (s)) & 0xf)\n#define COL(s) COLS(s)\n\n#define STEPA(s)                                                                                   \\\n    if (COL(s) && 0 <= y && y < bot)                                                               \\\n        SETLOW(s);                                                                                 \\\n    y++;\n#define STEPB(s)                                                                                   \\\n    if (COL(s) && 0 <= y && y < bot)                                                               \\\n        SETHIGH(s);                                                                                \\\n    y++;                                                                                           \\\n    tdata++;\n#define STEPAQ(s)                                                                                  \\\n    if (COL(s))                                                                                    \\\n        SETLOW(s);\n#define STEPBQ(s)                                                                                  \\\n    if (COL(s))                                                                                    \\\n        SETHIGH(s);                                                                                \\\n    tdata++;\n\n// perf: expanded version 5% faster\n#define ORDER(A, B)                                                                                \\\n    A(0);                                                                                          \\\n    B(4);                                                                                          \\\n    A(8);                                                                                          \\\n    B(12);                                                                                         \\\n    A(16);                                                                                         \\\n    B(20);                                                                                         \\\n    A(24);                                                                                         \\\n    B(28)\n//#define ORDER(A,B) for (int k = 0; k < 32; k += 8) { A(k); B(4+k); }\n#define LOOP(A, B, xbot)                                                                           \\\n    while (cnt--) {                                                                                \\\n        auto v = *fdata++;                                                                         \\\n        if (0 <= y && y <= xbot - 8) {                                                             \\\n            ORDER(A##Q, B##Q);                                                                     \\\n            y += 8;                                                                                \\\n        } else {                                                                                   \\\n            ORDER(A, B);                                                                           \\\n        }                                                                                          \\\n    }\n#define LOOPS(xbot)                                                                                \\\n    if (y & 1)                                                                                     \\\n        LOOP(STEPB, STEPA, xbot)                                                                   \\\n    else                                                                                           \\\n        LOOP(STEPA, STEPB, xbot)\n\n            if (color >= 0) {\n#define SETHIGH(s) *tdata = (*tdata & 0x0f) | ((COLS(s)) << 4)\n#define SETLOW(s) *tdata = (*tdata & 0xf0) | COLS(s)\n                LOOPS(sh)\n            } else if (color == -2) {\n#undef COL\n#define COL(s) 1\n                LOOPS(bot)\n            } else {\n#undef COL\n#define COL(s) COLS(s)\n#undef SETHIGH\n#define SETHIGH(s)                                                                                 \\\n    if (*tdata & 0xf0)                                                                             \\\n    return true\n#undef SETLOW\n#define SETLOW(s)                                                                                  \\\n    if (*tdata & 0x0f)                                                                             \\\n    return true\n                LOOPS(sh)\n            }\n        }\n    } else if (tbp == 1 && fbp == 1) {\n        auto left = img->pix() - imgBase;\n        auto right = img->pix(0, img->height() - 1) - imgBase;\n        LOOPHD {\n            y = y0;\n\n            auto data = fromBase + fromH * xx;\n            auto off = imgBase + imgH * x;\n            auto off0 = off + left;\n            auto off1 = off + right;\n\n            int shift = (y & 7);\n\n            int y1 = y + h + (y & 7);\n            int prev = 0;\n\n            while (y < y1 - 8) {\n                int curr = *data++ << shift;\n                if (off0 <= off && off <= off1) {\n                    uint8_t v = (curr >> 0) | (prev >> 8);\n\n                    if (color == -1) {\n                        if (*off & v)\n                            return true;\n                    } else {\n                        *off |= v;\n                    }\n                }\n                off++;\n                prev = curr;\n                y += 8;\n            }\n\n            int left = y1 - y;\n            if (left > 0) {\n                int curr = *data << shift;\n                if (off0 <= off && off <= off1) {\n                    uint8_t v = ((curr >> 0) | (prev >> 8)) & (0xff >> (8 - left));\n                    if (color == -1) {\n                        if (*off & v)\n                            return true;\n                    } else {\n                        *off |= v;\n                    }\n                }\n            }\n        }\n    } else if (tbp == 4 && fbp == 1) {\n        if (y < 0) {\n            fromBase = from->pix(0, -y);\n            imgBase = img->pix();\n        }\n        // icon mode\n        LOOPHD {\n            auto fdata = fromBase + fromH * xx;\n            auto tdata = imgBase + imgH * x;\n\n            unsigned mask = 0x01;\n            auto v = *fdata++;\n            int off = (y & 1) ? 1 : 0;\n            if (y < 0) {\n                mask <<= -y & 7;\n                off = 0;\n            }\n            for (int i = off; i < len + off; ++i) {\n                if (mask == 0x100) {\n                    mask = 0x01;\n                    v = *fdata++;\n                }\n                if (v & mask) {\n                    if (i & 1)\n                        *tdata = (*tdata & 0x0f) | (color << 4);\n                    else\n                        *tdata = (*tdata & 0xf0) | color;\n                }\n                mask <<= 1;\n                if (i & 1)\n                    tdata++;\n            }\n        }\n    }\n\n    return false;\n}\n\n/**\n * Draw given bitmap on the current bitmap\n */\n//%\nvoid drawBitmap(Bitmap_ img, Bitmap_ from, int x, int y) {\n    img->makeWritable();\n    if (img->bpp() == 4 && from->bpp() == 4) {\n        drawBitmapCore(img, from, x, y, -2);\n    } else {\n        fillRect(img, x, y, from->width(), from->height(), 0);\n        drawBitmapCore(img, from, x, y, 0);\n    }\n}\n\n/**\n * Draw given bitmap with transparent background on the current bitmap\n */\n//%\nvoid drawTransparentBitmap(Bitmap_ img, Bitmap_ from, int x, int y) {\n    img->makeWritable();\n    drawBitmapCore(img, from, x, y, 0);\n}\n\n/**\n * Check if the current bitmap \"collides\" with another\n */\n//%\nbool overlapsWith(Bitmap_ img, Bitmap_ other, int x, int y) {\n    return drawBitmapCore(img, other, x, y, -1);\n}\n\n// Bitmap_ format (legacy)\n//  byte 0: magic 0xe4 - 4 bit color; 0xe1 is monochromatic\n//  byte 1: width in pixels\n//  byte 2: height in pixels\n//  byte 3: padding (should be zero)\n//  byte 4...N: data 4 bits per pixels, high order nibble printed first, lines aligned to 32 bit\n//  words byte 4...N: data 1 bit per pixels, high order bit printed first, lines aligned to byte\n\nBitmap_ convertAndWrap(Buffer buf) {\n    if (isValidImage(buf))\n        return NEW_GC(RefImage, buf);\n\n    // What follows in this function is mostly dead code, except if people construct bitmap buffers\n    // by hand. Probably safe to remove in a year (middle of 2020) or so. When removing, also remove\n    // from sim.\n    if (!isLegacyImage(buf))\n        return NULL;\n\n    auto tmp = mkBuffer(NULL, buf->length + 4);\n    auto hd = (ImageHeader *)tmp->data;\n    auto src = buf->data;\n    hd->magic = IMAGE_HEADER_MAGIC;\n    hd->bpp = src[0] & 0xf;\n    hd->width = src[1];\n    hd->height = src[2];\n    hd->padding = 0;\n    memcpy(hd->pixels, src + 4, buf->length - 4);\n\n    registerGCObj(tmp);\n    auto r = NEW_GC(RefImage, tmp);\n    unregisterGCObj(tmp);\n    return r;\n}\n\n//%\nvoid _drawIcon(Bitmap_ img, Buffer icon, int xy, int c) {\n    img->makeWritable();\n\n    auto iconImg = convertAndWrap(icon);\n    if (!iconImg || iconImg->bpp() != 1)\n        return;\n\n    drawBitmapCore(img, iconImg, XX(xy), YY(xy), c);\n}\n\nstatic void drawLineLow(Bitmap_ img, int x0, int y0, int x1, int y1, int c) {\n    int dx = x1 - x0;\n    int dy = y1 - y0;\n    int yi = 1;\n    if (dy < 0) {\n        yi = -1;\n        dy = -dy;\n    }\n    int D = 2 * dy - dx;\n    dx <<= 1;\n    dy <<= 1;\n    int y = y0;\n    for (int x = x0; x <= x1; ++x) {\n        setCore(img, x, y, c);\n        if (D > 0) {\n            y += yi;\n            D -= dx;\n        }\n        D += dy;\n    }\n}\n\nstatic void drawLineHigh(Bitmap_ img, int x0, int y0, int x1, int y1, int c) {\n    int dx = x1 - x0;\n    int dy = y1 - y0;\n    int xi = 1;\n    if (dx < 0) {\n        xi = -1;\n        dx = -dx;\n    }\n    int D = 2 * dx - dy;\n    dx <<= 1;\n    dy <<= 1;\n    int x = x0;\n    for (int y = y0; y <= y1; ++y) {\n        setCore(img, x, y, c);\n        if (D > 0) {\n            x += xi;\n            D -= dy;\n        }\n        D += dx;\n    }\n}\n\nvoid drawLine(Bitmap_ img, int x0, int y0, int x1, int y1, int c) {\n    if (x1 < x0) {\n        drawLine(img, x1, y1, x0, y0, c);\n        return;\n    }\n    int w = x1 - x0;\n    int h = y1 - y0;\n\n    if (h == 0) {\n        if (w == 0)\n            setPixel(img, x0, y0, c);\n        else\n            fillRect(img, x0, y0, w + 1, 1, c);\n        return;\n    }\n\n    if (w == 0) {\n        if (h > 0)\n            fillRect(img, x0, y0, 1, h + 1, c);\n        else\n            fillRect(img, x0, y1, 1, -h + 1, c);\n        return;\n    }\n\n    if (x1 < 0 || x0 >= img->width())\n        return;\n    if (x0 < 0) {\n        y0 -= (h * x0 / w);\n        x0 = 0;\n    }\n    if (x1 >= img->width()) {\n        int d = (img->width() - 1) - x1;\n        y1 += (h * d / w);\n        x1 = img->width() - 1;\n    }\n\n    if (y0 < y1) {\n        if (y0 >= img->height() || y1 < 0)\n            return;\n        if (y0 < 0) {\n            x0 -= (w * y0 / h);\n            y0 = 0;\n        }\n        if (y1 >= img->height()) {\n            int d = (img->height() - 1) - y1;\n            x1 += (w * d / h);\n            y1 = img->height() - 1;\n        }\n    } else {\n        if (y1 >= img->height() || y0 < 0)\n            return;\n        if (y1 < 0) {\n            x1 -= (w * y1 / h);\n            y1 = 0;\n        }\n        if (y0 >= img->height()) {\n            int d = (img->height() - 1) - y0;\n            x0 += (w * d / h);\n            y0 = img->height() - 1;\n        }\n    }\n\n    img->makeWritable();\n\n    if (h < 0) {\n        h = -h;\n        if (h < w)\n            drawLineLow(img, x0, y0, x1, y1, c);\n        else\n            drawLineHigh(img, x1, y1, x0, y0, c);\n    } else {\n        if (h < w)\n            drawLineLow(img, x0, y0, x1, y1, c);\n        else\n            drawLineHigh(img, x0, y0, x1, y1, c);\n    }\n}\n\n//%\nvoid _drawLine(Bitmap_ img, int xy, int wh, int c) {\n    drawLine(img, XX(xy), YY(xy), XX(wh), YY(wh), c);\n}\n\nvoid blitRow(Bitmap_ img, int x, int y, Bitmap_ from, int fromX, int fromH) {\n    if (!img->inRange(x, 0) || !img->inRange(fromX, 0) || fromH <= 0)\n        return;\n\n    if (img->bpp() != 4 || from->bpp() != 4)\n        return;\n\n    int fy = 0;\n    int stepFY = (from->width() << 16) / fromH;\n    int endY = y + fromH;\n    if (endY > img->height())\n        endY = img->height();\n    if (y < 0) {\n        fy += -y * stepFY;\n        y = 0;\n    }\n\n    auto dp = img->pix(x, y);\n    auto sp = from->pix(fromX, 0);\n\n    while (y < endY) {\n        int p = fy >> 16, c;\n        if (p & 1)\n            c = sp[p >> 1] >> 4;\n        else\n            c = sp[p >> 1] & 0xf;\n        if (y & 1) {\n            *dp = (*dp & 0x0f) | (c << 4);\n            dp++;\n        } else {\n            *dp = (*dp & 0xf0) | (c & 0xf);\n        }\n        y++;\n        fy += stepFY;\n    }\n}\n\n//%\nvoid _blitRow(Bitmap_ img, int xy, Bitmap_ from, int xh) {\n    blitRow(img, XX(xy), YY(xy), from, XX(xh), YY(xh));\n}\n\nbool blit(Bitmap_ dst, Bitmap_ src, pxt::RefCollection *args) {\n    int xDst = pxt::toInt(args->getAt(0));\n    int yDst = pxt::toInt(args->getAt(1));\n    int wDst = pxt::toInt(args->getAt(2));\n    int hDst = pxt::toInt(args->getAt(3));\n    int xSrc = pxt::toInt(args->getAt(4));\n    int ySrc = pxt::toInt(args->getAt(5));\n    int wSrc = pxt::toInt(args->getAt(6));\n    int hSrc = pxt::toInt(args->getAt(7));\n    bool transparent = pxt::toBoolQuick(args->getAt(8));\n    bool check = pxt::toBoolQuick(args->getAt(9));\n\n    int xSrcStep = (wSrc << 16) / wDst;\n    int ySrcStep = (hSrc << 16) / hDst;\n\n    int xDstClip = abs(min(0, xDst));\n    int yDstClip = abs(min(0, yDst));\n    int xDstStart = xDst + xDstClip;\n    int yDstStart = yDst + yDstClip;\n    int xDstEnd = min(dst->width(), xDst + wDst);\n    int yDstEnd = min(dst->height(), yDst + hDst);\n\n    int xSrcStart = max(0, (xSrc << 16) + xDstClip * xSrcStep);\n    int ySrcStart = max(0, (ySrc << 16) + yDstClip * ySrcStep);\n    int xSrcEnd = min(src->width(), xSrc + wSrc) << 16;\n    int ySrcEnd = min(src->height(), ySrc + hSrc) << 16;\n\n    if (!check)\n        dst->makeWritable();\n\n    for (int yDstCur = yDstStart, ySrcCur = ySrcStart; yDstCur < yDstEnd && ySrcCur < ySrcEnd; ++yDstCur, ySrcCur += ySrcStep) {\n        int ySrcCurI = ySrcCur >> 16;\n        for (int xDstCur = xDstStart, xSrcCur = xSrcStart; xDstCur < xDstEnd && xSrcCur < xSrcEnd; ++xDstCur, xSrcCur += xSrcStep) {\n            int xSrcCurI = xSrcCur >> 16;\n            int cSrc = getCore(src, xSrcCurI, ySrcCurI);\n            if (check && cSrc) {\n                int cDst = getCore(dst, xDstCur, yDstCur);\n                if (cDst) {\n                    return true;\n                }\n                continue;\n            }\n            if (!transparent || cSrc) {\n                setCore(dst, xDstCur, yDstCur, cSrc);\n            }\n        }\n    }\n    return false;\n}\n\n//%\nbool _blit(Bitmap_ img, Bitmap_ src, pxt::RefCollection *args) {\n    return blit(img, src, args);\n}\n\nvoid fillCircle(Bitmap_ img, int cx, int cy, int r, int c) {\n    int x = r - 1;\n    int y = 0;\n    int dx = 1;\n    int dy = 1;\n    int err = dx - (r << 1);\n\n    while (x >= y) {\n        fillRect(img, cx + x, cy - y, 1, 1 + (y << 1), c);\n        fillRect(img, cx + y, cy - x, 1, 1 + (x << 1), c);\n        fillRect(img, cx - x, cy - y, 1, 1 + (y << 1), c);\n        fillRect(img, cx - y, cy - x, 1, 1 + (x << 1), c);\n        if (err <= 0) {\n            ++y;\n            err += dy;\n            dy += 2;\n        } else {\n            --x;\n            dx += 2;\n            err += dx - (r << 1);\n        }\n    }\n}\n\n//%\nvoid _fillCircle(Bitmap_ img, int cxy, int r, int c) {\n    fillCircle(img, XX(cxy), YY(cxy), r, c);\n}\n\ntypedef struct\n{\n    int x, y;\n    int x0, y0;\n    int x1, y1;\n    int W,H;\n    int dx, dy;\n    int yi, xi;\n    int D;\n    int nextFuncIndex;\n} LineGenState; // For keeping track of the state when generating Y values for a line, even when moving to the next X.\n\ntypedef struct\n{\n    int min;\n    int max;\n} ValueRange;\n\nvoid nextYRange_Low(int x, LineGenState *line, ValueRange *yRange) {\n    while (line->x == x && line->x <= line->x1 && line->x < line->W) {\n        if (0 <= line->x) {\n            if (line->y < yRange->min) yRange->min = line->y;\n            if (line->y > yRange->max) yRange->max = line->y;\n        }\n        if (line->D > 0) {\n            line->y += line->yi;\n            line->D -= line->dx;\n        }\n        line->D += line->dy;\n        ++line->x;\n    }\n}\n\nvoid nextYRange_HighUp(int x, LineGenState *line, ValueRange *yRange) {\n    while (line->x == x && line->y >= line->y1 && line->x < line->W) {\n        if (0 <= line->x) {\n            if (line->y < yRange->min) yRange->min = line->y;\n            if (line->y > yRange->max) yRange->max = line->y;\n        }\n        if (line->D > 0) {\n            line->x += line->xi;\n            line->D += line->dy;\n        }\n        line->D += line->dx;\n        --line->y;\n    }\n}\n// This function is similar to the sub-function drawLineHigh for drawLine. However, it yields back after calculating all Y values of a given X. When the function is called again, it continues from the state where it yielded back previously.\nvoid nextYRange_HighDown(int x, LineGenState *line, ValueRange *yRange) {\n    while (line->x == x && line->y <= line->y1 && line->x < line->W) {\n        if (0 <= line->x) {\n            if (line->y < yRange->min) yRange->min = line->y;\n            if (line->y > yRange->max) yRange->max = line->y;\n        }\n        if (line->D > 0) {\n            line->x += line->xi;\n            line->D -= line->dy;\n        }\n        line->D += line->dx;\n        ++line->y;\n    }\n}\n\nLineGenState initYRangeGenerator(int16_t X0, int16_t Y0, int16_t X1, int16_t Y1) {\n    LineGenState line;\n\n    line.x0 = X0, line.y0 = Y0, line.x1 = X1, line.y1 = Y1;\n\n    line.dx = line.x1 - line.x0;\n    line.dy = line.y1 - line.y0;\n    line.y = line.y0;\n    line.x = line.x0;\n\n    if ((line.dy < 0 ? -line.dy : line.dy) < line.dx) {\n        line.yi = 1;\n        if (line.dy < 0) {\n            line.yi = -1;\n            line.dy = -line.dy;\n        }\n        line.D = 2 * line.dy - line.dx;\n        line.dx <<= 1;\n        line.dy <<= 1;\n\n        line.nextFuncIndex = 0;\n        return line;\n    } else {\n        line.xi = 1;\n        // if (dx < 0) {//should not hit\n        //     PANIC();\n        // }\n        if (line.dy < 0) {\n            line.D = 2 * line.dx + line.dy;\n            line.dx <<= 1;\n            line.dy <<= 1;\n\n            line.nextFuncIndex = 1;\n            return line;\n        } else {\n            line.D = 2 * line.dx - line.dy;\n            line.dx <<= 1;\n            line.dy <<= 1;\n\n            line.nextFuncIndex = 2;\n            return line;\n        }\n    }\n}\n\n// core of draw vertical line for repeatly calling, eg.: fillTriangle() or fillPolygon4()\n// value range/safety check not included\n// prepare \"img->makeWritable();\" and \"uint8_t f = img->fillMask(c);\" outside required.\n// bpp=4 support only right now\nvoid drawVLineCore(Bitmap_ img, int x, int y, int h, uint8_t f) {\n    uint8_t *p = img->pix(x, y);\n    auto ptr = p;\n    unsigned mask = 0x0f;\n    if (y & 1)\n        mask <<= 4;\n    for (int i = 0; i < h; ++i) {\n        if (mask == 0xf00) {\n            if (h - i >= 2) {\n                *++ptr = f;\n                i++;\n                continue;\n            } else {\n                mask = 0x0f;\n                ptr++;\n            }\n        }\n        *ptr = (*ptr & ~mask) | (f & mask);\n        mask <<= 4;\n    }\n}\n\nvoid drawVLine(Bitmap_ img, int x, int y, int h, int c) {\n    int H = height(img);\n    uint8_t f = img->fillMask(c);\n    if (x < 0 || x >= width(img) || y >= H || y + h - 1 < 0)\n        return;\n    if (y < 0){\n        h += y;\n        y = 0;\n    }\n    if (y + h > H)\n        h = H - y;\n    drawVLineCore(img, x, y, h, f);\n}\n\nvoid fillTriangle(Bitmap_ img, int x0, int y0, int x1, int y1, int x2, int y2, int c) {\n    if (x1 < x0) {\n        pxt::swap(x0, x1);\n        pxt::swap(y0, y1);\n    }\n    if (x2 < x1) {\n        pxt::swap(x1, x2);\n        pxt::swap(y1, y2);\n    }\n    if (x1 < x0) {\n        pxt::swap(x0, x1);\n        pxt::swap(y0, y1);\n    }\n\n    LineGenState lines[] = {\n        initYRangeGenerator(x0, y0, x2, y2),\n        initYRangeGenerator(x0, y0, x1, y1),\n        initYRangeGenerator(x1, y1, x2, y2)\n    };\n\n    int W = width(img), H = height(img);\n    lines[0].W = lines[1].W = lines[2].W = W;\n    lines[0].H = lines[1].H = lines[2].H = H;\n\n    // We have 3 different sub-functions to generate Ys of edges, each particular edge maps to one of them.\n    // Use function pointers to avoid judging which function to call at every X.\n    typedef void (*FP_NEXT)(int x, LineGenState *line, ValueRange *yRange);\n    FP_NEXT nextFuncList[] = { nextYRange_Low, nextYRange_HighUp, nextYRange_HighDown };\n    FP_NEXT fpNext0 = nextFuncList[lines[0].nextFuncIndex];\n    FP_NEXT fpNext1 = nextFuncList[lines[1].nextFuncIndex];\n    FP_NEXT fpNext2 = nextFuncList[lines[2].nextFuncIndex];\n\n    ValueRange yRange = {H, -1};\n    img->makeWritable();\n    uint8_t f = img->fillMask(c);\n\n    for (int x = lines[1].x0; x <= min(x1, W - 1); x++) {\n        yRange.min = H;\n        yRange.max = -1;\n        fpNext0(x, &lines[0], &yRange);\n        fpNext1(x, &lines[1], &yRange);\n\n        if (x < 0 || yRange.min >= H || yRange.max < 0)\n            continue;\n        if (yRange.min < 0)\n            yRange.min = 0;\n        if (yRange.max >= H)\n            yRange.max = H - 1;\n        drawVLineCore(img, x, yRange.min, yRange.max - yRange.min + 1, f);\n    }\n\n    fpNext2(lines[2].x0, &lines[2], &yRange);\n\n    for (int x = lines[2].x0 + 1; x <= min(x2, W - 1); x++) {\n        yRange.min = H;\n        yRange.max = -1;\n        fpNext0(x, &lines[0], &yRange);\n        fpNext2(x, &lines[2], &yRange);\n\n        if (x < 0 || yRange.min >= H || yRange.max < 0)\n            continue;\n        if (yRange.min < 0)\n            yRange.min = 0;\n        if (yRange.max >= H)\n            yRange.max = H - 1;\n        drawVLineCore(img, x, yRange.min, yRange.max - yRange.min + 1, f);\n    }\n}\n\nvoid fillPolygon4(Bitmap_ img, int x0, int y0, int x1, int y1, int x2, int y2, int x3, int y3, int c) {\n    LineGenState lines[] = {\n        (x0 < x1) ? initYRangeGenerator(x0, y0, x1, y1) : initYRangeGenerator(x1, y1, x0, y0),\n        (x1 < x2) ? initYRangeGenerator(x1, y1, x2, y2) : initYRangeGenerator(x2, y2, x1, y1),\n        (x2 < x3) ? initYRangeGenerator(x2, y2, x3, y3) : initYRangeGenerator(x3, y3, x2, y2),\n        (x0 < x3) ? initYRangeGenerator(x0, y0, x3, y3) : initYRangeGenerator(x3, y3, x0, y0)};\n\n    int W = width(img), H = height(img);\n    lines[0].W = lines[1].W = lines[2].W = lines[3].W = W;\n    lines[0].H = lines[1].H = lines[2].H = lines[3].H = H;\n\n    int minX = min(min(x0, x1), min(x2, x3));\n    int maxX = min(max(max(x0, x1), max(x2, x3)), W - 1);\n\n    typedef void (*FP_NEXT)(int x, LineGenState *line, ValueRange *yRange);\n    FP_NEXT nextFuncList[] = { nextYRange_Low, nextYRange_HighUp, nextYRange_HighDown };\n    FP_NEXT fpNext0 = nextFuncList[lines[0].nextFuncIndex];\n    FP_NEXT fpNext1 = nextFuncList[lines[1].nextFuncIndex];\n    FP_NEXT fpNext2 = nextFuncList[lines[2].nextFuncIndex];\n    FP_NEXT fpNext3 = nextFuncList[lines[3].nextFuncIndex];\n\n    ValueRange yRange = { H, -1 };\n    img->makeWritable();\n    uint8_t f = img->fillMask(c);\n\n    for (int x = minX; x <= maxX; x++) {\n        yRange.min = H;\n        yRange.max = -1;\n        fpNext0(x, &lines[0], &yRange);\n        fpNext1(x, &lines[1], &yRange);\n        fpNext2(x, &lines[2], &yRange);\n        fpNext3(x, &lines[3], &yRange);\n\n        if (x < 0 || yRange.min >= H || yRange.max < 0)\n            continue;\n        if (yRange.min < 0)\n            yRange.min = 0;\n        if (yRange.max >= H)\n            yRange.max = H - 1;\n        drawVLineCore(img, x, yRange.min, yRange.max - yRange.min + 1, f);\n    }\n}\n\n//%\nvoid _fillTriangle(Bitmap_ img, pxt::RefCollection *args) {\n    fillTriangle(\n        img,\n        pxt::toInt(args->getAt(0)),\n        pxt::toInt(args->getAt(1)),\n        pxt::toInt(args->getAt(2)),\n        pxt::toInt(args->getAt(3)),\n        pxt::toInt(args->getAt(4)),\n        pxt::toInt(args->getAt(5)),\n        pxt::toInt(args->getAt(6))\n    );\n}\n\n// This polygon fill is similar to fillTriangle(): Scan minY and maxY of all edges at each X, and draw a vertical line between (x,minY)~(x,maxY).\n// The main difference is that it sorts the endpoints of each edge, x0 < x1, to draw from left to right, but doesn't sort the edges as it's too time consuming.\n// Instead, just call next(), which returns immediately if the x is not in range of the edge in horizon.\n// NOTE: Unlike triangles, edges of a polygon can cross a vertical line at a given X multi time. This algorithm can fill correctly only if edges meet this condition: Any vertical line(x) cross edges at most 2 times.\n// Fortunately, no matter what perspective transform is applied, a rectangle/trapezoid will still meet this condition.\n// Ref: https://forum.makecode.com/t/new-3d-engine-help-filling-4-sided-polygons/18641/9\n//%\nvoid _fillPolygon4(Bitmap_ img, pxt::RefCollection *args) {\n    fillPolygon4(\n        img,\n        pxt::toInt(args->getAt(0)),\n        pxt::toInt(args->getAt(1)),\n        pxt::toInt(args->getAt(2)),\n        pxt::toInt(args->getAt(3)),\n        pxt::toInt(args->getAt(4)),\n        pxt::toInt(args->getAt(5)),\n        pxt::toInt(args->getAt(6)),\n        pxt::toInt(args->getAt(7)),\n        pxt::toInt(args->getAt(8))\n    );\n}\n\n} // namespace BitmapMethods\n\nnamespace bitmaps {\n/**\n * Create new bitmap with given content\n */\n//%\nBitmap_ ofBuffer(Buffer buf) {\n    return BitmapMethods::convertAndWrap(buf);\n}\n}\n\nnamespace bitmaps {\n/**\n * Create new empty (transparent) bitmap\n */\n//%\nBitmap_ create(int width, int height) {\n    Bitmap_ r = mkImage(width, height, IMAGE_BITS);\n    if (r)\n        memset(r->pix(), 0, r->pixLength());\n    else\n        target_panic(PANIC_INVALID_IMAGE);\n    return r;\n}\n\n/**\n * Double the size of an icon\n */\n//%\nBuffer doubledIcon(Buffer icon) {\n    if (!isValidImage(icon))\n        return NULL;\n\n    auto r = NEW_GC(RefImage, icon);\n    registerGCObj(r);\n    auto t = BitmapMethods::doubled(r);\n    unregisterGCObj(r);\n    return t->buffer;\n}\n\n} // namespace bitmaps\n\n// This is  6.5x faster than standard on word-aligned copy\n// probably should move to codal\n\n#ifndef __linux__\nextern \"C\" void *memcpy(void *dst, const void *src, size_t sz) {\n    void *dst0 = dst;\n    if (sz >= 4 && !((uintptr_t)dst & 3) && !((uintptr_t)src & 3)) {\n        size_t cnt = sz >> 2;\n        uint32_t *d = (uint32_t *)dst;\n        const uint32_t *s = (const uint32_t *)src;\n        while (cnt--) {\n            *d++ = *s++;\n        }\n        sz &= 3;\n        dst = d;\n        src = s;\n    }\n\n    // see comment in memset() below (have not seen optimization here, but better safe than sorry)\n    volatile uint8_t *dd = (uint8_t *)dst;\n    volatile uint8_t *ss = (uint8_t *)src;\n\n    while (sz--) {\n        *dd++ = *ss++;\n    }\n\n    return dst0;\n}\n\nextern \"C\" void *memset(void *dst, int v, size_t sz) {\n    void *dst0 = dst;\n    if (sz >= 4 && !((uintptr_t)dst & 3)) {\n        size_t cnt = sz >> 2;\n        uint32_t vv = 0x01010101 * v;\n        uint32_t *d = (uint32_t *)dst;\n        while (cnt--) {\n            *d++ = vv;\n        }\n        sz &= 3;\n        dst = d;\n    }\n\n    // without volatile here, GCC may optimize the loop to memset() call which is obviously not great\n    volatile uint8_t *dd = (uint8_t *)dst;\n\n    while (sz--) {\n        *dd++ = v;\n    }\n\n    return dst0;\n}\n#endif\n","bitmap.ts":"type color = number\n\nnamespace bitmaps {\n    export function repeatY(count: number, image: Bitmap) {\n        let arr = [image]\n        while (--count > 0)\n            arr.push(image)\n        return concatY(arr)\n    }\n\n    export function concatY(images: Bitmap[]) {\n        let w = 0\n        let h = 0\n        for (let img of images) {\n            w = Math.max(img.width, w)\n            h += img.height\n        }\n        let r = bitmaps.create(w, h)\n        let y = 0\n        for (let img of images) {\n            let x = (w - img.width) >> 1\n            r.drawBitmap(img, x, y)\n            y += img.height\n        }\n        return r\n    }\n}\n\n\n//% snippet='bmp` `'\n//% pySnippet='bmp(\"\"\" \"\"\")'\ninterface Bitmap {\n    /**\n     * Draw an icon (monochromatic image) using given color\n     */\n    //% helper=imageDrawIcon\n    drawIcon(icon: Buffer, x: number, y: number, c: color): void;\n\n    /**\n     * Fill a rectangle\n     */\n    //% helper=imageFillRect\n    fillRect(x: number, y: number, w: number, h: number, c: color): void;\n\n    /**\n     * Draw a line\n     */\n    //% helper=imageDrawLine\n    drawLine(x0: number, y0: number, x1: number, y1: number, c: color): void;\n\n    /**\n     * Draw an empty rectangle\n     */\n    //% helper=imageDrawRect\n    drawRect(x: number, y: number, w: number, h: number, c: color): void;\n\n    /**\n     * Draw a circle\n     */\n    //% helper=imageDrawCircle\n    drawCircle(cx: number, cy: number, r: number, c: color): void;\n\n    /**\n     * Fills a circle\n     */\n    //% helper=imageFillCircle\n    fillCircle(cx: number, cy: number, r: number, c: color): void;\n\n    /**\n     * Fills a triangle\n     */\n    //% helper=imageFillTriangle\n    fillTriangle(x0: number, y0: number, x1: number, y1: number, x2: number, y2: number, col: number): void;\n\n    /**\n     * Fills a 4-side-polygon\n     */\n    //% helper=imageFillPolygon4\n    fillPolygon4(x0: number, y0: number, x1: number, y1: number, x2: number, y2: number, x3: number, y3: number, col: number): void;\n\n    /**\n     * Returns an image rotated by -90, 0, 90, 180, 270 deg clockwise\n     */\n    //% helper=imageRotated\n    rotated(deg: number): Bitmap;\n\n    /**\n     * Scale and copy a row of pixels from a texture.\n     */\n    //% helper=imageBlitRow\n    blitRow(dstX: number, dstY: number, from: Bitmap, fromX: number, fromH: number): void;\n\n    /**\n     * Copy an image from a source rectangle to a destination rectangle, stretching or\n     * compressing to fit the dimensions of the destination rectangle, if necessary.\n     */\n    //% helper=imageBlit\n    blit(xDst: number, yDst: number, wDst: number, hDst: number, src: Bitmap, xSrc: number, ySrc: number, wSrc: number, hSrc: number, transparent: boolean, check: boolean): boolean;\n}\n\nnamespace helpers {\n    //% shim=BitmapMethods::_drawLine\n    function _drawLine(img: Bitmap, xy: number, wh: number, c: color): void { }\n\n    //% shim=BitmapMethods::_fillRect\n    function _fillRect(img: Bitmap, xy: number, wh: number, c: color): void { }\n\n    //% shim=BitmapMethods::_mapRect\n    function _mapRect(img: Bitmap, xy: number, wh: number, m: Buffer): void { }\n\n    //% shim=BitmapMethods::_drawIcon\n    function _drawIcon(img: Bitmap, icon: Buffer, xy: number, c: color): void { }\n\n    //% shim=BitmapMethods::_fillCircle\n    declare function _fillCircle(img: Bitmap, cxy: number, r: number, c: color): void;\n\n    //% shim=BitmapMethods::_blitRow\n    declare function _blitRow(img: Bitmap, xy: number, from: Bitmap, xh: number): void;\n\n    //% shim=BitmapMethods::_blit\n    declare function _blit(img: Bitmap, src: Bitmap, args: number[]): boolean;\n\n    //% shim=BitmapMethods::_fillTriangle\n    declare function _fillTriangle(img: Bitmap, args: number[]): void;\n\n    //% shim=BitmapMethods::_fillPolygon4\n    declare function _fillPolygon4(img: Bitmap, args: number[]): void;\n\n    function pack(x: number, y: number) {\n        return (Math.clamp(-30000, 30000, x | 0) & 0xffff) | (Math.clamp(-30000, 30000, y | 0) << 16)\n    }\n\n    let _blitArgs: number[];\n\n    export function imageBlit(img: Bitmap, xDst: number, yDst: number, wDst: number, hDst: number, src: Bitmap, xSrc: number, ySrc: number, wSrc: number, hSrc: number, transparent: boolean, check: boolean): boolean {\n        _blitArgs = _blitArgs || [];\n        _blitArgs[0] = xDst | 0;\n        _blitArgs[1] = yDst | 0;\n        _blitArgs[2] = wDst | 0;\n        _blitArgs[3] = hDst | 0;\n        _blitArgs[4] = xSrc | 0;\n        _blitArgs[5] = ySrc | 0;\n        _blitArgs[6] = wSrc | 0;\n        _blitArgs[7] = hSrc | 0;\n        _blitArgs[8] = transparent ? 1 : 0;\n        _blitArgs[9] = check ? 1 : 0;\n        return _blit(img, src, _blitArgs);\n    }\n\n    export function imageBlitRow(img: Bitmap, dstX: number, dstY: number, from: Bitmap, fromX: number, fromH: number): void {\n        _blitRow(img, pack(dstX, dstY), from, pack(fromX, fromH))\n    }\n\n    export function imageDrawIcon(img: Bitmap, icon: Buffer, x: number, y: number, c: color): void {\n        _drawIcon(img, icon, pack(x, y), c)\n    }\n    export function imageFillRect(img: Bitmap, x: number, y: number, w: number, h: number, c: color): void {\n        _fillRect(img, pack(x, y), pack(w, h), c)\n    }\n    export function imageMapRect(img: Bitmap, x: number, y: number, w: number, h: number, m: Buffer): void {\n        _mapRect(img, pack(x, y), pack(w, h), m)\n    }\n    export function imageDrawLine(img: Bitmap, x: number, y: number, w: number, h: number, c: color): void {\n        _drawLine(img, pack(x, y), pack(w, h), c)\n    }\n    export function imageDrawRect(img: Bitmap, x: number, y: number, w: number, h: number, c: color): void {\n        if (w == 0 || h == 0) return\n        w--\n        h--\n        imageDrawLine(img, x, y, x + w, y, c)\n        imageDrawLine(img, x, y, x, y + h, c)\n        imageDrawLine(img, x + w, y + h, x + w, y, c)\n        imageDrawLine(img, x + w, y + h, x, y + h, c)\n    }\n\n    export function imageDrawCircle(img: Bitmap, cx: number, cy: number, r: number, col: number) {\n        cx = cx | 0;\n        cy = cy | 0;\n        r = r | 0;\n        // short cuts\n        if (r < 0)\n            return;\n\n        // Bresenham's algorithm\n        let x = 0\n        let y = r\n        let d = 3 - 2 * r\n\n        while (y >= x) {\n            img.setPixel(cx + x, cy + y, col)\n            img.setPixel(cx - x, cy + y, col)\n            img.setPixel(cx + x, cy - y, col)\n            img.setPixel(cx - x, cy - y, col)\n            img.setPixel(cx + y, cy + x, col)\n            img.setPixel(cx - y, cy + x, col)\n            img.setPixel(cx + y, cy - x, col)\n            img.setPixel(cx - y, cy - x, col)\n            x++\n            if (d > 0) {\n                y--\n                d += 4 * (x - y) + 10\n            } else {\n                d += 4 * x + 6\n            }\n        }\n    }\n\n    export function imageFillCircle(img: Bitmap, cx: number, cy: number, r: number, col: number) {\n        _fillCircle(img, pack(cx, cy), r, col);\n    }\n\n    export function imageFillTriangle(img: Bitmap, x0: number, y0: number, x1: number, y1: number, x2: number, y2: number, col: number) {\n        _blitArgs = _blitArgs || [];\n        _blitArgs[0] = x0;\n        _blitArgs[1] = y0;\n        _blitArgs[2] = x1;\n        _blitArgs[3] = y1;\n        _blitArgs[4] = x2;\n        _blitArgs[5] = y2;\n        _blitArgs[6] = col;\n        _fillTriangle(img, _blitArgs);\n    }\n\n    export function imageFillPolygon4(img: Bitmap, x0: number, y0: number, x1: number, y1: number, x2: number, y2: number, x3: number, y3: number, col: number) {\n        _blitArgs = _blitArgs || [];\n        _blitArgs[0] = x0;\n        _blitArgs[1] = y0;\n        _blitArgs[2] = x1;\n        _blitArgs[3] = y1;\n        _blitArgs[4] = x2;\n        _blitArgs[5] = y2;\n        _blitArgs[6] = x3;\n        _blitArgs[7] = y3;\n        _blitArgs[8] = col;\n        _fillPolygon4(img, _blitArgs);\n    }\n\n    /**\n     * Returns an image rotated by 90, 180, 270 deg clockwise\n     */\n    export function imageRotated(img: Bitmap, deg: number) {\n        if (deg == -90 || deg == 270) {\n            let r = img.transposed();\n            r.flipY();\n            return r;\n        } else if (deg == 180 || deg == -180) {\n            let r = img.clone();\n            r.flipX();\n            r.flipY();\n            return r;\n        } else if (deg == 90) {\n            let r = img.transposed();\n            r.flipX();\n            return r;\n        } else {\n            return null;\n        }\n    }\n}\n","pxt.json":"{\n    \"name\": \"bitmap\",\n    \"description\": \"Support for bitmaps (micro:bit V2 only).\",\n    \"dependencies\": {\n        \"core\": \"*\"\n    },\n    \"files\": [\n        \"bitmap.cpp\",\n        \"bitmap.ts\",\n        \"shims.d.ts\"\n    ],\n    \"public\": true,\n    \"targetVersions\": {\n        \"target\": \"7.1.42\",\n        \"pxt\": \"11.4.28\"\n    },\n    \"preferredEditor\": \"tsprj\",\n    \"hidden\": true,\n    \"searchOnly\": true,\n    \"disablesVariants\": [\n        \"mbdal\"\n    ]\n}\n","shims.d.ts":"// Auto-generated. Do not edit.\n\n\ndeclare interface Bitmap {\n    /**\n     * Get underlying buffer\n     */\n    //% property shim=BitmapMethods::__buffer\n    __buffer: Buffer;\n\n    /**\n     * Get the width of the bitmap\n     */\n    //% property shim=BitmapMethods::width\n    width: int32;\n\n    /**\n     * Get the height of the bitmap\n     */\n    //% property shim=BitmapMethods::height\n    height: int32;\n\n    /**\n     * True if the bitmap is monochromatic (black and white)\n     */\n    //% property shim=BitmapMethods::isMono\n    isMono: boolean;\n\n    /**\n     * Sets all pixels in the current bitmap from the other bitmap, which has to be of the same size and\n     * bpp.\n     */\n    //% shim=BitmapMethods::copyFrom\n    copyFrom(from: Bitmap): void;\n\n    /**\n     * Set pixel color\n     */\n    //% shim=BitmapMethods::setPixel\n    setPixel(x: int32, y: int32, c: int32): void;\n\n    /**\n     * Get a pixel color\n     */\n    //% shim=BitmapMethods::getPixel\n    getPixel(x: int32, y: int32): int32;\n\n    /**\n     * Fill entire bitmap with a given color\n     */\n    //% shim=BitmapMethods::fill\n    fill(c: int32): void;\n\n    /**\n     * Copy row(s) of pixel from bitmap to buffer (8 bit per pixel).\n     */\n    //% shim=BitmapMethods::getRows\n    getRows(x: int32, dst: Buffer): void;\n\n    /**\n     * Copy row(s) of pixel from buffer to bitmap.\n     */\n    //% shim=BitmapMethods::setRows\n    setRows(x: int32, src: Buffer): void;\n\n    /**\n     * Return a copy of the current bitmap\n     */\n    //% shim=BitmapMethods::clone\n    clone(): Bitmap;\n\n    /**\n     * Flips (mirrors) pixels horizontally in the current bitmap\n     */\n    //% shim=BitmapMethods::flipX\n    flipX(): void;\n\n    /**\n     * Flips (mirrors) pixels vertically in the current bitmap\n     */\n    //% shim=BitmapMethods::flipY\n    flipY(): void;\n\n    /**\n     * Returns a transposed bitmap (with X/Y swapped)\n     */\n    //% shim=BitmapMethods::transposed\n    transposed(): Bitmap;\n\n    /**\n     * Every pixel in bitmap is moved by (dx,dy)\n     */\n    //% shim=BitmapMethods::scroll\n    scroll(dx: int32, dy: int32): void;\n\n    /**\n     * Stretches the bitmap horizontally by 100%\n     */\n    //% shim=BitmapMethods::doubledX\n    doubledX(): Bitmap;\n\n    /**\n     * Stretches the bitmap vertically by 100%\n     */\n    //% shim=BitmapMethods::doubledY\n    doubledY(): Bitmap;\n\n    /**\n     * Replaces one color in an bitmap with another\n     */\n    //% shim=BitmapMethods::replace\n    replace(from: int32, to: int32): void;\n\n    /**\n     * Stretches the bitmap in both directions by 100%\n     */\n    //% shim=BitmapMethods::doubled\n    doubled(): Bitmap;\n\n    /**\n     * Draw given bitmap on the current bitmap\n     */\n    //% shim=BitmapMethods::drawBitmap\n    drawBitmap(from: Bitmap, x: int32, y: int32): void;\n\n    /**\n     * Draw given bitmap with transparent background on the current bitmap\n     */\n    //% shim=BitmapMethods::drawTransparentBitmap\n    drawTransparentBitmap(from: Bitmap, x: int32, y: int32): void;\n\n    /**\n     * Check if the current bitmap \"collides\" with another\n     */\n    //% shim=BitmapMethods::overlapsWith\n    overlapsWith(other: Bitmap, x: int32, y: int32): boolean;\n}\ndeclare namespace bitmaps {\n\n    /**\n     * Create new bitmap with given content\n     */\n    //% shim=bitmaps::ofBuffer\n    function ofBuffer(buf: Buffer): Bitmap;\n\n    /**\n     * Create new empty (transparent) bitmap\n     */\n    //% shim=bitmaps::create\n    function create(width: int32, height: int32): Bitmap;\n\n    /**\n     * Double the size of an icon\n     */\n    //% shim=bitmaps::doubledIcon\n    function doubledIcon(icon: Buffer): Buffer;\n}\n\n// Auto-generated. Do not edit. Really.\n"},"fonts":{"font12.jres":"{\n    \"bitmaps.font12\": {\n        \"mimeType\": \"font/x-mkcd-b26\",\n        \"data\": \"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9A9UANwHAAD4AQAI/AcAADhSIAGqCOoIrAS4Aq4BqAi4CKwG6gGqACABOVJQBFQDVAjIB0wAUgFSBgAA/AkACP4PAAA6UgAEdAYUAf4PFAH0AgAA/AEACAAI/gcAADtSAAAkCbQErwJkAhQDxAQAAPwJAAj+DwAAPVIgAJAMiAakBaYEiAawCAAA+AkACP4HAABCUkQIVARUAzYANACsDyQAAAD8CQAI/wcAAENSAAToBKoCrAH4D64AuAcAAPwJAAj+BwAAR1IACP4FKgUqASoB/g0AAPwBAAgACP4HAABKUgAA9g9QAV4JUAn2BwAA/AEACAAI/gcAAE1SAADoD6oCrAqoCugHCADoAw4I6AcIAAAATlIAAFIEUgNMAOQPSgJqBAAA/AkACP4HAABRUhAAWAiEBRIE0wQEB8gCAAL8CAAI/gcAAFRSAAG+BOoCqg2qA6oIvgcAAPwJAAj+BwAAVlIkAKwPrASmBKQEvASsBwAA/AkACP4PAABbUgAA/A8MA+QDFAn8BwAA+AEACPwHAAAAAF1SAADAANgKVgrUB3QAzAYAAPgJAAj+BwAAY1IQCPAEvAbyAbQC5AwAAPwBAAgACP4HAABkUgAAJAisB5YCrAKkDyQAAAD8AQAI/g8AAGVSoAIqCioJ6g8qAb4CoAYAAPwJAAj+BwAAZ1LABz4AqgeqBPoEqgSuBwAA/AAACP8HAABpUogIbARsAgwB/A8MAWoCKAQAAPwJAAj+B2pSAAV8BTwFPgW8A/wBBAF0BQYFdAUEAwAAb1ICAN4PVgXWB1YFVgXeDwAA/AkACP4HAABwUgAArAT8AqwB/A+qAvoGAAD4AQAI/gcAAHJSjAC8D7QFtAX2BbQHtAeMBwAA/AEACP4HdVIQABAO0AP4BfQF5AXoBwAA+AEACPwHAAB/UgAIdgVwBXQD+g94A3ADdgUAAPgJAAj+B4NSSAT8B/wH/gf8B/wH/Af8BwAE+AEACPwHh1IADvgBGATYBn4DbA9sAggE8AEACPwPAACIUoAAfAj0CbQJtAX4A1QBXAn2CVwJVAcAAIlSAACcCcoLyQmwB84FQgUOBPgBAAj+BwAAjVIICOgErALqAEsIogbkBAAA/AEACP4HAACRUjgASAz0A4wClgK8AswPIAD8AQAI/gcAAJtSAAAQCBAEEAKQAX4AEAAQCBAIEAzwAwAAnVIABBQCZAHkABwJAASIA34ACAgICPgHAACeUgAAiAloBAgCiAF+CAgICAz4AwAA4AEAAJ9SBAIEAvwBBAkECRAEEAP+CBAIEAzwAwAAoFIICAgG/gEICAgI+AcAAPwPBAQEBPwPAAChUkAIUAlICSwFNgOkASQJNAlMCUQHQAAAAKNSKAioCKQIogSgA54AkAiICIIIhAcIAAAAqFIAACQE5AMkAqQCJAMACBAH/gAQCPAHAACpUgAE/gOSBJIC/gsABBAD8AgfCBAI8AcAAKpSAAhECVwJZgUkA1wBRAE0CSQJXAdEAAAAq1IAAEgHyAR+AkgCQAcQABAP/gAQCPAHAACxUgAO/AEUDPQDVAjUBwQAEAf8ABAI8AcAALJSAACkCKQElAesBKQEMAAQDv4BEAjwBwAAs1IACLQIlASWBJQD1ACUCJQIlgiUBzQAAAC0UgAIuAiKBIoEiALrAYgIiAiMCIoHOAAAALlSKAioBKgCDAGoAggIUAQQA/4IEAjwBwAAv1IAABQIVAl+BRQFwAM0AR4JBAk8B0AAIADBUgAAtASEBLQHhAS0DAQEEAP+CBAI8AcAAMNSAAA0AhQJXgeUATQJAAQQA/4IEAjwBwAAx1IACAIK+gqqBqoC+gKqAq4Kqgr6BgAAAADJUhAI+ASWA/QAnAfwCBgKmAl+CAgK+AkABMtSAAjuCSoEqgMqCO4LAAAQB/4AEAjwBwAA0lIAAOQCvgL0D74C5AgEBBAD/ggQCPAHAADVUgAAfAl8CfwHeg0IBBgCkAF+CBAI8AcAANhSgACCB/8FqgSqBP8FggwIAv8BCAT4AwAA2VIAACoDqgjqBzYA4AlIBy4BNAk0CSwHRAHdUgAM/gOSCP4HgAFqCTgHrgE4CW4JqgcAAd5SEgiSCKgErgSgAqIBpAioCKYIKAdyAAAA31IAAkQB/AV+A3wDfAF8BX4F/AN8AUQCAADiUgAArAmsCe4FrAWAA/gBGAkOCXgGgABgAORSAAj0CdYF9AfWBfQFAAwQA/4IEAjwBwAA51IAACAB7A+4B+gHqAeoDgAG/AEQCPAHAADyUgAB/g3+Af4B/g3+AQgLmAh+AAgB+AwAAPNSBAh9BW0B/wTsAvwCAAaIAX8ECAT4AwAA9VIADPwDzA/8AewD/AvMDwAM/gMQCPAHAAD4UgAB+g+7B4AHuwe6BwAM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JAAAAK1T+AcEAPQD/AJ8B3QFhAckBPwDJAEUAgAErlMABv4BAgT6AVoD+gECDPoDSgDKD0oAAACyUwAO/gECAOoP6gHqBeIH6gXqBeoJCg8CALNTAA74AQ4E+Ae4BroG/A8IAOgMLAPqBSgIu1NAAEgMSAZIBcgEfgRIBEgFSAZICEAAAAC/UwAAgACABP4GqgWqBKoEqgSqBP4GgASAAMFTIAGoCKgK7Aq6CqgKqgruCqgKqAggAQAAwlMgASgBqAhsCroKqAooCWoErASgACABAADDUwAAAAGwAKQJdgulChQKJgl2BKAEMAFAAchTAAAACAQIHARkBIQCBAGEAmQEHAQECAAIyVMACAQIPAREBJQCFAGUAkQEPAQEBAAIAADKUwAEBAaEAXwIJATEBAQDHAOQAnAEEAQAAMtTAAQIBAgDyAh+BKgEKAMoA6gEaAQICAAEzFMUCDQERALkARwKAAh8BIQDxAI8BAAIAADNUwAAAAz8AyQI5AgkBSQCJAakBWQIBAgAAM5TAAL4AQABAAH+DwAAFAjkBAQDxAQ8BAQI0VMABBACHAuQCPAIXgVQBlAF1ghQCBAIAADUUwACoAEgCP4PJACgCwQIfAaEAeQCHAwACNZTBAT8B5QElASUAvwPAABoCIgFCAPoBBgI11MAAHQIHATcBFQFXAJcAlIF2gQaBDAIAADYUwAIpAiUCIQJvAaGBIYEvAaECZQIJAgACNlTUAZYAVQI8g9UAFQDBAh8BIQDxAI8DAAA21MAAKwIoAb+AaQAAA78AXIMkgOSAnIMAATgUwAA6Ah2CFYPVg9GD1YPXg9WD3gIyAgAAOFTAACoANgHvwfaB/oHkAAMDPQChAF8BgAE4lMIAKoE7Af4B/wH6A/oAPwH7AXqB4gJgAjjUwAAAAD8DwQEBAQEBAQEBAQEBPwPAAAAAORTAAAIAIgPiASIBP4EiASIBIgEiA8IAAAA5VMAAGAAEADMByoCKAIoAugLCAgIDPgDAADmUwAAgAi8BKQEpAPkAKQApAikCLwIgAcAAOhTAAD8AwQB/AkACAQGhAF8BAQIBAz8AwAA6VMAAPwDBAEEAfwBAAD8DwQABAIEAvwBAADqUwAAAAh8BEQCRAFEAEQARAFEAnwEAAgAAOtTAAD8AwQBBAH8AQAA/AMAAQAB/g8AAAAA7FOAAEQARA8kCRQJ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ggCyAIoAAAB9VAAAEADQB1gCWALUAxIA1A9YAEgC0AEQAIZUAAD8AwQB/AEwAPgDlgSUBPQFBAX8BAACi1QAAPwDBAH8ARAACAAOAPgPKAEoASgBAACMVAAClAFUAPwHUgAAAPwHBAIEAgQC/AcAAI9UAAD8AwQB/AQAAtQBFAj0D4QAQAEgBgAEkFQAAPwDBAH8AWAA/A8CANAAEAkQCP4HEACSVAAIHAgUBNQDXABAAFwAVADUBxwIAAgABpVUAAD8AwQB/AEAAJAPkASQBP4EkASQDxAAllQAAPwHBAH8DAAC/gkIDPAD/A8EBPwPAACZVAAA/AMEAfwJAASQA34IEATyB5YIVAgQBJpUAAD8AwQB/AFQAEgCLgK1BDQFTAlEAEAAplQAAPwDBAH8AQAI7ASsAv4BrAKsBLwJAAinVAAA/AMEAfwBQAi8BJQDYAD4CQAI/gcAAKhUIAARAIoPoASsBKMEkgSOBJIEog8uAAAAqlQAAPwHBAL8AwAIrAcgAP4PIACoAyQMAACsVAAA/AMEAfwBAAgoCKgECgPMBQgEaAhACK9UAAD8AwQB/AEQAYgPVgllCXQJXAmED4AAsVQAAPwBBAH8AQAA+AeoAqwCqgKoAvgHAACyVAAA/AMEAfwJAAhOBEwC+AFMAk4ESggAALNUAAD8AwQB/AEACCQFtARvAiQClAVECAAAuFQADPgDCACoB6gCqAoIC/4ICAfKCCwIAAa9VAAA/AMEAfgA/g8CBCIF+gSiBQIE/g8AAMBUAAIEAXQBVA/UBFUE1gRUAVQCdAUEBQAIwVQAAMAPQAReBNIHEgDSD1IEXgRABMAPAADEVAAA/AMEAfwBAAiIBP4CiACIAP4CiAyACMZUAAD8AwQB/AEACCgJpASWBFQCTAHEAAAAx1QAAPwDBAH8AQAIJAkkCb4PJAkkCSAJAADIVAAA/AMEAfwBYAAwD6gEpgSoBDAPYABAAMlUEADUB1QCXgJUAtQJEAz+AhADkgRUCAAHzVQAAPwDBAH8AQAA+A8IAOgDLgHoCQgI+AfOVAAA/AMEAfwBAAgkCM4EBAMEBc4EJAgECNFUAAD8AwQB/AVABAQE/AcEBPwHBATkBAAA11QAAPwDBAH8AQAAfAECAZAPPgFIAUQBJADfVAAA/AMEAfwBAAT8BYIEEALOCAgI+AcAAOFUAAAACP8LrQatBq0CrQKtBq0G/wsACAAA5VQAAEQAfAdsBWwFbAVsB3wARAj8D0QAAADmVAAA/AMEAfwBAAj8D5IAEAz+A5AFVggABuhUAAD8AwQB/AEAAPYPUAFeAVAJUAn2BwAA6VT8AwQB/AEAAHwJVAlUCfwPVAlUCXwJAADqVAAA/AMEAfgMAgL+CZII/gf8DwIA/gMAAO1UgAieCJIIkgSeA8AAnAOUBNQE3AiACAAA7lQAAP4BggD+AIABagEqCb8PagEuASoBCQHyVAAAEgCyD78EigSgBJ4EiQSJBLkHCQAIAPpU/AMEAfwBAADoD6gCqAL+D6gCqgrsBwAA/FQAAPwBhAD8AAAAvAisCK4OrAGsAbwABAABVQAA/AcEA/wDAACoDqgKqgqqCqgKqA4IAAZVAAD8AwQB/AlACCgJngaIBPwGzAVYCEAIB1UAAAAP/gAiDuoKqgpqCqoKqgoqDSIBAAAJVQAA/AMEAfwBAAgoCS4F6gMoBS4JKAkAABBVAAb8AQQAXAdcBVwF/gVcBVwFfAcUAAAAFFUAAPwDBAH8AQAAqge6BK4EqgS6BKIHIAAgVQAA/AMEAfwBAAiUBJYC1AmUCJYMNAMAACRV/AMEAfwBAAj4BJQClgH0AZwClAT0BIAIJ1UAAPwDBAH8AQAE/AdUAjwA+A8EAPwDAAAsVQAA/AMEAfwBAAz4AygIPgdsAGwHTAgABC5VCAAIAHwPXgVcBVwFfgVcBVwFXA9EAAAAL1UAAPwDBAH8AQAA/A+qBKgE/geoBKgEAAAxVQAA/AMEAfwBAAD+B2oFagVqBWoF/gcAADdVAAD8AwQB/AEACPQH7ADmAmUKZAr0ByQAOFUAAPwDBAH8CAAGKACkBLIJNAr0ACQGCAg+VQAA/AMEAfwBAAjUChQK/A8UCtIKUAoQCENVAAD+AYIA/gAIAO4PqAKvAqoKqgrqDwAARFUAAPwDBAH8ASAElAJUCiwJxAdkAJQDAARGVQAAAAD0DxQAfAcWBTQFVAVcBxQA9A8AAEpVAAD8AwQB+AD+DzIAzAHkAxQB5Aj8BwQAT1UAAP4PKgCqB74CgAK+AqoDKggqCP4HAABTVcIAOgCqB6oEqgS6BJAEzgS0BDQHTACEAF9VAAb8AaoHqgKqAroDIAR+AogB6AIYBAAAYVUAAPwDBAH8AQAAKAH+DwAA/g8oASgBAABkVfwDBAH8AQAAfALUAtQCfgJUD1QCfAIAAGVVAAD8AwQB/AEQAEgHRAXyBVQFRAVIB1AAZlUAAPwDBAH8AQAM/gMICGAIiQkKDugJAABqVQAA/AMEAfwBgAj+B0AA+A+MBIoE+A8AAHBVAAD8AwQB+AmOCVIIfgVSAl4B0gFeAAAAeFX8AwQB/AEADKwDLAYsAf4PLAEsArwPCAB8VQAA/AMEAfwBAABsB6QApg+0AKQEpAMAAIBVAAD8BwQC/AMAAKQPtAlWCVQJpA6MAAAAglX8AwQB/AEAAPwA1A/UCPwJ1ALUB/wJAACDVQAA/AMEAfwA4A8UALQCngfUAhQI9AcAAIRVAAFEAVQPVgtUC/wLVAtUC9YL1A9EAQAAh1UAAPwDBAH8DGQCng/0AZQCYAj4CP4HAACJVQAA/AMEAfwBYAD4DwYAUAlUBdQDXAVQCYpVAAD8AwQB/AzwAwgHqAIIDX4CiAVqCAAGlFUAAPwDBAH8DAAC/Ak0CPQKtA+0CrwKAACYVfwDBAH8AQAAvA+wALAP/gCwD7AAvA8AAJpVAAD8AYQAfAjwBVgFNgOUAzwFUAXwCQABnFUAAQQBfA/cC1wLXgtcC1wL3At8DwQBAAGdVQAA/AMEAfwBAAC+BqoEqgWqCKoIvgcAAKdVAAD8AwQB/AEICPQLtAq2CrQK1AscCAAAqlUAAIQIvAisD7wIhAj+CYQCvASsCrwKhAirVQAA/AMEAfwJAAg+BTQDwAM8BQQJfAkAAKxVKAAsAJwP/ADcB9wF3AXcBfwHmgioDyAArlUAAAAE/gVaBVoF/g9QBV4FWgX6BQ4EAACyVQAA/gMCAf4BGAznApAAUAaOAAgI+AcAALNVAAD8AwQB/AEACNQLrAquCqwK1AsUCAAAtVX+AYIA/gAAAPAPkgSXBPIHkASXBPIHAgC2VQAAGAAKB3wFWAXeBVgFWAV8BQoHGAAAALdV/AMEAfwBAAjUC1QIVAZWAVQEVAjUCwAIu1UAAPwDBAH8ARgA2A+0AvIPlAEYCMgHEADFVQAA/AMEAfwBAAh8BVwFXgNeA9wFfAUACc5VAAD8AwQB/AEADP4AqgaqAP4EqgGCDwAA01UAAPwDBAH8AQAIUgV2A4YPlgNSBTAFAAjaVQAA/AMEAfwJAAT8ANQO1gDUBdwIwAcAANxVAAD8AwQB/AFAADQHfgfUB9wH1AfUBwAA4VX8AwQB/AEABMgCVAqiBxAAUgJ0CuQHCADjVQAA3A/UB9QP3A+EAVQC1AsECPwHAAAAAORV/AEEAfwBAATgB2wGeAbuB2gGaAbsDyAI5lUAAPwDBAH8AQAMVAH0CV4HFAGUBTAIAADoVQAA/AMEAfwAAA5EAJADzAKoC6gK6AcAAu9VAAD8AwQB+AA+AWICagRaBVoEQgF+AwAC/VUAAPwDBAH8BCQC/g9UAXQJEAbOAQgGOAgAVgAA/AMEAfwBAAD0DxQC9gVUBVwHFAj0BwFWAAD+AYIA/g74AYQE9AcUAIcEfAOFBnQCBlb8AwQB/AEACPQK1ArWBvQD1AbWCvQKAAAJVgAAgg6+Au4KrgqvBq4M7gquCr4Kgg4AAA5WAAD4AwgB8AUEBXwF/AN8A3wF/AV8BwQDF1YAAAwARg/WC/QL9gv0C/QL9gvFD5wAAAAbVgAA/AMEAfwI+AcEAfQPJgKEAfQPpAAEAx9WAAD8AwQB/ACAD34FUAWID/wHBAD8AwAAMVYAAPwBhAB8CAAH/A60AdwF/AfUAdwPAAAyVgAA/AMEAfwDfAKuD3wC/geSAP4PAAAAADRWAAD8AwQB/AEQBNgD7gL0B/AC7gLUBxAANlYAAPwDBAH4AAQN/gFUAf4N/AMkAOIPIgA5VgAA/gOCAf4BAAz6AVYJUw9WAfoBMgwAADtWAAD8AwQB/AEAAHwP3AteC1wL3At8DwQBP1b8AYQA/AAACF4FVgFSBf4JWgFSBV4AAA5BVgAA/AMEAfwAIA1UAdwHBAvcC1QJdAEADWJWAAD8AwQB+Al8CAwFZAN2ASQDRAV8CQAAaFYAAEACXA9UCdQJfA9gAEwP9Al0CVwPQAJpVgQIxAv8CvwLRAj8D0QI/AvsCvwLBAgAAGpWAAD8AwQB/AnABbwF9AOUD/QPvAPgBQAIdFYAAPwBhAD8BBAE9Af0AvYC9ALUBvQHEAiHVgAA/AMECfwH5As/COQPJA3kA/8PJACgA45WAAD8AwQB/AFACDwGvAa+A7wPvAPkBAAAo1YAAIgH7gWuBW4HWABuB24FrgVuBYgHAAC0VgAO4AG8BPQH9AfsD7gB1Al0BvwFYAgAALdWAAD8AwQB/AUADPwP7An+AfQH7AX8CQAAvFYAAPwDBAH8AQAA9A/yBfoMMgG5CLUHgADCVgAACAL+B/4H/gf+BvgA/gb+B/4HCAUAAclWAAD+AYIAfAH3BqUCBwP9D1cF9QdXBQAAylYABbQD/Av8B/wFngX8AfwD/AXcB5QHAADaVgAA/g8CBAIFggRCBDoEwgQCBQIE/g8AANtWAAD8DwQExAU8BAQEBAR8BIQEBAT8DwAA3lYAAP4PAgTyBJIEkgSSBPIEAgQCBP4PAADgVgAA/g8CBCIFIgWiBHoEogQiBQIE/g8AAOJWAAD+BwIEkgRSBFIFMgX6BRIEAgT+BwAA41YAAP4HAgQKBGoECgUKBfoECgQCBP4HAADkVv4PAgRSBJIEkgT6BZIGkgZSBgIE/g8AAO1WAAD+BwIEKgXqBCoE6gUqBSoFAgT+BwAA8FYAAP4PAgSiBWIE+gViBKIEIgUCBP4PAADxVgAA/A8EBEQFJAVXBZQEdAUUBQQE/A8AAPJWAAD+DwIEkgT6BZIEkgT6BZIEAgT+DwAA81YAAP4PAgZaB0IFygTCBDIFCgUCBP4PAAD0VgAA/g8CBKoEqgT6BaoEqgSKBQIE/g8AAPpWAAD+DwIEEgTSBVIFegVSBdIFAgT+DwAA/VYAAP4PAgQqBSoF+gUqBWoFKgUCBP4PAAD+VgAA/w8BBCkFLQUVBZUFrQYlBgEE/w8AAANXAAD8BwQE9AX0BPwE/AX0BPQE9AUEBPwHBlf+BwIG3gZWBlYFVgVWBF4GwgYCBP4HAAAIVwAA/gcCBD4E/gU6BroGegY6BQIE/gcAAAtXAAD+BwIE6gWqBUoEegWKBW4GAgT+BwAADVcAAP4HAgT+BX4FfgX+BX4FegUCBP4HAAAPVwAA/gcCBGoE6gX6BuoG+gZqBAIE/gcAABJXAAD+DwIM6g1qC3oLagtqC+oLAgz+DwAAE1cAAP4PAgjCC/oL6gvqC+oL+gsCCP4PAAAWVwAA/gcCBP4H9gf2B/YHfgbiBwIE/gcAABhX/g8CBP4E/gX+BP4E/gb+B/4EAgT+DwAAH1cABCAEIAQgBCAE/gcgBCAEIAQgBAAEAAAjV0AIRAhMCSwJNAmkDzQJNAlMCUQIQAgAACdXAAAADPwDBAhECEQI9A9ECEQIRAgECAAAKFcIAYgAyA84AI4IiAiICOgPiAiICIgIAAAtVwAIJAkkCSQJJAm/DyQJJAkkCSQJIAgAADBXAAIQAv4BEAFAAPwHIAggCP4JEAgQCfgEM1cABBAC/gMQAQAM/gMAAAAA/AcAAAAA/g86VwACEAL+AxABAAEiCfIEKgLmCSIM4AMAAD5XAAQQAv4DEAoABIQDfAiEBCQHPAXgBAAIQFcQAhAC/gEQAQAI8A8ACAAI/g8gCCAIIAhCVwACEAL/AZAEAAb+ATIM0gISA5ICcgQCCEdXAAIQAv4BEAEwAAwCKgEoCagICAz4AwAASlcQAhAC/gEQCQAMCAL4AUoISAhICMgHCABOVwACEAL+ARABQAg0CAoG6AEIAkgEOAgAAE9XAAIQAv4BEAFEAUQAJAD8DwQAJADEAIAAUFcgCJAIjgiwCIAI/g+gCJAIjgiQCCAIAABRVwACEAL+ARABAAzoAyoAKgDoBwgICAYAAFdXAAIQAf4BkACACAgESAP+AMgBSAJ4BEAIWlcACD4IAAkACX4JRg8qCRIJKgkmCUAIAABbVwACEAL+ARABAAQkBqQFZAQkBKQFJA4ACF1XAAIQAv4BEAEACP4JAgQCAvoBAgQCBP4JXlcQAhAC/gMQAQAC/AKEAoYCpgqkCJwHAABfVwACEAL+ARABgAkIBHgEigOMAngECAgIBGBXAAR+BQIFPgUCBaAHMAUOBRAFIAVABAAAYVcAAhAC/gMQCQAM+APICX4GSAbICVgIAABkVxAC/gEQAQAA/AMkASQB/w8kASQB/AMAAGZXgAAQAf4AkAAABP4EkgSSBJIEkgT+BAAEalcAABAC/gMQAQIAugCCAP4PggCyAIoAAABvVwAEEAL+AxACQAlECCQI/AskCEQIhAgAAHdXAAIQAv4DEAEEAPQDFAH0CQQI/AcEAAAAglcAAEACVAr0C1QKVAr8D1QK8gtSCkAAAACDVwACEAL+ARABAAQoBMgFCgQIB+gECAQAAIRXiAiICmgKGApMCkgPeAqsCqwKiApICAAAi1cAAEAEygQ+BAoFfgUKBwAFHgVABX4EAASSV0AIaAlICWwJCgkID2gJTAlICSgJQAgAAJtXAAQQBP4DEAIACKAEngLCD4IBvgKgBKAIolcAAhAC/gEQAQAO/AGUD1QEVARSBNIPEACjVwACEAL+AxAJBAj0C1QKVApUClQK9AsECKZXAAAACP4KqgoqCioPagqqCqoK3gqACoAIq1ckBJQF/gUUBQAF1Ac0BR4FBAV8BIAEQACuVwAEEAL8AxACgACoArgDrAqoCpgKqAaoAMJXAAIQAv4DEAkACfwHrAasBfwIrAisCPwAw1cABBAC/gMQAUAIKAkuBegDLAUsCSAJAADLVwACEAL+ARABAAh8CVQJVAn8D1QJVAl8Cc5XAAAQAv4BAAz4AygAKArICX4EiAduCAgG1FcAAhAC/gEQAQAA6A+oAqgC/g+oAqoK6gffVwAAEAL+ARABQACoAugKCAR+AogFaggMBuBXAAIQAv4BEAEAAvwCtAK2D7QCtAL8AgAC91cAAJQC1AKeD/QCEAhIBv4BCAEIAPgHAAz5VwABEAL+AQABJACkB7QEpgSkBLwErAckAPpXAABIAUgF/AR4BXgHeAV4BfwESAVIAQAA/FcAAhAB/gEQAQAAtAe0Aq4LNgg0CPQPNAAAWAAACAH/AAAG/wEFDnUERQT1B0UEdwcAAAJYAAA4CAoK7AqoCq4PqAqoCuwKCgo4CAAABVgABH4FVgV2BVYFXgcABUoFMgU6BUYEQAAGWBACEAH+AYAAMAD8D6oEqAT+B6gEqAQAABVYAAj+CgoKdgoACnwPPgo8CrwK/AoECAAAIVgQABAEfgUABV4FOgcaBXoFOgVeBVAEAAAkWBAEEAT+AxAKgAi+BqoEqg+qCqoKvgqACCpYAAAQBP4DEAMED/4JVAtUC1QJ/g0ECQAAL1gAAJgJnAl8BVwDDgFcAVwHfAlcCVgFAAAwWAACEAH+ARAA/A8EBPwGfAd8BfwFfARAADFYAABUAXQB3gd0AQAA/g9iCLIEMgPuDAAENFgAAggC/gEIAEAJ/gVqA2oFagNqCX4HAAA1WAACEAH+ARAB1ABUAN4HdAVQBVgF1gcQADpYAAEIAf4AgAm+BKoE6gM+ACoA6g++AQABQVgACEAJfgtqCyoKPg8qCqoKagt+C0AJAABKWAAEEAL+AxABAAF8CFYH1QD8B1QIVAt8C0xYCAEIAf8BCAFAAN8BVQXVB5UBVQnfDwAAUVgAAGgIzAp4CkwKKA+ACnwKVApUCvwIAABUWAACEAL+ARABRAAkByYFVAVUBSYFJAdEAFdY2ggCCooKqAosCqwOqgr6CiwKrAqoCAgAWFgAAggB/wEIAQAG/AEcBl0F+gVcBXwHFABaWAACEAL+AZAFBgWqAnoKigk6BsoAJgcAAF5YAACECrQKtAn0CrQKtg70CrQJtAqECgAAaVgAARAB/gEQBTgE9gfUB9QE1Af0BIQHAARrWAAEEAL+AxABAAj8C7wKvgK8CvwLBAoAAHVYAAAADP4H6gT+BWoFawd+BeoF6gX6BAAAflhECHwJfAv+C3wKAA+ICmgKHgr4CAAJwAiDWAACCAL/AYgICAj6BV4DWwFeD/oJCAQAAIVYAAh+C2oL/gtqC34PEAqSCvoKFgpyCAAAilgAAKwIrAruC7wKiA/oCjwKSAr4CAAJwAiTWAABRAX8BH4FfAV8BXwHfAV+BPwERAUAAZdYAAIQAv4BAAF8ANcP1Ar8CtQK1wr8DwAAmVgAABAD/gGQAAQA7AfkB/4G5AZsBeQHAACcWAAAfgSKBnYGAAZWBzwFtAX0BRYFZASAAJ5YAAAQA/8BgAA8AOYPdAV8BWQF5w88AAAAqFgABCAEfgU6BXoFPgd6BT4FOgV+BSAEAACpWBAE/gMQA3AC2grcD/gDAAr+BIgDeAwAAK5YAAD+CAIKfgoACvYPOwp+Cn4K3gp+CAgIs1gAAhAC/gEQAQQI1AfcB94D1APUB9QLEAjBWEAAfgRqBWoFagVuBzQFPAV2BTQFPAUABMdYAAAQAf4BAAF8BMwH/Af+B/wHzAd8BAQEylgAABAC/gEAA/QK1A70Cd4F9ALUBvQIAAjTWAAM/gPKAf4G/ga+B8IHEgf6BvIGtAQAAdVYAAAQAv4BEABEBbwGvAO+C7wHvAHkBgAE2FgABHAFfgV+BX4FfgcuBX4FfgV+BXAEAADeWAAAEAL+AQAAXAKsDjwJbgk8AuwG/AgAAOJYAAAQBPwDAAj8BwQA9A5kCAQO9AqkCgAA5FgAABAC/gEABXwE7A3+C8YB/AfsBfwJBAHrWCAAIAQgBCAEIAT+ByAEIAQgBCAEIAAAAO5YAAIYAgAB/g8AACAIIAj+DyAIIAggCAAA71iACJ4HkAD+DwAAIAggCCAI/g8gCCAIIAjwWAAABAzUA1QBVAHeAVQBVAFUAdQDBAAAAPJYAAjECFQIVAZUAV4AVABUB1QIVAjEBAAA81gACMQIVAhUBNQD3gDUANQHVAhUCMQIAAT2WAAAxAhUClQIVA9UCF4IVA9UCFQKxAgAAPlYAAA0BLwFfAV8BX4FfAV8B/wF3AUUBAAA+lgAAGQINAu0CvQOPgj0DrQKtAo0C2QIAAD9WJQA3Ab8BvwG/Ab+APwE/AL8CtwP1AKAAARZgAhgCN4ECAPoAhgEAAj+CyAIQAiACAAAB1lAAFAASA+sCrYKpA+0CqwKzArED0AAQAAJWQQKRAo0CYQFpAaeBMQG/AaECZQIJAgAAA1ZAAAICAgKdgneB1wFXAVcBVwLfAkECAAID1kACAQKfAl8BfwHfAV8BXwHfAl8CQQIAAgVWQAAQAAgCBAISAROBIoCCAGIAGgAGAAAABZZQABgCFAEjgKIAWgAEAAgAP4PgAAAAQACGlkAAFAISAlECTQFpgSUBkwCRAHAAEAAAAAcWYQARAD0DwQARAhmBLQDFAOUBHQEFAgAAB9ZIADwAywJ6AkICPgHAACoCJYEVAJMAcAAIFkICagEdgVUAswBEADMAyoB6AkICPgHAAAiWcQAfApsCm4L/AtsBWwFdgNsAXwAxAAAACVZAAj8BNQC/A/UAvwAEAhICdYGtASMA4AAJ1kQCBAEEAIQAdAAPgBQAJABEAIQBBAIAAApWUAIRAhEBEQCRAP8AEQBRAJEBEQIQAgAACpZEAgQBBAEEAPQAj4EUAiQARACEAQQCAAAK1lACEgESARIAkgB/gBIAUgCSARIBEAIAAAtWQAAQAhECEQERAREA/wARANEBEIEQghACC5ZAACACPgIiASIA/4AiAGIBogE+AiACAAAL1mAAEgIyAioBJgDzgCICIgImAgoB0gAiAAxWWAIcAROBEgCyAF+AMgBSAJIBEgEQAgAADRZQARICFIEVAREAsABfgBAAkACQARACAAAN1kAAAQI7ASsBKwC/gGsA6wErAq8CoQJAAA4WQAAKACoAKgCuAOsAqgKqAq4CqgGqAAoADlZAACACIgIqAiIBIgD/gCIA4gEqASICIAIOlkAAKgAqACoAJgGjACKCJgImA+oAKgAqAA+WQgJiAhoBAgECAP8AAgDiARoCIgICAkAAERZSAAoAOgHuAKsAuoHqAqoCrgK6AtICAAAR1kAADQAtAe0ArQCrAKuAywINAj0BzQAIABIWSgEqAyoApgIrAiqB6gAmAKoAqgMKAAAAElZAACgAKwCbAIsArwCrg+sAiwCbAKsAqAAS1lAAEQA5A9UBUwFxgdMBVQFZAXkD0QAQABOWRQEVARMBVwFVgV1B1QFXAVMBVQFFAQAAE9ZkABUCFwFfAVcA94BXANcBXwFXAlcCJAAUVkAAFQJVAl+CVQFQANCAyIFHglCCT4JAABUWSABJAkUBawDJAEmAXUBJAGMDxQBJAEgAVVZJAlUCUQJJAUcBQYDBgF8BQQFFAUkCQAIVlkgCSQJEAl+CQAFSANEAyYFJAkcCQQJAABXWSAAJAEUBfwHdAV2BXQFdAV8BRQNJAkgAFpZAAmECawFZAW0A6oBYgNSA0IFSgUACQAAYFkAAAQF/AXuBe4F3APcA+4F7gX8BQQFAABiWSgBKgGqAK4P6gq7CqoKugqmCqYPKgAqAGVZAAAACXwJDAVkBXYDJANMBQQFfAkACQAAZ1kACXwJBAVsBWwFLAN+ASwDLAOEBfwFAAloWQAALgkgCX4FAAUkA5IBFgORBf0FFQkQCWpZAABUATQB/AP0B/YB9AX0BfQD/AGUARQBblkAABoAmg/+Cv4K+w/6CvoK/gr6D0oAAABzWQAAEAgQCdAIMAkeBRICEAKQBXAEEAgQCHRZiAj4BA4DyAE4CAAMNATEA8QCPAQACAAAdlkICPgMDgOIA3AIBAf8AAQEPAgkCOAHAAB4WQAA+AgOBYgDeAwAAEQARAD8D0QARABAAHlZAAj4DA4DiAF4BgAA/AcQCP4JCAj4CAAGfVkACOgMHgOIA3gEAABECEQI9A9MAEQAQACCWQAACAj4CA4F6AMQAPwPBAQEBAQE/A8AAINZAAj4CA4FiAN4BAAAxAdECEQIRAj8CAAGhFmACIQIvAqkC6QKpgSkBKQHpAikCIQIAACGWQAAGAOAAP4PAACQCHAJHgYQA/AEEAgQCIdZCAj4BA4DiAF4AAAERAREBEQERAT8DwAAiFkACPgMDgPoAhgEcAFEAUQJZAlcDMADAACSWQAI+AwOA+gDGAzwA0gASgBKAEgA+AAAAJNZCAj4BI4CyAE4AgAIaASoBT4CqAVoBAgIllkABPwEBwPEAjwAAAwiAqIBfgChASECIASZWQAA6AieBsgBOAIACDwEgAT+AgACjAEwAJ5ZEAjwBA4DiAN4AAgI4A9cCEQI/A9ACAAApVkAAEQIVAbEB2QGbAJEAmIF8gRKBEAIAACoWQgA+AkOBYgDcAQAAAgP+ABOCEgIyAcIAK5ZAAj4DA8D+AgADP4DEgDSB5IIkgheCAAGs1kAANAIPgUQA/gEAADUAwoI+A8IANgBCAK5WQAI+AgOBYgDeAAADEgCSAH+D0gBSAJIBLtZFAlcCVwLXAvcBX4FXAVcB1wFfAkUCQAAxlkACPgJDAb4BQAA/AdEBFQFVAxEDPwHQATJWQAA6AgfB8gBOAbAASQAJAD+DyQA5AMAAMpZCAj4CA4H6AEQBngARA/EAP4PRADEBwAAy1kAAOgNHgOIAXgCAACwD64EoASsBDAHQADQWQAA+AkOBugDEAj8DyQJJAkkCfwPAAgAANFZAAD4DA4DiAN4BAAAkA+QBP4EkASQDwAA01kAAOgIHgXIAzgAIAicCJAI/g+QCJAIAAjUWagIrAisC5wKzAb8BIwCmgWqBKoIqAgAANpZAAj4BA4D8AgMCYAE/gMAAP4HQAicCIQG3FmgCKwIrQquC6wGvASsBq4FrQSsCKQIAADlWRAI8AQeA5ADeAQAAagHfgkoCTgJKAUkAOhZAAj4DI4DcAQEAOwMrAL+AawCrAS8CQAI61kAAPQMjwLkARgA/g+SBJIEngeSBPIEAATsWQAI+AQPA+gBEAD+BwIE8gSeB5IE8gQCBPtZAAD4DA8D6AEQAv4PAgXiBLoFAgT+DwAA/1kAAKIIlArUC8AGpgSUBIwGlAWkCKwIAAABWgAO+AEIBNgFeALYAwgI/gQIA8oEKggABgNaAAj4CA4H+AQAACQJJAm+DyQJJAkgCQAABFrICMgIrgqYC9gG/gSYBpwFqgTqCMgIAAAHWgAI+AQOA8gBOAZQADQPHAAUADIPUgCAABhaAAj4BA4D+AYAAPwPVARWBNQBVAO8BIAEG1oAAPANHgP4AAQIcAlcB+QBZAN8BcAJAAkcWgAA+AyOA3gIAgb+AZII/gf8DwIA/gMAAB9aCAj4CA4F6AMYAMAPvAK0ArQKtAr8DwAAJVoACPgMDgP4AgAKlAj8DxIE/gKQBVYIAAYpWgAI+AgOBcgDOAj4CJQElgP0D5wI8AgABDFaCAj4CAwFiANwCAwJVAfUAVQDVAVcCQAJNFoAAPgMDgP4APIPBACgAfoHogACCP4HAAA2WoAIwgj+CtoL/gaiBsgGtAWUBKwIpAgAAEZaSAhqCQoLYAscBUwFXAUuBSwHXAlECQAASVoAAPgMDgP4AAAITAw0A0YA9AcUCPQJAARaWgAA6ASeAsgBMAC+B2oFagVOBZoHKQAoAGZaAADoCJwGyAEwBoQDvAD8D7wAvASgAwAAdFpAAF4JQgkyC44F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TAVEBQwJAAC/W4AATADkBxQABADWB1QFdAVUBVQF1AcAAMJbAABMA0QI9A9UAEYLFAh0BJQD1AQ0CAAIxFsAAIwAxAfUBbQFtgW0B9QA1AjED4wAAADFWwAIDAjkC7QGtAb2A7QCtAa0BuQLDAgAAMZbAAAMAaQHhATkBE4HpASUBEQEFA9kAAAAx1tACFQE1ANUANQHVggECHQLVAvUCFQIAATMWwAADACEB/wF3AXeB9wF3AX8BYQHDAAAANJbAACMBLwCvAH8BL4IvAr8CLwJvAKMBAAA01sAAIQP9AD0AvQC9gP0AvQC9Ab0BIQHAADbWwAIDAjEC9QL9AfWA9QD9AfUC8QLDAgAAN1bAAAsAQQB/APECX4IfAt8BXwFfAvMCQAI3lsAAAwK5Ar0CvQG9gP0AvQG9ArkCgwKAADfWwAATAlkBbQB9AmGD5QBpAPUAzQFnAgAAOFbAACMAIQF/AX8A/wD/gH8BfwH/AGMAoAA4lsACWwHRAH0DwQA9gn0C/QF9Af0CKwJAADlWwABXAlcCbwKnAt+B0QGvAR8BXwBDAEAAOZbAAAUCNQH/Af8A/4D/AP8B/wH3AcUCAAA51sAAAwBxANUA9QLagvsD2QDRAPUAwwDAADoW4AEtAK0CrQL9AK2DrQC9Aq0C7QKhAIAAOlbAAFMAWQP9AtUC3YPVAtUC/QLVA9EAQAB61sAAAQB9AT0AvQA5gLEAfQA9AX0BIQDAADsWwAIDAjEC9QH1AfWA8QD1AfUC8QPDAgAAO5bAACMCEQI1AP0CtYO1AL0AtQLRAiMCAAA9VsAAFQI9AfUAfQK1AcGAPQHdAt0C3QOAAT2WwAEFgjWB94H1gPHA+4D7gP+B+4HLggAAPhbAAAIACgAaACIAQgICAgICP8HCAAIAAgA+VsACCQMRAKEAXwCAALQABAJEAj/BxAAAAD6W6AAqACoAKgGqAS8AKgIqAjoB6gAqACgAPtbAAAAAUQBVANUA1QBVAlUCVQHfAEAAQAB/FsAAAABPAFUA1QFVAFUCVQJVAdcAUABAAH+WwAIKAxIAo4BaAYIBFAA0AEQCP4PEAAAAP9bQAREBVQDVAH0BV4BVAlUCdQHVAFEAQAAAVwAAKQEpAS/B6QEpAQAANAJEAj+BxAAAAACXAAAAgF+AVYFVgF/CVYJVgnWB34BAgEAAARcgAT+BKoCqwmqCP4PCADoBAgE/wMIAAAABlwAAAgBkAD+DwAAhAK0ArYIlAjMD4QAAAAHXIAIngeQAP4PAADYAMQGrgSWCMwPhACAAAhcAAKEArwCvAa8Bv4CvAq8CvwHvAKEAgACCVwAD/4ACgKqCKoPqgCGAhAIkAj+BxAAAAAKXAAABAL0A5YHvAeUA7wL1AvWD/QDBAIAAAtcAAAgAzQD/AK8BhwC/Aq8CrwHvALgAgACDVwUBFgFbgXQB24FVAUUANAJEAj+BxAAAAAOXJAClgJwAoQG/Ab+AvwK/Ar8B/4ChAIAAg9cAAAAAeAAEAAACAAI/gcAAAAAEABgAIADEVxACCAIGAgACAAE/gQAAgACiAGQACAAAAAUXAAAIAIQAcwACggICPgPCABIAMgAGAEIAhZcoAiwCIwIgASAA94AgAOEBIQEmAigCAAAGFwAACAIEAkMCQAJAAm+DwAJBAkMCRAJIAgaXAAAAADkDygAoAe8AqACoAKgAygI5AcAAB1cAACYBLoMvAu4CL4EuAS4BLwGqgSYCAAAJFwACBAIEAQQAtABPgCQBxIIFAgUCBAGAAAsXAAI6AceAPgHCAgICugJBAgGCOgLCAgABDFcCAR4A1gI3AdYALgJAATwAx4A0AccCBgGNFwAAOgPHgD4BwAMnA+4D5AMjA+oDKgPCAw4XAAIAAz8AyQAJAAkACQAJAAkADwAAAAAADlcAAAQCJQElASUA/wAlACUAJQA/AEQAAAAOlwACAAG/gEiACIAIgBiAKIBIgI+BAAIAAA7XAAAAAz8AxQIlAb0AZQAlACUBxQIHAgABjxcAAAADv4BEgDSA5IEkgSSBFIEXgQAAwAAPVwAAoABfgASAlIEkgSSBDIIUgieAAADAAA+XAAAAAz+AxIA0gLSAtIHsgqyCrIJngUAAD9cAAAADv4BEgRSA5II0g+SAJIBUgJeBAAEQFwAAAAO/AFUAFQHVAVUBVQHVAhcCMAHAABBXAAA4A8eANIPkgiSBBIA0gcSCZIIXggABEJcAAAABv4BCgCqBKoHqgSqBKoEqgauDIAARVwAAIAPfABUD1QJVAn0CVQJVAlUD1wAAABGXAAA8A8OAOoPCghKCkoK6gtKCgoI7g8AAEhcAAAAD/4ACg7qCIoIigjqD4oI6ggODgAASVwAAAAM/AMUANQPlAjUC5QKlArUC5wIAABKXAAA4AccANQHVAVUBdQHVAVUBVQF3AcAAEtcAAAADPwDFAjUCtQK1A/UCtQK1ApcCgAITVwAAIAPfAAUC9QG1AJUAdQHVAlUCVwJAAROXAAAAA7+ARIMsgKSANIPkgDSAtICngSACE9cAAAADv4BCgg6BfoDKgEqAfoPOgEuAQABUVwAAAAM/AMUAJQP1AP0A5QDlAu0DxwAAABVXAAAAA7+AQoIqgfqBKoEqgHqAqoFrgWACF5cAA78ARQA9A/0BfQF9Af0BfQF1AkcDwAAYFwAAAAM/AMUBFQPVA/0D1QP1A9UD1wBAAFhXAAAAA7+AQoI6gtKDeoFSgVKB9oFzgnACWRcAAAADPwDFAD0B/QH9Af0B/QH9Af8AAAAZVwAAIAG/gHKBzoAKgr6BvoH+gX6B/4FAARsXAAAAA7+ARYIfgv2C+4H5gf+B/4I5gcAAG9cAAAIAOgBCAEIAf4HCAkICQgJ6AkICAAEcVwAAPAPAAQABAAE/gcABAAEAAQABPAPAAB5XAAA+AP+AwAC+AMAABgGLgmoCGgIKAgIBn9cAADwA/4BAALwAwAAdAFIAUgJSAzIAwAAgVwAAAAIjgmICGgIWAdPBEgCSAHIAE4AAACCXAAADAAoBygJKAkuCSgJKAkoCegJDAQAAJBcAAD4B/4DAAL4CwAI6AgoBT4GKAXoCAgIkVxAAEwAKAEoAVgBXgFYASgNKANIAUwAQACUXAAACABEB0oEOASKBwoESgQyBAQHCAAAAJZcAADwA/4D8AMAAPwPBAg0C8QINAkECgAAl1wAAOwPKACoAqgCLgEoAegCaAooCOwPAACaXAAAAAz8AxgA2AYeAZgBWAYYAPgHDAgABptcAAAAB3wERARUB1YERARUD1QITAjABwAAoVwAAPwPBACsByQCJALkAyQCJAKsCwQI/AepXCACLgGoAOgHqASuBKgEqASoBKgErgcgAK1cAAD8A/4DAAL8AxAASABEAlMCRAXIABAAsVwQAAgAfAcCBAgEzgcYBCgESgRKDygAAACzXEAAQAB8D1QEVATUB1QEUgRyBFAPQAAAALhcAAzgAywAqAKoAqgCrg+oAqgCqAKsAiAC4VwAAPAD/gMAAvgFAAy4BIgD/gGIAqgEiAjmXAAAJAA0BwQEPASGBwQEfAQEBJQPJAAAAOhcAADwA/4DAAL4AwII/g8QAP4GkAVWDAAA6lwAAPgDAAL+AwAC+AfAAKYPkgiwCMYPiADtXPgDAAL+AwAC+AMAAO4PoAK+AqAK7AcAAPBcAAD4B/8HAAT8BwAAJAVXBdoPVgVSBRAE9lwAAAAO/ARcBVwHXgVcBVwFXAFcCUAHAAD7XAAA+AP+A/gDAAAoBYwFygKIAi4FaAQAAANdAADwA/4D8AMAAFQDxAD+B8QAVAFEAgAAB10ACXwFGAFYCVgJXA9YAVgBWAUYBXwJAAAOXfgHAAL+AwAC+AMAALQDrAKuCzQI9AcgABRdQAAsAOgPWAVYBV4F+AdYBVgFWAVcBQAEFl0ADP4DDAisCqwKrgrsDqwKrAqsCq4KCAgXXQAAAAD2DxQAVAZ2BtYHdAZ0BhQI9gcAACldAAAMDOwDqAnoDw4ACAjoB6gCqArsBwAALV0IAWsBWgHKB0oBSwECDPoDSgDGD0cAAABKXQAA8AP8A/ADDADsBgwB/A8MAWwCqgQABEtd/AMAAv4DAALwBf4Dyg+qCq4KqgruDwAATF0gAOwPKAUoBegPDgDIDCgCqAEoBqwIYABQXQAA5g8cANwJXAn+D1wNXA2MCPwHBggABmldEACWD/QA9AD0B/QF9gX0BfQH9AiWDxAAi10AAAAA8Af+A/AJ/ARcDV4DXAtcCUAHAAC6XSAAkwCqAqoEsgcHAP4FrgWuAa4F/wUACM1dIAl8C3gFeAV4Cw4A+ATYA/gD3AbQBvAC3V0ACAAM/AMAAAAAAAD4BwAAAAAAAPwPAADeXQAAcAgABv4BIAAAAP4HAABwAAAA/g8AAOFdAAhECMgHAAT4CAQLcAiMCSAK2AgECwAI4l0AAAAF+wWoA6oD/Q+oAaoDrgX9BQAFAADjXQAAAAn+BagFqgP8D6gBqAOsBfoFAAkAAOVdAAQEBAQEBAQEBPwHBAQEBAQEBAQABAAA5l0AAAgMCAPICHwISghICMgPSAhICEgICAjnXQQCBAL8AwQBAAEEAHwERAhECEQMxAMAAOhdAAAAAP4PkgSSBJIEkgSSBJIE8gUCBAAA6V0EAgQC/AEECQAE/AMEAHQABAD8DwAIAAbrXQAFhAR0BIQEBAT8BwQFhAR0BIQEBAUAAO5dgAioBKoDrgioCfgJqA+uCaoJqAmACAAA8V0AAAAA5AckCCQIJAgkCCQIJAh8CAAHAAHyXQAA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dAbUBQYIVAr0C1QKVAoAALVeAAz8AwQAVAD0B9YC1AfUCtQK9AtUCFQEtl4ADvwBBAQkByQA9A6mAKQO9AAkAiQMAAC3XgAG/gECBKoCqguqCPsHqgKqBvoFIgkAALheAA78AQQA9A/0A/QD9g/0A/QL9AukDwQAwV4ADPwDBAj8B6wGrAL+CwQA9AsECPQHAADDXgAM/AMECEwF/ANOAUQB3AdsCWQJFAUAAMleAAz8AwQIdAV0A/QPdgH0D3QD9AVUCAAAyl4ADPwDBAj0D7QItAb2DAQA/A8MAPwHAADTXgAM/AMEAPQLvAu8D/YDBAD8DwwE/AMAANZeAAT+A4IAlgiOBmYHvwZiBW4FRgKeAIIA314AB/wABAL0A7QDtAe2A/YHBAb8AawE/APgXgAM/AMMAOQPvAKmC+4PRAj0BSQD5AwAAOJeAAz8A0QALAusCn4ERANsBfQHtAkUAAAA414ABv4BAgjqBfoF+wX7AfoB+gPqA+oFIgTzXgAAgA98AAQLfA/+DyQEdA10CXQDdAUAAPZeBAi0BKwDZAQABfQJBAkECfwJJAkiCSAJ916ECDQHrAVECAAKJAokCvwLJAoiCiAKAAD6XgIIcgwuA+IECAWqCaoJ/wuqCaoJvgkICf9eAAAQABAA/g8QBBAEEAQQBP4PEAAQAAAAAF9ACEQIRAb8AUQARABEAEQA/A9EAEQAQAABX5AIkAiQBMwDiwCIAIgAigDqD4wAiACQAAJfAAAACR4FqgMqASoBKgEqAaoPLgEgAQABA18ECSQJJAW0AywBJgEkASwBvA8kAUQBBAEEX0AJVAlUBVQDVAF8AVQBVAFUD1QBVAFAAQpfAAl6CTgFPgN4AXoBEAEsAbYPNAFMAQQBD18ICEgESATIB0gESAQIAn4AiAMKBAoICAYTXwAAAADyAJIAkgCSAJIIkgiSCJ4HgAAAABVfAADEAKQIpAikCLwHAAAAAAAA/A8AAAAAF18AAIgI6AioBvwBqACoAPwPqACoBLgDAAAYXwAB5AikCKQIvAcAAAAH+AQEBIAEAAcACBtf8giSCB4HQAD8ByAIEAj/CRAICAn4CAAGH18AAAAEyASqAqwCqAH4D6gArASqBLgDAAAgXwAA8giSCJ4HAABACP4PQATQBEgBRgZACCVfBAHkCKQIvAigBxADzAgICPgPCADIAAgD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iAAACqIJcgQqA+YIIg7gAQAAbWKIAIgI/weIAEAIAghCDv4JQghCDv4JAAhuYggBiAj+D4gAIAhQBE4DwABCCE4I8AdgAG9imACYCP4PWAAACPgPAAgACP8PIAggCCAIcGKIAIgI/g+IAEAIEATQAz4AkAcWCBAIEAZxYogAiAj+D0gAAAf8AMQEBAU8A5AEcAgAAHNiiACIDP4DiAgADvwBZASkBSQCpAVkCAAIdmKAAIgI/g9IAAAISARIA/4ASANIBEgIAAB5YogAiAj+D4gAAAD+DyAEAAD+ByAIGAgQBnxiAAGIDPwDiAgADPwDBAD0BxQIFAn0CAAEfmKIAIgI/g9IAAAIEAQ+AtADEgXUCBQIEAZ/YgAAEAQQA/QABAqkCvQHrAIMAuQAIAMQBIBiiACICP4PSAAACGgEqAU+AigF6AQoCAAAhGKIAIgI/g9IAAAIeAgABP4EAAKMAVAAAACKYoAAiAj+B0gAAAD8B0QIRAh8CEQIRAj8CJFigACICP4HAAD8BwICAgD8DwQABAT8AwAAkmKIAIgI/w9IAAAAIggqCOoPNgCmAGIAAACTYoAAiAj+D0gAAA78AQQA/A8CAP4AAg8ACJViiACICP4HSAAACN4EQgVCAt4FUAgICAAAlmKIAIgI/g9IAEgAAAEiAUwBAAH+D4AAgACXYgAAiACICP4HSAAADOgDLgAoAOgHCAgABphiiACICP4HSAAADv4BIgAiACIA4g8iACIAmmKAAIgI/g9IAEAIBASkA3wA5AckCCQIIASbYgAAiAj+B0gAAA//APgHAAn4CA4K+AkABJxiiACICP4PSAAADIgDfgioBSgC6AUoCAgInmIICYgI/g+IAAAM/ANEAEQAxAFEAnwMAAigYogAiAj+D0gAAAD8DwQIFAvkCLQJBAoACKFigACICP4PSAAAANgHhAiCCEQICAgwBiAAomKIAIgI/g9IAEAAEADIBycIJQnICBAGEACkYogAiAj+B0gAAAz4A0gASgBKAEgA+AAAAKViiAiICP4PSAAAAP4PIgDyDDIDMgXuBAAIq2IIAYgM/gOICAAO+AHIBX4GSAXIBFgIAACsYoAAiAj+D0gAAACwD6wEogSgBKQEmA8gALFikACQCPwHUAAAALAHrgioCOgJCAn4CAAGtWKIAIgI/g9IAAAA/A8kBCIAPgziByIIIAa5YogAiAj+D4gAQAQIAkgB/g/IAEgDSAQAALxigACICP4HiAAAAPwBpACkAPwPpACkAPwBvWKIAIgI/gcIAOAPkASQBP4HkASQBPAPAADCYgAAkAj8B0AA6AyoAv4BqAD+D6gAuAcAAMRiiACICP4PiAAIAIAIiAiKCPoPiAiICAgIxWKIAIgI/g9IAAAI/AkkCSQJJAkkCfwJAAjGYogAiAj+B4gAAAz8AyIAogDiDyIBIgIAAMdigACICP4HSAAAAP4DIgKqCiIKIgb+AyACyWKAAIgI/g9IAAAEKATIBQoECAfoBAgEAADLYgAAiAj+B0gAAA/+AMgHAAn+CggK+AkABMxiCAGICP4HiAACACwBIAH+DyABLAEiAQAAzWIIAYgI/geIAAAA+A+IBI4EigSIBPgPAADQYogAiAj8B0gAAAi8BKQCpAGkCKQIvAcAANJiiABICP8PSAAAAP4PkgSSBJIEkgTyBAIE02KIAIgI/g9IAAgBgADkD1wERAREBMQPAADUYogAiAj+D0gAAAyIA34IqAUqAqoFaggICNZigACICP4HiAAgAJAAzgdICOgLSAjoCwgI12IAAIgI/g8AADgD5gIwCxAF8AMeCPAHAADYYoAAiAj+D0AAEADIAy4BKAHoCQgI+AcAANligACICP4HSAAAALwHIAT+ByAEIAS8DwAA2mIAARgJ/geYAAAImATUA5IAkADUD5gAoADbYoAAiAj/B0gAAACiD5oEhgSiBKIEngcAANxiAACUDJQC/AGSAAMAKAEqAf4PKgEqAQAB3WKIAIgI/gdIAEABFAFUAfwPVAFUAQQBAADfYoAAiAj+D0gAAAT+AwABvAwAAsABPgEADuBigABICP4HYAD+DIgDcAT8CQQI/AsACoAJ4WKIAIgI/g9IAAAO+AEIBIgHbgQIBQgFCA7iYoAAiAj/D4gAAA6QAX4MEATyB5QIVAgQBONigACQCPwHkAAABOgCuAqsCOgPiACIAggE5WKAAIgI/gdIAAAM/gOSAJIA/g+SAJII/gfmYoAAiAj+B4gAAASSBJYEkASYBJYEEAQAAOdiCAGICP4PiACAABgASAhICMoPSABYAAAA6GKAAIgI/geIAAACHAnQBH4FUALUBVQIEAjpYogAiAj+D0gAAAKkApwC1A+cAqQCJAIAAOxigABICP4PSAAAAJIPkgj+CJIIkgiRDxAA7WKAAIgI/g9IAAAEUATQBxAE/AEQBhQMAADvYoAAiAj/D0gAAAnSCCIK+gsmCNIIEgkAAPFigACICP4PSAAACIgE/gKIAIgA/gKIBIAI82KgAKgCagJsC3gL7gcoAygDbgKoAqAAAAD0YgABiAj+B4gAIAgYCSQJ4g8kCQgJMAgAAPdiAAEQCfwHkAAAACgBqAP8CqgKuAqoBiQA/GIAAQgJ/gfIAAAIiQT6A4gAiAD8D4sAgAD+YogAiAj+B0gAAACYD4QEogSiBKQEiAcwAP9iCAHIAfgB/AX6BfoD+gH8AfgB+AGIAQgBAWOQAJAI/AdQAAAAqAKoArwIqAjoB6gAIAACY4AAiAj+D0gAAAgkCSQJvg8kCSQJIAkAAAdjiABICP4PSAAAAN4HZAVkBWQFYgXiBxgACWMIAQgN/gMICEAIXAjEBXcGRAPEBFwIAAAOYwABEAn8B9AAAACoArgDrAqoCrgKqAagABFjgACICP4PSAAACYgE/gMAAP4HQAicCIQGFmOAAEgI/g9AAAQAVARUC0YJ1AhUCAQGAAAZY4gCSgIsArgKqgrsB6gCiAI+AkoCSAIAABpjAAAUAtQD/gOUC4AHtAOeA4QDPANAAyACH2MAAQgJ/gfIAAAIqAiIBv4BiAOoBIgIAAAgYwAAiAj+B0gAAAikBKYDvAC0D8wIrAiABCFjiAGICP4HSAAABC4FIAU+BSAFKAXmDwAAI2OAAIgI/g9IABAAWAlWCfQHXAFUAfABQAAkYwAAiAj+B0gAAAhEBEwDNgAkAFwPRABEACVjAACICP8HAACWAtICsgKaAtIPkgKWAgACKGOAAIgI/gdIAEAJLAUrA+gDKgMuBSgJAAgqYwAAiAz/AwAIkgb+AZII/gf8DwIA/gMAACtjgACICP4HSAAgCBwJYAn+DyAJHAkgCUAAL2OAAIgM/wOICAAO/gHCD1IE0gVSAVIOAAg6YwAAiAj/D0gAAgw+A+IEAAgiCf4JIgkiCT1jgACICP4HQAAQCPgIlASWAvQBnAeUCPAIQmNIAEgI/g8oACAAqge+BKoEqgS6BKIHIgBFY4AAiAj8B0gA4A+kArQC9A+sAqwK5AcAAEZjgACICP8HAAD+DwIEUgT6BVIEAgT+DwAASWOAAIgI/g9IAAAMvAMkBOQPpAikCLwIAAhMYwAAiAz+AwAIvAakAbwIAAf4AQAI/gcAAE1jiACICP4PSAAAAX4BagFqAeoPagF+AQABTmMIAQgJ/geIAAAA4g+sAqACvAKgCuwPAABPY4gASAj+D0gAAAS+BKoEqgeqBKoEvgQABFBjiACICP4HSAAAAO4PqgKqAqoKqgruDwAAVWMIAYgI/geIAAAA6A+oAqgC/g+oAqwK7AdcY4gASAz+AwAIvASsBawG/gSsBqwFvAgABF5jgACICP4PSAAACJQElgLUAZQIlgw0AwAAX2OAAIgI/gdIAAAI4AkuBCoCqgEqBC4I4AthY4AAiAj+D4gAIASYBSQEogUkBAgH0AQAAGJjiAz+A0AIEAj4BJQClgH0AZwClAT0BIAIY2MAAQgJ/geIAAAG/ASEBpYEhAa8CIAHAABnY4AASAj/B0gAAABqAr4Cqw+qAuoCqgIAAGhjiACICP4HSAAQAEwHUgV6BVIFRAVIB1AAbmNAAEgI/g9IAAAH/gAyB7IE8gSyBL4HAAByYwABEAn8D5AABALUB3AJXA1QDVQO1AhAA3ZjAACICP4HCABACfQJVAn8D1QJ8glQAQAAd2OAAIgM/wNICAIIqgaqBKoE/w+qCvoKIgh6YwABEAn8BxAAQAQoARgJTA9YASgBSA1AAHtjgACICP4PSABABwgAJAcqCCIJZAgoAwgEgGMAAIgI/gcAAPwPFAD0DwAAFA7qAQgGOAiCY8AARAb/AQAM/gMCAIIPggT7BJIEkg8CAINjgABECP8HBABgALUHtQD1D7UAvwTgAwAAiGOAAIgI/gfIAGAIaAikBKoHogS6BmoFAAiJY4gI/gdIAAAC+AKoAqgCrg+sAqwC/AIEAoxjAAAcAs0C/wL8Cv4H/AL8Av8CjQKcAgAAj2MAAQgJ/gcYAIwCqgLoA6gCqAqICPgHAACQY4gAiAj+D0gAAADQD0gFBgVEBFwFxA8AAJJjiACICP4PSABAAAgBKAHWDvwHKAEoAQAAlmMAAIgI/geIAAAA5A8UAMYIdAWkA+QEJAiYY4AAiAj+BwAA/g8KAOoOigjqD4oI7g4AAJljAAEICf4HiAAAAqwKpArqB6ICqgLqA4AAm2OAAJAI/AcAACgFvgcoBQAA/A9AAMAAAACgY4AAiAj+D4gAAAT0ApQIlgeUAJQC9AIEBKFjgACICP4HSAAABJQChAHUD4IBsgKKBAAAomMAAQgJ/gfAAAwEpAKUAcQPlAGkAqwEAAClY4AAiAj+B0gAAAikCqwLpgSkBrQFpAigAKdjAAGICP4PSAAMCKQIlAiGD5QIpAgMCAAAqGNIAEgI/g9AADAA/A+qBKgE/geoBKgEAASpY4AAkAj8B1AAAADoA7gCrALqB6gKuAroC6pjiABICP4PSAAAANQHXgVUBVQFXgXUBwAAsGMAAJQI/AeyADgG5gH8AxAIkgj+B5IAgACyYwgBCAn+BwgAAAG+A+oFqgSqAqoIvgcAALdjAACICP4HSAACDvgBTgcAAP4PAgD+AwAAuGMAARgJ/geYAAAC8ANSA1QD8A9cA1ID8AO6YwAAiAj+B0gAQABYCrwKWgkYBTwEWAKQAMljgACICPwHSAAACXQFHANcD3wDFAU0CRAAzWOAAEgI/g8oAAAIXAl8BdwDXgF8BVwFXAjPY0AARAT/AyQAAAD0D5QElwT0B5QElwT0D9BjAAEICf4HiAAADL4CqgSqD6oKqgq+CoAI0mMAAEQE/wNEAAAA6g+qBAoE/gcJBOkPAADWY4gAiAj+B0gAAATsB2wFbAVsBWwF7A8gAtpjBAGEDP8HxAAABt8DVQlVBVUDVQlfBwAA22OAAIgI/geIAAgIeAk2BZQDPANQBXAJAAjhYwAAkA78AQAM/AM0CLQK9Aq0D7QKvAoACONjAACICP4HQAAcD7AAsA/+ALAPsAC8DwAA6WOAAIgI/g9IAAAA/gdoBUAFfgVoBeQHFADqY0AAiAj+B0AAEgH+D0IAGgwAA/4AAAM4DO1jAAEICf4HiAAAAP4G6gSqBaoIqgi+BwAA7mMgAEgI/gdIAAAC+gK6AroC+g+6AroC+gL0Y4AAiAj+D4gAAgRWAvIJ1gbSBNkHVQhACPpjiACICP4HSADAAIwOpASsBOwHogSyBKoO/WMAAIgM/wNACB4IwAteCEAHVgjUCwQIAAQAZIAAiAj+B0AAEAC4BHYENAV8CbQKsACAAAFkAABICP4HAADyD0IAWAeqAtoCAgv+BwAAAmRAAIgI/g9IAAAIqgqYC94EmAaqBaoIgAAFZAAAiAj+B0AAGgj8BTgEugc4CO4JCggABg1kiACICP4PSAAACOwF7APsAewB7AXsCQAID2SAAFAI/AeQAAAAeAN4A3gBfgl4CXwHeAETZIAAiAz+A0gIAAzVA1YIfAlUD1cJVAkAABRkgACICP4HSAAAAKYJWglSCdYPWg1WD9IPFmQAAAgJ/geIAAACVArECqYKng+MCoQKAAAcZIgI/gdIAAAIvAi0CaAG/gSgBrQJvAgACB5kgACECP8HJACAD1oAWgdbBVoHWgDCDwAAKmTAAEgI/gdIAAAH/AB0BnUF9gV0BXQHFAAsZAAAEA78AYAM+AN+CfgHAADeDUICngUgCC1kAACICP4HSABAAG4HVgVcBWQFTgdEAAQANmRAAEgI/A8gAJAPaAB4B3QFcgV0BWgHEAA6ZAABBA3/B4QADAj/BasDqgH/BasDqg6CAERkAACIDPwDKAiABLwGvAG8BbwGvAakCQAARmSAAIgI/gdAABwFVA1cC9QJXAVUBVwJAABHZIAAiAj+B0gAAAasBKQE6geiBKoEqg4AAEpkAABICP4POALIATgBMAD+D6gE/gesBAAEVGQAAIgI/geAAIgCBAK0Au4OxAIEArQCgABYZIAAiAj+BwgA4A8UAFwH9gVcBxQI9AcAAGdkAABICP4PSABMAOgHaAVuBegHaAVsBQAAaWQADPwDBAC0A7QLtguEB7QDtAN0A3QDVAJ4ZIAASAj+D0gAAAl0CXYH9AF0A3YFdAkECXlkAAFEA3wD/AN+C/wL/A9+AvwCfANEAwABg2QAAvwD/AP+C/wLvAfYA9YDUgN2A1QCgAKHZAAAiAf+APAPXgD8B3AA9Ac6BsUBPAYABJBkkACQCPwHkAAYCPwL2AbeBtgC/g+YAgACkWSAAJAI/AcAAJgD/AvYC9wH2AP8AxgDAACSZIgI/gdIABAA9A++ArQK/g8QCO4GiAN4DJVkAACQCPwHAAD8DVgB/AUAAPgPJADkDyQAnmRICP4HWAAACPQK9Ar0CvYP9Ar0CvQKEAikZEAARAz/BwAA8g+/AtoPEAg4BMcDfAwAAKVkAAAICfwHCACgC7wK5A5ACygF/AeoCQAAqWSAAIQE/wNEAAAE+gFWCVMPVgH6ATIMAACrZAABkAj8B1AAAA38ASoB6A0oAegNKAHoDaxkAACICP4HSAACA9YPHgM2AK4DrQcoCwAKrWSAAIgI/gdYANQAVAe8BbwHlAW6BdIHkACuZIAAhA7/AWAE4Ae/BrUG9Q91BHUD/wVgBLBkAACICP4HoABOCfYFVgVAAU4F9gVWBUAJsmRAAEgI/g9IAAIJeAVuA+gBbgN4BWoJAAi1ZAAAiAj+B4gAAARcBd4FQA9cBU4FXAUAALxkAABIB/4AAA78ASwB3AesA38CpAMVBAADv2QAAIgI/gcIAOgMtAL0BBIA8gy0AuQECAjBZEAASAj+BwAAtAxkAwQA+gdUBfwHVAUABMJkAACICP4HCACcB8wFnAW8B5wFzAWYBwAAxWQAAIgI/gdAAHwEzAf8B/4H/AfMB3wEAATHZAAASAj+ByAAvgL6Ar4Cug++AvoCvgIAAMpkQAT8BPwH/gf8DvgPkAfuBqIG5gaoBAgBy2SAAEgI/gdIAAAAmgf8BdgF3gfYBf4FigfNZAAAkAz8AxAIwAW8BfQDlA/0A7wF4AkAAM5kFAA8Ar4DuAPOC7wLhA+oA7YDlAMsA0QC0mQAAYgI/geIAAgOxAGSB9oF8gO0CcQPAADUZIAAiAj+D0gAGA74Aa4MvA/MD7wPyA8AANpkgABICP4PAAT4AxgA2AX+A3wPbAFsBgAE4GQAAIgI/gcIAGAM1APkAr4CvAK8AuwPBADmZAAACA3+AwgJLAmUAdQJvg+0AfQBHA0AAOxkAACICPwHAABeDdQDVAwAAywE9A88CWQI9GSAAIgO/gEADPwDRAj0C/QL9gP0C9QLAAD6ZAAAiAz+A8AIdgfKDO4HCgBuBqoKrgoAAP5kAAGICP4HCADCCH4K3gdeB14H/gvCCgAIAGVUAMwCXgJMA+AL5gvUB8IDSANeAswCVAAPZQAAmAz+AwAI6AdmAvQPAADeB9QL9AoAABJliAj+B0gADAjeC14IXAZMAV4EXgisCyAAFGUAAIgI/gcAAP4H9gR+A/AH7gP2CP4HAAAYZQAAiAj+B0gE+APsD/wJxgH8B+wF/AkAABxlQAAkBP8DIACLD34B+gJ7BvoBegT7ByAAHWUAAJAI/AdQAMQD/AL8DzwA/AP8A+QHIAIkZQAAAABICP4P/gv0B/4O9A+uBPoHqAQAAC9lCAgoBGgEqAQoAz4CKAOoBGgEKAQICAAANmUAAPwDAAEAAf4PAAAwBG4EiAPoAhgECAg5ZQAA5AEkAiQBfAVgDDAEzgIIAegCGAQICDtlBAEEAfwBBAlkCRAEbgKIA4gCeAQICAAAPmUACAgG+AEqCMgHIAAQDO4CiAN4BAgIAAA/ZQQE9AMEAvwDJAJkCDAE7gIIA+gEGAgACEVlCADID0gEfgTID2AIPATKAogDeAQICAAASGUICKgEigKMAygEQAAwDM4CiAN4BAgIAABMZQAAkg+SBP4EkgSCDyAAFAzqAogDeAQICE9lQAD4AVYB9AVUBfQDYAkeBOUCxAM8BAQIUWUIAmgJCAn+D8gACglgCH4EiQPoAhgMAABWZQAEVALUAf4E1ATUA0AAfgaIAWgCGAYABFdlAAj8BVQFVAH8BWAAOAzMAogDeAQICAAAWGVQAlgJVAjyB0QAZAswCO4ECAPoBBgIAAhZZQACVAJUCd4P9AFYCTYIfASLA8gCOAwICFtlAADQBRgE1AQWA4gIMARuAogBeAIIDAAAXWUAAPYP0AH+D9AB9g8ACD4EyQPoBBgIAABeZQAA7g/gAX4CoAnuD0AIfgSIA+gEGAgAAGJlAAAIAvoDqgKqAv4PAAAwDO4CiAN4BAgIY2UAAOoPrwKqAq8KygcgABoMdQLEAzwEBAhmZQgC+ArYCtwO2AN4CmAI/gQIA/gECAgAAGxlRAD0A1YB1AkWDPQDMAhuBogB6AIYDAAIcGWgCKoKmAf+BJgHigggCD4EyQOIAngECAhyZQAA9A/0A/YCdAn0BwAA4Aw+AygD6AwACHRlQABcCDwIvg68CNwP2Aq2CrQKTAhECAAAdWUAAPoPDgP7Ag4J+gcQAD8MxAN8BgQIAAB3ZQAEvwKrAf8FqwW/A5gIPwTCA3ICDgwCBHhlCAl8C3wL/gV8BXwLYAkwBO4DeAQICAAAg2UAAF0JfgX/B1QDXgFoAOYDVgVcBWQFQASHZQAACAgICBgEaASIAgoBiAJoBBgECAgICIllIgQSDNIDVgFaAUsBSgFWAVYB0gcSABIAi2VkAGQPZAFUAVwP1gFUAVwPZAFkCWQHYACMZQgIaASOA3wCAAjUD/QHEAD+AxAEFg4AAI5lJAgkD6QAHAJUCVYPVAEsBSQApA8kAAAAkGWkCKwIrASsBZ4GwAKAAr4GrAWsCKwIoAiRZQAAJAT8AwAIKAbKATgCAAhECPwPRAgACJdlAAIQAiQBJAFIAQgBAAH+DwABgACAAAAAmWUMAKAD/g+gAKwAAAIkAUgBAAH+DwABAAGcZQAEWANUCPIPVAAEAyAAbAEAAf4PgAAAAJ9lQADIA3wF+AT4BXwFAAQoAIAA/weAAAAApGUAAAAO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rAL8BAQEAAB+Z4gBSAD/B0gAgAQ4BIYHYAQBBI4FMAYAAH9nCAOIAP4PiAAADPwDZAikBSQGpAVkCAAAgWeIA0gA/g9IAAAMhAN8CIQFNAIsBeAIAAiEZ4gBSAD+D0gAAACcAWoBCAnICQgM+AMAAIlniANIAP4PSACIAAAIRAhECPwPRAhECEQIkGeIA0gA/w9IAIgAAAz8AyIAIgDiDyIAIACVZ4gDSAD+D2gAgAg4BIgDfgDoBwgIOAgABpdnAACIAUgA/w8oACgCgAFIAP8PaACIAwABmmeIA0gA/w9IAKAIEARuBIgDyAI4BAgIAACcZwAAgAS+BKoCqgGqAf4PqgGqAr4EgAQAAJ1niAFIAP8PSACICCAEqAQoBT4CKAXoBAgInmeAAUgA/wdIAAAH/gAABIADfgCAAwAEAACgZ4gDSAD+D0gAAAEkARwBBgGEDzwBIAEQAaJniANIAP4PSAAAAPwPBAgUC+QItAkECgAIo2cAAAQBtACUBFQEfglUClQKlAq0AAQBAACqZ4gDSAD/D0AAEADIByQIIwkkCcgIEAYQAKtngAFIAP4PKABAD/wABAb0AQQC/AcADAAAr2eIAUgA/g9IAEAAEA+QBP4EkASQBJAHEAC2ZwAApAiUBI4ChAHcD4ABvAKkAqQEvAQABLdngAFIAP4PSAAADv4BCAzwA/wPBAT8DwAAxGeAAUgA/g8oAAAA9A8UAJQBfACUCRQI9AfPZwgBiAD+D0gAAAD4D4gEjgSKBIgE+A8AANBnAACEBIQEvgKsAewHrACsAb4ChASEBAAA0WcIAYgA/g9IAAAA/g+IBIgEiAT+DwgAAADSZwQJZQkRBRIDBAPEDx8DJAMkBSQJFAkAANNniASqBKoCgAKkAbQPjgGEAvwCwATABLAE1GcACVAJVAU0A3wD3A90AxwDFAU0CRAJAADYZ4gBSAD+DygAKAGAAPQPTAREBEQExA8EANxnCAOIAP4PSAAAAPwPJAkkCSQJJAnkCQQI4GcIA4gA/g9IAAAAWABICEoIzA9IAFgAAADlZwAASAgoCKgPWA1cDUgNWA2oDygISAgAAOxnAAAECPQEtAKUAf4PlAG0ApQE9AQECAAA72eIA0gA/g9IAAAA9AMUAfQJBAj8BwQAAADxZwAAiANIAP8PyAAICQAIigj6D4wIiAgICPNngANIAP4PAAD8CQIF+gIAAPwPBAD8AwAA9GegBL4EoAK/AqQBgA+fAaQCpAKkBKIEkAT7ZwAAJAgUCNQPrAquCqQKrArUDxQIJAgAAP9niAFIAP4PSAAAAOgDKAAqAPwPKAAoAugBA2iIAUgA/w9IAAAP/AAUDvQBUghSCNIHAAAEaAAEUARcAlAB0gDUD9AAUAFYAlQCUAQABAVoAAOIAP4PAAT+A0II/gdAAP4HQgD+D0AAB2iIAUgA/g9IAIgEIAKkCSQI5A8kAKQBIAYIaIgBSAD+DygAQAgQBFAEfgTIAyoFqgigBgtokANQAP8PUAAEBnwBRwjkD0QARAMEBAAAD2iIAUgA/g9IAEAEEgSWBJAEmASWBBAEAAARaAADiAD+D0gAAAbkARwDQADQCRAI/gcQABNoiANIAP4PQAAQCAgJJAniDyQJCAkwCAAAFmiIAUgA/g9oAPoPigV+BAoEfgSKBPoPAAAXaAQJdAlUBVQFfAPUD1QBfANUBVQFdAkECSFoiAFIAP8PSAAICGAEGATYAg4ByAIoBEgIKmiIA0gA/g9oAIAEEAROA8gA/g/IAUgCQAQ3aAgBiAD+D0gAAAFKAUoB+A9IAU4BCAEAADhoiAFIAP8PSACICCAEaAWYBE4CKAOoBIgIOWiIA0gA/w9IAAAA/g9SCNIIUgFSBn4FAAk8aMQBJAD/DwQATADkD2cEWwRaBGYE4gdAAD1oEARUAlQB3g9UAVQJEAT+AhAD0gQUCAAGPmhACGQJFAUEBTwDBg9EATwDBAUUBSQJAAhCaIgDSAD+D0gAAAgkCSQJvg8kCSQJIAkAAENogANIAP4PQAAMCYAE/gMAAP4HQAicCAQFRWiIA0gA/g8IACAO+AGWB1QIXArQCRAIAARGaIgDSAD+DygAQAD8DwQIVAr0C1QKVAoACEhoAACUCZQFtAVUA1YPVAF0A5QFlAUUCQAITGgAAAAJeAVYBVgD3g9cAVwDXAV8BQQJAABQaAgDiAD+DwAA/A8EANQDVALUAwQI/AcAAFFokAmYBV4FfgMWAYYPVgFaA1oFsAWACQAAU2jEASQA/w8kAAAE/QUlBSUFJQUlBf0FAQBcaIgDSAD/D0gAyghCCMQFcQZWAkAF3ARCCGNoiANIAP8PSAACBCwFIAU/BSAFKAXmDwAAZWiIAUgA/g8oAIAIVAQ0AxwAFAAyD1IAgABmaIgBSAD+D0gAAAF8AQIBkA8+AUgBRgEkAGhooASUBJACvgKAAagPpgGWApQCjASEBAAAaWjEASQA/wcUAAAO/AEEBCUE9QckBCQEAAB2aIABSAD+BwgA4g9SAVoB+g9WAVIJ8gcAAH9oiAFIAP4HSAAAAX4BagFqAeoHagF+AQABgWhMCWAJEgVYA0IDMg8OAUIDQgU+BQwJMAmFaBABkAD8D5AAoATYA6wCqALoC6gK6AeAAoZoAAOIAP4PSAAACSgN/gMAAPwPBAD8AwAAk2gIA4gA/g9IAAAAVAFEAcYPdAFEAUQBAACXaIgDSAD+DwAA/AisBqwG/AWsCKwI/AgAAJ1oAAAgAPwPAgD4AwAAqAauAJQPtACsAqQEomiEAUQA/g8kAAQA8QdWAVABXgFQBfYHAACmaAAAEgmKBF8ERgVqAkgCSgHfAEYACgAQAKdoiAFIAP4HKAAgAKoHvgSqBKoEugSiBwAAqGhACCoJGgV+BRkDqg8AAR4DQAVABX8JAAmtaIADSAD+D0gAQApYCR4FygaYBp4JqAgACK9oiAFIAP4PSAAABOoErAL4D6gArgS4AwAAsGgAA4gA/w9IAIAM6AOIAOgP/gQIB+oIIASzaIABSAD+D0gAAAy0AywApw8kALQPIAQAALVoAAA0CAwE3gNMAVQBQAJMAN4HDAgUCCQGtmiIA0gA/w9IAAAP/gAKAqoC6gdKCU4JAATAaAgBiAD+D0AAEAUIBSQEogQMBpAFUAQAAMRoRAlUBdQFzAPMAe4PzAHMA8wDzAVUBVQJyWiEA0QA/w8kAEAAngeqAKoA6w+qAL4EgAPLaIgBSAD+D2gAQAkIBf4FWAFYAf4BCA0AAM1okANQAP4PUAAAAPwPVAlUANQHfAkABQAA0miIAUgA/g9IAAAAbAI8Aq4PrAI8AmwCoADVaIQBRAD/D2QATAZEAVQE1wdUAEQBTAIAANhoAAD0DBQC/g8UAfQIYAQUAv4PFAL0DAAA2miAA0gA/g8ABP4Dkgj+BwAM/gOSCP4HAADfaIgBSAD/D0gAAAT8BKwCrAH+D6wBrAL8BOBoAAgYCQoFfAVYA94PWANYA34FCgUYCQAA42gIA4gA/g9IAIAIFAZUAP4PVABUBXwFEAjuaAAApASUAtQPjAKMBD4EjALUD5QBpAKABPFogANIAP4PSABACjQJ1AbeBJQGtAkUCAAA9WgAAMQBJAD/DyQAAAPfAPUH/wfVAF8DQAL6aIgBSAD+B0AAHAD8B/QHVgVUBWQFDAcAAAVpiANIAP4PCAAgALQHrAKuCywI5AcgAAAADWnIACgA/wcIAOAPBAT8BVwFXgVcBfwFBAQOaYgBSAD+DwAAMAD8D6oEqAT+B6gEqAQAABJpgAFIAP4PCAAgDf4DKAiACRwE5AN0BgwIHGmQA1AA/g8QAPAJOAk0BfIDNAM4BfgJEAgtaQAAkAD/DwAA/g8SAO4BAAD4D68C6A8AADBpgANIAP4PAAD8A1QC/A8AAP4PAgD+AwAAP2mAAVAA/AcAAKgA+A94BXgFfAX4D3gAgABKaRADkAD8D5AAAAj8B9QB1AXUA9QJ/AcAAFNpgAFIAP4DAAz+A0IAqgT6B6oEQgT+AwAMVGmAAUgA/g8AACwJfgkMB6ADHgVCCT4JAABaaQAAVAhMBl4DVATAD1QJTAleCUwI1AgACF5pAAOIAP4PQAAcCFQE3ANUAVwJVAlcB0AAY2nAASQA/w8UAIADfwDlD1UFVwVVBfUPBwBtaQgJagVsBXgDbgHoD2gBfgNsBWoFCAkAAHVpiANIAP8PCADiCaII7gj6C0IIkglyCgAAd2mAAUgA/g9IAAAAvA+oCoAKvgqkCqQPFAB8aYABSAD+DygAiAiqCpgH3gSYBqoFqggAAH1pAACkBKQEgAL8AdYH1AH8AYACrASiBAAAgmkAA4gA/g8AAPwHVAJ8CSAExAN8D0QIRASEaQADiAD/D0AAHgjACV4EQANOBtQLBAgABIZpgAFIAP4PCADwB7gC9A8WANYDBAjoBwgAlGkAA4gA/w8AAPwHVgJ8BwAA/A8EAPwDAACVaYgDSAD+DygADAGUD0QJJglECZQPLAMAAJtpgAFIAP4PKACACOwFvAOuD6wDbAUkBQAAnGmIAUgA/g8IAEAIXAbcAVYJVAlUCVQHAACoacQBJAD/DyAAggBKACYA9w+iAqoCqgIAAK5pAATiBOwErgKiAKAPsgCoAqYCqASiBAAAtGkAA4gA/g/IAAAAvA+iCpAKpA+cCoQKvA/LaQAAyAMoAP8PAAD8D74CvAL8A74K/AcQAs1pyAAoAP8HKAAIBugBfAd7BXwFdAV0BwAA0GmAAUgA/g8IAHwAVAhWB/wA1AdUCXwLAAjYaQgDiAD+D4gAAARWBVQA/A9UAlYFVAUAAP1piANIAP4PSAB6ANoP/wraCv8K2gr6DwAAAmrABOwE2gLAArwA1gfWAPwCiAL2BOAEAAAKaiQIFAl/CRQFUAVKAzYBQQM0BX8JFAkkCRFqiAdIAP8PSAGEASYJDA24Dw4BfgUQCQAAE2qAAUgA/g9oAAAIfAt8C/wFfgV8B3wJfAkZaogDSAD/D0gAHAVsAXwJbA98AWwFfAUABR5qAAOQAP4PAAD8BwQJ9ArUC1QJtAqECwAAH2qAAVAA/g9QAAAC9AL8AvYP9AL0AvQCEAIhaoABSAD+D2gAAAl0BXYD9AF0A3YFdAUECSNqhAFEAP8PRAAADSsDqgg+B2oCKwWiDAAAKWo4A7gA/Ae4ACgAgADsB7gHqAeoB6gHAAAqaogBSAD/D0gACAj6CV8FWgX6AV8FWgX6CTFqiANIAP4PAABeCToLjg0cBUIFegtCCV4JOWoAA4gA/w/IAOAItAq+DPQGAASQAP4PEABEagAAyAD+DwgA+gOqAqoC/g94BI4DeAwACEtqkANQAP4PEAAyD7IA8gf+BfIH0QCwDyAAWGqIAUgA/g8oAIAPWgFaB0oF3gZaAMoPAABZasABKAD+ByAA2gS6BboEtQS+B9oFEAQAAF9qiANIAP8PQADmDLgDtArfCKQHuAq0CKAEYWqAAUgA/g9IAAgEuAVsA+4KvAmsB6wBOAJraogBSAD/D0gAEgjyBX8FegX6AX8FcgXyCXFqgANIAP8PAAT8A0QErAdsBwQApAj0ByAAgGoAA4gA/w/IAHgIzAv8C/4L/AvMC/wLAACQaogBSAD/DygAiA98ACcH7gX2BeQF9AcEAJRqiANIAP8PQAAaB/wF2AXeB9gF/gWIBwAAomqAAUgA/g8IANgMuAL0BBYAxAyoAugEAAipagAByAH+B2gAeAXMAfwF/gfMAfwFhAUAAKxqAAOQAP4PAAAUBtQG9gN0C3YHVANUBAAAw2qAAUgA/gcAAP4HAgT+Bf4F/gX+Bf4FEgT7aoADSAD+DwgAfgkuC/4NAAVeBS4LXgkAAARrgAFIAP4PAAD+B+4E5gPwD+YD7gz+BwAACmsIA4gA/g+IATAB1A82D4APNg9UD3QJAAAga0AIMAgMBAoCiAF4AIgBCAJIBDgICAgAACFrAAAEBoQBCAhgCB4ECgPoAAgDSAQ4BAAIImsUBCQCxAE8AwQIMAQOA+gACAMoBBgIAAAjawAE/AMUABQA8gcCADAMDgPoAAgBOAYICCdrAAD8DwQFpATUBAQNYAweB/gACAN4DAgIMmuIAMQPogSQBJIE5AewDA4D+AAIAzgEAAg6awAACAn8BVgB/AUAATAMDgPoAAgDOAwIAD1rUAhYC1QI8gdUDQAIMAQOA+gACAM4BAgIPmsABKoCqgivB6oAogIwCA4G6AEIAzgMCAhHawAB/geqBKoFqgi+BwAAHA7KAQgCOAwAAElrJAStAv4H/AOuAf0EOAwHA+QADAMEBAAATGuAALwHrAW8B4QIvAewCA4G+AEIA3gMAABQawAA/gOCBNoFqgTaBQAMEAPuAAgDKAwYAFNrIAHsD6wHuAeoB+AMYAQcA/ABEALwDAAAYWsAAboPuweAB7sHmgcwAA8O5AEEA3wMAABiawAEAATwBwAEAAQABP4HIAQgBCAEIAQAAGNrAAQEBOQHBAQEBAQE/AdEBEQERAREBAAEZGsACPAPAAgACP4HIAQAAP4HIAggCBAIEAZlayAIIAu8CKAIIAggBP4HJAIkAqQBpAAgAGZrAAAQCNQHFATUB5QEEAT+ABAHFAgUCBAGZ2sACPAHAAT+ByACCApoCKgFPgIoBegECAhpa6AAoAV8CGAIIAUgBf4EJAKkASQApAAgAWprJAikCKQOlAiUCLwIhA+UCpQKpAqkCgAIb2sQANAHHATQBZAF3gWeBbQFFAT0B/AHEAByawgM6AMoAGwL6AdoAi4JfASsA7wEqAgoBnNrEA7QAVAE3ALQD9AAXgn0DFQDdAVUCRAEdGsADPwDBAhUCHQPFAiED1QK9Ao0CtQIAAB3awAM/AMECGwI/A5sCAQPbAr8CmwKpAgAAHhrAAh8B1QE1gc8BUAAPAe8APwPvACoBwAAeWsAAIQARAgkBFQEnAIUAZQAdAAUAAQAAAB7awAAxAhkBJwGFAH0AAQA/AdECCQINAgkBnxrwAAiCJ4EEgPyAAAARABEAP4PQgBCAEAAg2sAAMIIPgSSA3IAAAj4CIgG/gGIBvgIgAiJa8AAIgieBJIDcgAQAM4HqQLoCwgI+AcAAIprgABiCB4GkgFyBBAETgPIAP4PSAFIAkAEi2uAAOIIngSSA3IAAAioBP8EaANlBVUJQASWa0AAYgxeApIBcADkDwQE/AVuBWwF/AUEBJhrgABiCF4GkgFyCAIJqAUvBxgFXQsVC6AItGsAAPwPFAXkBBQNQAzeCEIHQgb+CWAIGAi1awAAAAL8D1ICUgIRCUAI3gVCAl4FoAgYCLdrAAz+A1UJVQk9B0AA4AheB0IG/gVgCAAAumsAAFIGVAHMD1MBAAjeBEIFQgJ+BeAEGAi8awAAbAxsA+4A7AcEAmAI3gRCA14DwAQACL9rAAf/APUOpQD1AqcEAASvAqECLwHoAgAEwGsAAHwJUglAB1QFPA1ACH4JQgb+CWAIAADBawAA/ATSBMAH1AQ8AkAI/gVCAv4FYAgAAMVrAABUATQL1goUB8QCEAjOBUIC3gVQCAAAy2sAACAA4Ak8BSQDpAF8CSQJJAf8ASABAADNawAAIADwAy4CogKqAqoKIgoiDv4DIAIAAM5rAABIAMQHcwJKAsoDegpKCkoO+gNCAkAAz2vAAMgC6AOmApQDlAPUA5QKlAr0B8QCwADSayABIgHqB2oFagX/B2oFag1qDeoHIgUAAdNrEAD4B7YFlAz0BwAAtA8sAKYPJAC0ByAI1GsAAAAA/g8gBCAEAAD+B0AIIAgQCBAHAADVawAAQAF+AUgBKAGADz4BSAFIAUQBJAEAANlrAABACn4L5AdkBVQDXgDkB2QKZAlQCUAE22sAACgBKAEoASQB/AckCaQIkgiSCJAIgAbhayQBJAH8ByQJoggQCMALfgpICkgKyAkIBOtrAADEBPwF7AXsA+4H7AvsCuwKfArECgAA72skASQB/AeSCIIIKApkChAJzgkQCswKAAQPbAAAAAj8ByQEIgQiBH4AogMiBCEIIgggBhFsAAAACPwHpASkBKQE5ASkAaQGvAiACAAGE2wIAPgBCgIIAgAI/g+SCJIE8gGSBp4IAAQUbCAAGABGAFUAVABUAFQAVADUAxQEBAgABBdsAAhYCUYFVAJUAtQF1ARUANQDFAwECAAEG2wQABgJhAUjAyoJKgmqB6oAKgHqAwoMAAYibAgAqAS2Bb4FfAd8BbwFvAUcAPwDBAwABiNsEAAYCUQFIwGqDyoBKgFqDSoA6gcCCAAGJ2wQAMgCxALeAtwP3ALcAtwCHAD8BwQIAAYobAgAUAlYC1YLXAVcB1wJXAkcAPwHBAgABi5sEAiICrYEXANcAlwEXAccCPwBDAYECAAG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AAQRcBAAJA8kAIAFvAT8DrwMvA78ArwEvAmAAh9wEQSmAwAAAgATDLoDOgP4DzoBuwe6A7oPLHAQDKIDhAA2BlQB/gcmAfIEbgVqAfoFAARMcAAAIghEBgQDdA7UDzYPhA92D1QPdA8AAFFwAAAiBqwBAATqA+oH+gXiAeoD+gXqBQAEY3AQACYPQAAXAk0DoAOcA7YL+gtcBxICQABrcAAIYAgYBAACgAF+AIABAAJABDgIAAgAAG1wAAACCEIEMgQCAsIBPgDCAAIDYgISBAAEb3BACHAEAAL+ARACBAAECAQI/AcEAAQAAABwcAQChAF0AA4I5AQkAgQB9AAEAWQCJAwAAHVwAAgACaoIKgQqAqoBKgIqBCoFvggACAAAdnBwBAAO/gEAARgFAAQgBCAE/gcgBCAEIAR4cAAAQAhICigJJAQWAtQBHAIkBKAJIAhACHxweAgABv4BEAEABjAAjgCICAgJCAz4AwAAfXAACAwJ0gQABAgD1gACAwgEDAXSCAAIAAB+cAAAmAiICGgECAIKAewACAMIBMgEGAgAAH9wOAgABv4BAAMIAPAHAAQABP4HAAQABPgPiXBwCAAG/gEAAjgIAgzyA5IAkgCSAPIBAACKcHAAAAz+AwACGAgwBA4C6AEIAygEGAgAAI5wAABACCgJpAQgBBgDxgEYAiAEpAUkCEAIknBAADAO/gEAARgKQAg4BAAE/gIAApgBIACVcDgIAAb+ARACAAjoByoAKgDoBwgICAYAAKtwOAgABv4BAAMIAEgEaAbaBUgEKAcIBAAArHBwCAAE/AMgAgAA/A8kCSQJJAkkCeQJBAitcAAM7AMoCKgJqAQuBqgBKAIoBCgJrAggCK5wcAgABPwDMAYAAPgHLgkoCegLCAr4CQAEs3AYCAAG/gEAAhgA4A8UAJwBfACUCRQI9Ae4cHAIAA7+AQACKAQwAA4A+A8oASgBKAEIALlwAAAADOACoACgBr4ApAKkBKQA5AIEBAAAunAAAYgMigLKALgGrACqAqgIuArgCIAHAAC8cDgIAAb+AQgBEAR0A14I9A9EAEQDRAQAAMFweAgABv4BCAMQADwHpAAkCPQPJACiAyAEwnB4CAAG/gEAARgBAASWBJAEmASWBBAEAADIcCAJEgcOA8oAagwaAAAEfAkAAQAF/gUACM9wAAgADPwBVAFUBVQBVgVUAVQLXAlABwAA2HA4CAAG/gEQAoAIiAT+AogAiAD+AogMAAjZcCAIEA7+AQADWABID64EtASkBLQETA9AANtwQAgwBv4BEAYABPgIiAj+B4gE+AYACAAA33B4CAAO/gEQAP4PAgQiBfoEogUCBP4PAADkcPAIAAz8AwAEEAUAAagD/AqoCrgKqAYkAOZwIAQYBAAD/wAIAwAI+QQJAu8BCQT5BQAI53B4CAAG/gEAApAIhASmA7wAtA/ECKQIgATrcAAIighiChQJAAQqA1oELgSaCIoKeAgAAO1wAAAkBCQDfwAUBoAAZAA/BwQAfAKABkAI+XAAACIIIgY+ADYFNgG3AHYCdgQ+ACICAgQJcQAAEAgUBPQBVAlcA1wBXANcCVwJFAcAAApxPAQADv4BCAMAAF4BVgHWD1YBVgFeAQAAFXEgCBAO/gEQAoAI+ASWAvQBnAL0BIAIAAAZcTgEAAb/AQgDIACsB6QEpgSkBLwEpAcgABpxAAAkChQLvgQMBKQDMAIMBH4FDAUUCCAEIXEoCCgN/gElAfwNJAH8BSQJ/AEkBSAIAAAmcRAIEAz4AV4BWA1YAfwBWg1YAVgBCA0ACDBxeAgABv4BAAI4ANAPSAUGBUQEXAXEDwAANnGICKgGbgJuABQFDAGAAGgGHgBoAooOgAg8cUAIOAQAAv4BEAikBPQDpgCkD/QIpAgABExxeAgABv4BAAKQCPwK1ArWD9QK1Ar8CAAATnEECfwEXQReAVwN/AAEAHYMBQH8AQQMAABVcQAAAAj+BLIAzgK6DAAA/gQSCRIDng8ACFlx8AgADPwDIAj0CpQK/AqUDvwKlAr0CgAAXnEAABgJVgVUAVwN9AEAABwN6gjIAjgFCAlkcTgEAAb+AQABEASEBL4CrAHsB74BhAIABGdxAAj8DZQAlADsDBQAzAFEBVQJVAHMDQAIaXE4CAAG/AEQAgAI/AusCqwCrAasBvwLAAhucQAAMA40APQBdAV+AXQFdAV4AfQBEgwAAH1xAAAQDv4BEA78A6wEbADqB6oEagL6DwAAhHE8CAAG/wEIAgAM/gCqBqsIqgqqAP4GAASKcQQEfAc/ALwAvgb8AAACZwSqAIkCRAwAAI9xAAAICvoK2gLaCv4D2gr6CtkC+QoICgAAlHEYACAM/gMQBCQBlA9ECSYJRAmUDyQBAACZcQAE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t3MEAiQC/AMkAgQAgA+ABP4EiASIBIgPCAC7cwAEJAL8AyQAAAz4A8gJfgZIBsgJGAgAAMJzAAQkBPwDJAIAAPQDFAH0CQQI/AcEAAAAynMAACQE/AMEAkAI/gdCAP4H/A9CAP4PQADNcwQCJAL8AyQBEAFICCQFkgTEBEgCEAEAAOBzBAQkAvwDJAIAAFwGSAH+D0gBSAJABAAA7XMAAEQE/AdEBAAC8AgABP4DAAj8D0QIBAjycwAAJAT8AyACDACMAvQClALUD5QClAIAAv5zJAQkAvwDJAoACPwFVANUAVQPVAn8CQAEA3QAAiQC/AMkAQwDaAIICP4HiAAKA2oEAAQFdAQCJAL8ASQBAAD8D1QEVgTUAVQDvASABAZ0AAQkAvwDJAIACXwIVAnUD/wPVAlUCXwJCXQABCQC/AMkAgAItAcsAKYPJAC0ByQIAAAQdAAEJAL8AyQCAAj0CRQEEALeARAEFAj0CyJ0AAQkAvwDJAKAANQC1Am8CMQHZACUAwAEJnQAAiQC/AEkAQAAtAe0AqwDLgj0DzQAAAAqdAAEJAL8AyQCAAgIBf4FWAFYAf4FCAUACDN0AAAkAvwBIAOIAP4PSAAAA8gA/g9IAIgDNHQAAFoAWgFeAXoBWgFYAXoFXgNaAVoAkAA8dAAIRAT8B0QGAADoBqgArA+oAKgB6AMIBEt0AAAkBPwDJAIAAPQHvAW2BbQPvAXwBQAFW3QAAiQC/AEgAQQE9gSUApAB8ACUApYC9ARcdAAAJAT8AwQI8Ae4AvQPFgDWAwQIyAcQAF50AAQkAvwDJAIAADwAsA+wB/4AsA+wALwPX3QAAJQOVAh8BFQGlApACVQJvARUAVQGAABqdAQCJAL8ASQBAAz+AKoGqgD+BqoBgg8AAHB0AAQkAvwDJAIACHwEVALUAf4HVghUC3wLg3QAAiQE/AMkAgQAdA9kA9YFZANECXQPAACHdAAAJAT8AwAM+gMqCMAHFgcqBOgPKAloCYt0AAAkAvwBJAAAAvQC9AL2D/QC9AL0AhACnnQAAiQC/AMgAQoEaAV+A+gBbgVoBW4JAACndIAAfAh0C7QLtAv8CwAPVAt2D1QLVAkAALB0AAIkAvwBJAUABP4Evge6Ab4CugJ+BRAFynQABCQE/AcgAggM/A/+B+wH7AfoC+gLAAjcdAAIAAb8AQQABAb8BQIEggc+CMIDAAwAAOJ0AAB0DfwB/A90AQAO/AEEBvwFBAL6DwAA43QEAE0N5gMADfwH/AsCCP4HWAHnD1QBAADkdAAE/AX+D/QJ7AHwDfwDBA78BQQG+gsADOZ0AAAEBAQO5AkcCNQEFAUUAPQHBAgECAQG7nQAAFgISA7kB3IHaAdiB2oBcg9kCEgISATvdAAA/AcEBbQE5AQQAQIM/guSAPIPAggABvZ0AACIDPoDiAD+D4oAAAj8D5QA9A8ECAQE93QAAEIIVAzAC2gJZAtWAUwBVA9kCGAEAAAEdQAAfAl8BVwHbAU8AIAPfAiUAPQPBAgABhh1AAAIAAgA/g+IBIgEiASIBP4PCAAIAAAAGnUAAAQBBA/+CVQJVAtUCVQL/gsECQQJAAAcdQAAkg+SBP4EkgcAAP4PiASIBIgE/g8IAB91AAAgCJAIjgiICIgI/g+ICIgIiAiICAAIInUADOQDJAm0CrwKrgqsD7wKtAqkCiQIAAAjdQAM5AMkCLwKpAqkCqYPtAqsCqQKIAggACV1AAArAiQC/wEkAQAIvgbqAb4EqgS+AwAAKHUAAAAM/AMkASQBJAH8DyQBJAkkCfwHAAApdQAAAAz+A5IAkgD+B5IIkgiSCpIK/gkABCt1AAAIAOgPqAKoAqgC/A+oAqwK7AcIAAAAMHUAAPwPRAREBEQE/AdEBEQERAREBPwPAAAxdQAA+A+IBIgEiAT+B4gEiASIBIgE+A8AADJ1AAAAAPwBlACUAJQA/A+UAJQAlAD8AQAAM3UAAPwDJAEkASQB/w8kASQBJAEkAfwDAAA1dQAAAAD8AyQBJAH/ByQJJAkkCfwJAAgABjd1AAAACXwJVAVUA/wBVAlUCVQJfAkABwAAOHVAACAA+AeuAqgC6AOoAugLCAgIDPgDAAA6dQAA/gciAv4DIgL+AwAACAgICPgHCAAIADt1AAD0DwQE9AVUBVQF/AVUBVQF9AUEBPQPRXUAAPgB/g+uD3gAIgnyBDoC5gkiDOADAABMdQAAAAG+CKoEagI+ACoAag+qAL4AAAEAAE91AACACPwP1AjUCPwI1APUBNQG/AiACAAAUXV4CAAG/AEABhAA/A9EBEQE/AdEBEQE/A9UdQAA/AckAvwDJAL8A4AAqAD+D6AArACAAFl1AAA8AKQPogqSCqIKgA+8CoQKRA88AAAAXHUAAEQA1A/UCvwK1g/UCsQKpAqkDyQAAABidQAAoACuAu4CrgLuB64CrgLuAq4CgAAAAGV1AAD8B/wDJAL8A5AAiA/WCKQI3AjED0AAZnUAAPwH/AMkAvwDAAgoCSgJvg8oCSgJAAhqdZAAlADcB7QFlAW8B5QFsgXaBdoHkABAAGt1SAB8BPwH/Af8B/4H/Af8B/wH/AdIBAAAcHUAAAAKvArsB6wGvAKsAqwG7Ae8CgAKAAB0dQAA/AckAvwHdAasA/QDXg1UDVQJVAcAAXZ1AAA4AAoP7AuoC64LqA+oC+wLCg84AAAAeHX8ByQC/AMkAvwDIAC0A7QCrgs0CPQHIAB/dUAA5gdZBdQHWAX/D+AEdgN5B7QIUghABoZ1AAB0BVQPXAzABwQA/A/0DvwP9A78D0QIinUAAPAJ/gj+D/4P/g+uD/4P/g/+CPAJAACOdQAE5AcEBPQDTAIECPQElAL+D5QC9AwAAI91AATEA/QDTAIACKQHPACmDywAPA9kCEQEkXUACW4JVAXUA1IBCA2iAyoE6g82CWIJIAiXdTgJgAT8AwQAJAAkCCcIpA9kAGQAJAAAAJl1MAkABfgDCABIBCgKrAmoCagIqAgoBAAAmnUYCYAM/AMECMQINAQmAqQBZAIEBAQIAACfdZgIgAb8AQQAhAD0B5UElgSUBJQElASEAKR1mASAAvwBBAD0A5QE9gSUBJQE9AQEAgAAq3WICLAO/AEECEQItAWWBpQG9AXECEQIAACudYwIQAb+AWIAIgDyBysIKwkqCfIIEgYiAK91OAGADPwDBAz0AxQAlgLUAxQA9AcECAQEsnWYAIAO/AEEDvQBVATWBXQCVAWUBDQIAAC5dbgIgAb8AUQAJAqUClYJFAWkBCQCRAEAALx1GAmADPwDBAAkBbQE1gjUCrQKlAAEAQAAvnWYCKAO/AEECIQEtASmAuQBpAKkBKQIAATFdZgIgAb8AQQA1A9UAFYD9ABUA1QI1A8AAMd1mASABvwBBATUBxQEFgT0B5QElASUBAAAynWYBIAG/AEEBCQFFAVWBdQHVAUUBSQFJATSdYgIkAb8AQQApAK0AqYC5A+kArQCpAIEANV1mAiABvwBBAD8D6wErgSsAawGfAUECQAA2HU4CYAE/AMECNQJVAtWCVQJVA3UCRQIAADbdZgIgA78AQQA7A+8Ar4C7A+8AqwK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JALkA3wA1AF+AVQB1Ad8AQABl3iEAPQHLATgB8QANAykA0YA9AcUCPQJAASYeEIA+gcWAvIBAAT8DKQC/wCkAP8CpAT8AJ94hAD0D0wEwAcIAHwNSAP8D2gDfAVICQAAp3gAAMoE6gL+D+oKgAr8CtQK1grUDvwAAACpeAAAhAD8ByQC5AsACPwHrAKsAqwG/A8ACLB4hAD8DyQE4AeIAA4J/A8ICPwPCgjICQAAsXgEAdQPLATEC/AHCACoDwgHfgKIBWoIAAazeIQA/AckAuQDAAisB2gALg2oAygErAkgALR4hAD0DywE5AcAAKgL2ArcCtgKqAsoCAAAuniEAPQPTATEB0wA5A9cCVYJ9A9UCVQJTAm8eAAAggD+ByICwAd+A6oEqgD+BqoBgg8AAL54wgD6ByYC4gEABP4DigjqB6oB6gKuBAAAwXiEAfwPJATkAwwIaA+OCOgOSAioD84IKA7FeEQA9AdMBMQHAAB0CFwG3AF2CVQJVAcAAMp4AABSAtIHegVuBWoHagLqB2oFegVCB0AA0HhQBVAFPANUDxYLfAsIC2YLUgu+D5gBgAHVeAAARAD0DywE4APID/wPzgjMD+wIyA8ACNp4hAH0DywEJATEB/wC3AbcDv4K3A/8AgQD6HgADvwBBAS0BLQOtAuWCoQKtAq0CrQOlAD0eEQA9A8sBMQHIACaCdoP1gjWDJoKIAgAAPd4QgD6BxYC8gOACHYHzAFfAMwB9QdUAQAA+ngAAIIA/gcSAuADSgjvBOoC+gDvAuoCAAwBeQAAQgD6BxYC4gEIDP8ArAb9AKwGLAAABw55hAD8ByQCxAsUCEwEXgfQD0wJXglUCRAIGXkAAAQB/APkCw4IVAfUAUAIDAfsDywJZAA6eQAAIAQkAqQBJAgkCOQPJAAkAKQBJAIgBDx5AACIAYoA7g9YAIgBAAD+BwAIAAgACAAGPnkAAAgBiADOD7gACAkgCCAI/g8gCCAIIAhBeQAAiABKAOwPWACIAAAA/A8EAHQCjAEAAEJ5AAGIAMoPeACIACAA/AcgCP4JEAj4CAAGSHkIAYgAzg94AIgJAAT8AyQAIgDiDyIAIABJeQgBiADuD1gAiAgACPAPAAj+DyAIIAgACFB5iACIAO4PWAAIAYAA+A9OBEgESATIDwAAVXmIAIgAzg98AAgI4AwAAvIHxAgwCGwGgABWeQgBiADKD7gAAAj8DyQJJAkkCSQJ/A8ACF15iAFIAO4PWACACDwEJAPkACQA5A88CAAGXnmIAYgA7g9cAIAA+AMoASgB/g8oAfgBAABfeQAAgASWBLQCtAC+B7QAtAK0ApYEgAQAAGB5gABJAOsHWACCAOoDKgEqAeoJAgj+BwAAZXkIAYgAzg94AAgAQAFKAUoB+A9KAUoBCAFoeQQJdAXUBdQB/AnUCdQH/AHUBdQFdA0ECW15EAAQAZgIbgRMAXQJSAlGD1gBZANUA4wMd3kIAYgAyg+4AAAEVALUAX4DVAlUD0QBAAB4eQgBigDqD5gAAADcD1QB9ABUC1QI3A8AAHp5CAGIAOoPWABACAgJ/gVYAVgB/gUICQAAgHkAAAQK/AuMA/wL3AveD/wDjAf8BwQKAACBeQAAFAlMBV4BTAlECVAPTAFeBQwFNAkgAIR5iACIAM4PfAAIAEIEKgIqCeoHKgG+AqAEhXmEAEQA5g9cAAQB8AGqAfgHrAGqAfgBAACNeYAAiADsDxgAwA98AMQH9ALUA1QI/AcAAI95iABIAO4HWACCAPoPagVqBeoHagV6BcIHpnkAACQFswWABesB/gHaB4ABvgOCAz4FAAWneQABigDqD5AABAB8D9wLXgtcC9wLfA8EAap5xAAkAPUPLQBAAv8CrQL/D6oCrQL/AgACrnmIAUoA6g+YAAAI/gv/CuoK/wrqCv4LAAixeQABigDqD5AAxA/8BfwH/gb8AvwP3AIAALl5AACED7wArASsBPwHrASsAqwKugiCBwAAunkAAIAP/ADUAtQC/APUAtQC1Aj8CIAPAAC7eQQABA90AWQFZAfWBVQFVANECXQJBAcEAL15EAAID+gBxAGUBbIHugWyB4QJ6A8IAAAAvnkgBCQCJAGkAGQA/A9iAKIAIgEiAiAEAAC/eQAAkAhUCFQENAN8ADQANAdSCFIIkASAAMB5iAhMCCwEnAOMALwAigqaCSoJSgdIAAAAwXkAApIBUgD+D1IAUgQAB/gEBgTABAAPAAjDeQAAUAhUCFQENAO8AJQANAdSCFQIUAYAAMZ5AAAYA5gA/A+UAAABRABEAPwPRABEAEAAyXkAACgEugS6AroBugH+D7oBugL5AigEAADLeQAAkgNSAP4PUgAACDgEgAN+AIADMAQICM15lANSAP4PUgACAPgBiACIAP4PiACIAPgB0XkAAJQDUgD+D1IAEAFCAUwBAAH+DwABAAHSeQAAlAFSAP4PEgCACDgEgAR+AgAB2AAAANV5EgOSAP4PUgAAAP4PIAQAAP4HIAgQCAgG2HkSA5IA/g9SAIAJYAT6B4IIYAgeCOAGAADfeRQDlAD8D1QAlAkACPwPJAkkCfwPAAgAAOR5AAAUA5QA/A+QAIQAtACEAPwPhAC0AIQA5nkgAawIbASsA7wDrg9sASwDbASsCCABAADneQAAFAOUAPwPkgAACPgIiAb+AYgG+AiACOl5lANUAPwPUgCSCBAETgJIAf4ASANIBEAI63mSA1IA/g9SAJICAAaQAXAA/g9QAJYBEAbveQAAlANUAPwPUgAACHwGRAFEAEQBfA4ACPB5kgNSAP4PUgCSAhACzwEECPwPBADsAQQC+HkUA5QA/A+SABoASA9ICUgJfglICUgPCAD7eQAAlAFUAPwPUgACCagErARWBXQCzAFAAP15FAOUAP4PUwAACZ4JUAhwBV8GUALQAV4AAHoQA5IA/g8SAAAB6gesALwApA+sAKoEqAMFehIDkgD+D0IACAj0BJIDkACSD+QICAgQBAt6AAAYA5gA/A8AATwIpAqkCqQPpAq8CgAIDXqSAVIA/g9SAAAA8gdUAVABXgFQBfYHAAAOegAAlANSAP4PAgA4DMoDSADMD04IeggABhp6AACUAVQA/A9SABAA/g+oBPwHqgSoBAAAIHoYA5gA+A+UAAAM/AMEANQH9ALUCwQI/AcjehAA+AVWBfQFXAX0BiAHpAD8D6QAIgcAAC56AADKASoA/wMACP4Krgr+D64K/QoACAAAMXoUA5IA/g+SAAAC6A+kAqQC6gOiCroK4gcyehQDkgD+D1IAEgDADxIAwg9aBUIF2g8AADN6JAIkAfwPogAABlgAVgVWC1QJXAHwBQAIN3qUA1QA/A9SAAAJfgmWBdYGvgZWBVYIXgA7eooBSgD+D0kAAADKB6oEgQQtBKEE7QcAADx6FAOUAPwPUgBABVwFtAJ2CbQG1ABcA0AEPXoUA5IA/geSABAAdAesB64HtAe2B5YHVAA/eooDSgD+D0kAgA9eAFYPVgVXB14Awg8CAEJ6FAOSAP4PUgCABnwArAysCf4KrAKsBvwIRnoSA5IA/g9SAIAIvAwsBSwF7gYsArwCgABMehAM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fXwsA6AA/g+gAAwBQABECEQI9A9MAEQAQACJfCwDoAD+D6AALAlgBFgGxAFACEYImAcgAJJ8LAYgAf4PoAAsAQAIaAiICw4IiA9oCAgIl3wIACAD/A+gACwBAAj8DyQJJAkkCfwPAAiYfAAALgOgAP4PJACAD4AE/gSIBIgEiA8AAJ58jAMgAP4PhAH8DxQE/AUUBPwEFAX0DwAAn3wECXQF1AXUBXwDVA9UAXwDVAVUBXQFBAmkfAAAgAD8AMQD1gLWAtQK9ArEDvwCgAAAAKV8AADyCJIIngc8A/4PKAAEA3AIkgieBwAAp3wsB6AA/g+oAAAM+AMICEgI7g9ICEgIAACqfAAAKAqoCqoKnAu+AogCmAacB6oKqAooCq58JgegAP4PoAAuAQAA/A9UBNYAVAN8BAAEsXxkCREFQQWMAyABkg8uAUIDwgV+BQwFMAm5fAMA0AH/D1AAkwGAALoAggDjB5oAkgCiAL18AAa4Af4PIAAIAwQIpAanAKQPpACMAoAMvnwCACwH4AC+DwAA1A/cAtwC3grcCtwPFADKfAwAIAP+DywAgA9+BMgDAAz+A5II/gcAANV8BgCgA/4P6AAACKgGqgCsDvgArAyqAIgO1nwGANgA/wNYABAP/AB0A/QC9gL0AvQDIADZfAwAoAH+D6gAJAlABNwHAAisC7wKqAqoC9x8AA78AQQIHAW8BS4Dhg8cA7wDHAUsBQAA33wGAKAB/g+MADoA1g//CtYK/wrWCv4PAADgfAMAkAH/D8IC/wEBAlUB/wfXAz0BkQKBAud8qAH+D6AAKAjgC/wL/Av8D/wL/AvcCwAI73wDANAA/w/eAY0HvQClB+8ApQetAL0HAAD4fIAEhASYA5QB4wDQD0gARAF0AUACgAQAAPt8AAAABJQE1ALcCLQIlA9SAEoBQgKCBIAE/nwAAJAO3ACyDIgCAAD8AwABAAEAAf4PAAAAfQAASAd8ANIPSAEAAOQHJAgkCCQIfAgABgR9SAd+ANAPTAAAAxAATgCICQgICAz4AwAABX0AAEgHdgDQD0wA4AoECAQI/A8ECAQIAAgKfQAAFAhUBVQFfAH0CVYPVAEcBZQJJAokAAt9SAduANAPTADgCggIOATIAg4DyAQ4BAgIDX1IB24A0A9MAAAB+A8IAcgAPgDICPgHAAAQfRAOnADyDsgAgAIECEQM/AtECPwPQAgAABR9SAduANAPTAEAAOgDCAEIAf4HBAnkCQAEGX1IB3YA0A9MAGQBAAT+ByIE/gEiBiEMAAAafUgHWAD2D2AAQAsEB/wAhAQkBTwD4AQgCBt9SAd2ANAPTAAAC3AITgbAAUIITgjQByAAIH0gACoJagVqA+oL/wlqByoBqgWqCSALIAghfUgHfgDQD0wAxAoACAgH+AAuCCgI6AcIACJ9AAA0CBQFVAX0AV4JVA80AbQFFAU0CQAAJ30ACB4JgAXeAcAJogmSD14BUgUeBSIJIAArfRAJHAlQBV4FtAGQD04BFAWUBRIJCAoAAC99AAAACD4FagXqAX4Jag8qAaoFPgUACAAIMH1IB3YA0A9MAcAA/A9EBEQE/AdEBEQE/A85fUgHbgDQD0wAAAMgAKIPngSCBKIEng8AAEJ9SAduANAPTACAAogATgQ1BTQFTAlAAAAAQ30QDtwAsgZIAEAHSABoBloFzAQoBggMAABEfUgHbgDQD0wAAAMACPwPJAkkCSQJ/A8ACEx9SAduANAPTAAAA0IIJgkqCZIPKgkmCUAIUH1IB24A0A9MAKADBACkD6QEvwSkBKQPJABVfbAN7ACiBJgCAAD0BzQJLAnkCTQJLAngBV59SAd4ANYPUAAACygImAQYA84DCAQoCCgAYX1IB24A0A/MAMQDkADID9YEpATcBEQPgABmfUgHbgDQD2wBIACQD4wEogSkBIgEkA8gAG59AAAsCCwFlgHUCcwJgA9eAVIFEgUeCQAAcX1ID3YA0Q9MAAAJBAS8AycALAC8DwQIAARyfQAAkA78AJIGSAIAAFgDdgjQD0wA4AIABHV9SAd2ANAPTAAACxAIiAamBaQEiAawDBAAdn1IB24A0A9MAQAA+AeWCJYI/AicCJQI8AaTfZAMvAHiDNgAAAo6CEIJEgnqD4IJPglGCJl9QAduANAPTAAAAf4PAASoBP4FoAQsBQAEmn0AAEgHfgDQD6wDgAlUBFQDXgBUBtQIBAScfTAO7ACiDJgCAACMDKQCpwCkD6QArAKADKB9MA7sAKICmAQABNoCVAjUD3QATAKABAAArX1IB24A0A9MAEADEAD+D6gE/AeqBKgEAACxfU4HcADsD0AB/A/sA+QDJAKsCyQI/AcAALJ9SAd4ANYPgAL8DwwAvAPkBLQEBAD8DwAAv31IB24A0A9sAQAAvgeqAKoA6w+qAL4EgAPKfQABPgUuBb4F7gGuB6IBWgMaAyYFQgUAAM99SAd2ANAPTAAAAV4EQAD8D2QJcQhGA4gE0X1IB24A0A9MAAAFIASqAioI6gc+AaAGAADSfUgDdgDQD0wA4AOEAJQHfgVUBVwF1gcQANp9SAduANAPzADABZwCrAksCO4PLAO8BAAE4H1IB3gA1g9IAQgAoAeUAJwA1g+cALQHAADjfSAIvAziAtgCgAQgBH4DtAq0B7wBIAYAAOh9SAduANAPTAAAD/wHrAKsD6wCrA+8AoQP6X1IB24A0A9MAEAJFARcA/QJ1AbSBtwFVAjvfUgHWAD2D2ACAAT0BbwHtgW0D7wF8AUABPR9SAd4ANYPSAAAAvwErAKsAf4PrAH8AgQE+32QDtwAsgTAAZwE1AeUBAQA8AwOA/gEAAgBfkgHXgDwD2wAgAIgBGoDqgpqB74AIAcAAAR+RANfAOgPJgAAAfwHvAK8AvwHvAq8CvwNI35AAnwBfAD8B/wASAIYAXwE1ANUANACgAAmfkgHbgDQD8wAQAL2D5gHFgTwD5YIEAgAACt+EA7eAHEEbAMBCHYG4AksCLsK+wsmCgAILn5AB34A0A9MAUAA7A8EANYHdAVUBdQHAAAxfhAO3gCxDMwCAAD3DwAEzgMBBOgHhgiYCD1+kA7cALIMiAIADPwChAaWCaQLhAD8BgAAPn5IB24A0A9MAAAK/Aj8Bf4F/AH8BfwJEAhBfgAIMAq+CjwL/AM8D4gCXgZkB1wKhAoAAEp+QAdOAPAP7AHAB/QHHgT0A5AG/geQDBYCVH6gAy4A8Ae8ABAA/Ae2AtgPPwPQBBYOAABefpAO3ACyBIgCAAiqCeoHrwEKD+oJqgmABWp+AAd4AJQGUgEIADQH8gX6BdIF9AX0BwQAa34AAH4Kfgd/B/4PfgsYB/YC0gp+CpgKgAhwfkgHbgDQD0wBAATwAt4B+gfqAdYC8AQAAHN+kA7cALICCAk+DOsD6wm+BzQMiwN4DAAAfH4QDtwAsgZIAv4PNAi6DzgJPgisDxALAAiMfpgO9gCRBkgBEgjuB/4H7wP+A+4H+gcACI9+gA7cAKIGWAEADPwD9An+C/4O/Av8C4QJln5QB3wAagIACXYE9QcQBPYPMAT+B9AMFgKgfqAEsAVsBSIFkAQAAPwBAAEAAQAB/g8AAKJ+AAAwCewEogSYBgAABAQEBPwHBAQEBAQEpH4AADAJqAVmBRAFQABEAEQA/A9EAEIAQACmfqAEuAXkBJIEgAIwAI4AiAgICQgM+AMAAKd+IAW4BeYEkAIQDIQDfAiEBTQCrAVgCAAIqn4AACAFuAVmBRAFAADEB0QIRAhECPwIAAarfgAAMAXoBaYEkAIACHQEBAP8CAQM/AMAAKx+IAW4BWYFEAQAAqgAqAD+D6gAqASIAwAAr34gBbgFZwUQBQAE9AEEAQQB/wcECfQNBASxfgAAMAXoBaYEkAIACHgIAAT+BAACmAEgALJ+AACYBdcEsQQAAP4PAgCyAdoBAgj+DwAAs34AADAFzgUiBQAA8A8QA/AAnggQCPAPAAC1fgAAMAXsBaIEkAAADv4BAAwAA/4AAAcACLd+AAAgBbgFZgUAAWAIWATEA0AIRgjYB2AAuH4gBbgFZgUwBQAA/A9ECEQE/AFEBkIIQAa5fgAAMAXsBKICmAoACDgEygIOA+gEGAQICLp+AAAwBawFYgUYAQAICAf4AE4ISAjIBwgAvX4AADAJrAVjBRgBAghCDP4LQghCDv4JAAi/fgAAuAXkBJICgAoQCFAEfgTIAyoFqggABMN+uATkBLICAABUBnwBVgj0D0QARAEEBgAAxH4AACAFuAVmBRABAAj8DyQJJAn8DwAIAADFfgAAIAm4BWYFAAD4AygBKAH+DygB+AEAAMZ+IAWwBW4FIgUAAPwPRAREBPwHRAT8DwAAx34gBbgE5gSQAgAIfAZEAUQARABEAXwOAAjIfgAAMAXoBaYEkAQQAEgCVgQkBVQFTAiAAMp+MAqsCWIJEAUAACwBIAH+DyABLAEiAQAAzX4wBZwE8gKIAiAAog+aBIYEogSiBJ4HAADOfiAF+AWmBJAEBACsAqwClA+0AqwCpAIAAM9+IA24BeYEkAAACKQIpAiUD6wIpAggCAAA0X4AADgL5gmQAQAIKA3+AwAA/A8EAHwChAHSfiAAmATkArICCABABugBCAh+BIgHaggIBtN+MAXsBKICmAIAAKQHpASkBL8EpASkBwAA1X4gBbwE4gSYAgAIpASmA7wAtA/ECKQIAATYfjAF7AWiBIACIAiQDqwJpgSIBpAEoAgAANl+IAW4BOYCgAIgAKAPsA+uBKgEsA8gAEAA234gBLgFZgUSAkAAqAKoAq4ClA+sAqQCIALcfgAAMAXsBKICkAIQAEgPtgSkBLQETA9AAN1+IAWcBOIEmAQAAPgHlgiWCPQInAjwCAAG3n4gCbgFZgUQAUAIOAiYBQoCyAUoCEgIAADffiAFuAVmBZIEEAJACGgHXgBID2gISAhIBuJ+AAAgCbgFZAUAAOAPvAK0ArQKtAr8DwAA434wBawE4gSYAgAIrAScA4wAvACaCSoHAADlfjAF6ASmAqACCAhEBeQGagLCBVoMQAQAAOd+IAC4BeYEsAIAAPgHBASgBP4FYASsBQAA6X4wBZwE8gKYCgAI3AVcBF4DXABcBNwJEADqfgAAmAT2ApICAAJUANQHfgVUBVwF1AcSAO1+IAW4BOYEkAIAALQIFAUeA9QBFAVwBRAI7n4AALAF7ASiBDgAoAe0AqwCrgs0CNQHNADwfiAFnATiBJgCAAD4AqgCqAKuD6wC/AIAAvN+AACwBWwFIgUAAPwDtAL0B7QKtAr8CwAA9H6wBOwEogKYAiAA/A+qBKgE+geoBKgEAAD1fiAAmAXWBLECAAC+B6oA6w+qAKoEvgMAAPd+IAX8BbIEAAz+A5II/gcADP4Dkgj+BwAA+H4AALAF7ASiAgAI/AcEANQH9AIECfwHAAD8fgAAIAW4BWYFAAUYAIgCqgisD6gAqAKABP1+AAAwBegFJAUAASgMqAMoBO4PKAkoCQAA/34AALgFZAUSBYgAQAQqAioJ6gcqAb4CoAQAfwAAOAqkC3MJAAyqCJoGBAmgCZIGnguiCAV/AAC8BeIEmQIIAOIHEgTyB14F8gfyBwAABn8AANgCTgJ5AQAE7wQ/AqABKAMmBOwFBAQOfwAAOAXmBJEAAAL8D1ICAAjeBUIC/gVgCBN/IAW8BOMEmALADFQC8gnWBtEG3QVVCAAIFH8QBawFYgUYBQAAtAecANYPnACUBLQDAAAVfwAAOAXkBLIECAKgCKoLmAbeBJgHmgSoCBZ/AAC4AuQCkgAABvwBlAfWA9QHVAHcBwAAGH8gBLwFYwUZAAAFbAVrBaoKqge+ASAGIAQZf5AE3AKjApgCAgDqD2IFfgV+BWIF6g8gABp/IAWwBG4FIAUAAHgBeAV8AXgJ/A/4AQABHX8AANwFswSIACII4AcECK8K6guuCqIKAAggfwAAOAXkBRIBAAz8A3QIrgr+D6wK/AoACCR/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SANABAAA/A8EAPwDK4EADP4Dkgn+BwgA9AySA5AAkg/8CBAIAAQvgQAM/gOSCP4HAADoD6gCqAL8D6gCrgroBzGBAAz+A5II/gcAAHgESgfMAMwPSgh5CAAGM4EADP4Dkgj+BwAA7g8ABEEFzgQABO4PAAA4gQAM/AMkCfwPIASQBSgEpgQoBxAHoAQAAD6BAAz+A5II/gcAAPwB1AFUAX4HVAFUAXwBSoEADP4Dkgj+BwAAFADeB1QFVAVeBdQHAABLgQAM/gOSCP4PAAD0DwQA5gxUA5QFdAgACEyBAAj+B5IA/g8AAOgDuALsB6gK+AsoCAAEUIHADzwApA+kALQGhAWmBZQF1Aj0CJQPBABUgQAM/gOSCP4HAACkCJQIhg+UCKQILAgAAFWBAAz+A5II/geAAEwItAdGAPQHFAj0CQAEZYEADP4Dkgj+BwAB/gjqCqoKqg+qCr4KgAhmgQAM/wPJAP8HAADvDyAEtwQoBSIE7QcAAG6BAAz+A5II/gcABHwDVABUB/wIVAhUAXwHcIEADP4Dkgj+B5IAqgf+BqoEvgOqBLoIAABzgQAI/geyAP4PgAD8D6AExA/4BwQA/AMAAHiBAAz+AxII/gcAAP4G6gHqBOoD/gjABwAAeYEADP4Dkgj+BwAAfAXuBewC7AX8BAAEAAB6gQAM/gOSCP4HAAC8AqwJLAjuDywDvAQABHuBAAz+A5II/geAAXgOeAD4BQgI/gMIDAoGfoEACP4HkgH+D4AB6gS4Bq4GqApqC6kGgAB/gQAM/gOSCP4PAAjuBwAI/AtUCNQJ/AoACICBAAz+A5II/gcAAFQO1AFUCVYJVAlUBwAAioEADP4Dkgj+BwAAeAV4BXgBfAl4D3wBeAGPgQAAZAA8D/wHvAe+B7wHvA/8DwwPZAAAAJiBAAz+A5II/gckAdQF/AHUD/wB1AX0BQAAmoEADPgDCAD4CPgH/gP8B/wH/A3cDxgAAACbgQAM/gMCCP4HEADKBagFrgeoBcoFGgUAAJyBAAz+A5II/gcAAHQFdgf0AXYDdAV0BQAJnYEADP4Dkgj+B4AAVAVMAj4PTAJMBVQEAACggQAM/gO2CP4HAABUCqIKvgpABVQFAgI+AKiBAAj+B5IA/g9AALQGvgR0BQAATAwiAwABs4EACP4HkgD+DwAAVA9WC/wLVAvWC1QPAAG9gQAM/gOiCP4HEAD4B5YItA+cD7QP0A/AAMCB8AAOAPoPugP6A74DgAP2C9ILPgdYAEAAwoFAADwA/A/cA9wD/AOwA7wL9gu8BzQAEADJgQAM/gOiCP4HAADwB7gF9wBVDKQC6AwAAMqBAAz+A5II/gfgAN4G+gH6B+oH1gHwAgAE04EADP4Dkgj+D+QH/g90B/QFHgD8BJwHWAzjgQAA/geSBJIEkgSSBJ4HkgSSBPIEAgQAAOWBAAD8B6QEpAS8B+QEAAyAA3wAgAEABgAI6IEAAPwPlAScB5QEcAuYBKYHVA/UBPQPBADqgQAAAAD8DyQJJAknCSQJJAkkCfwPAAAAAO2BAAAACXwFXAVcA14BXAFcA1wFfAUACQAE84EECKQItAisCKQIpA+kCKQIlAikCAQIAAD0gQAAvASkBJQHlAS0AiAIfgSIA+gCGAQICPqBhAn8DdwP3A3cDd4P3A/cD9wP/A2ECQAA/IEAAPwPRARCBEIEAAREBEQERAREBPwPAAAAggAA1A9UBUQFRAUUBCQFAgViBXoFyg8AAAWCAAAcBfwF/AX6A/AB/AH8BfwF/AX8AwAABoIAAAAJ/AVSBQAFXgF0AVQFAAXUBTwJAAAHggAAAAn8BVQFAAU+AXQBAAVUBdQFPAkAAAiCAAAACfwFBAX8BSwBXAEkAfwFQAX8CQAJCYIAAMAAfAJaAsAC7gfcAsgCXAL8AsAAAAAKggAAJAD0B/QH9gfwBvAG9gf0B/QHlAcAAAyCAAAKAMoPSgRKBH4ESgRJBEkEyQcIAAAADYIQAFAAUAdYBVQF8gVUBVQFWAVQB1AAEAAOghAAUABID0QJUgl6CVIJVAlYCUgPUAAQABKCEABID0QF8wVEBQgHYABqCPIPLgDiAAAAFIIAAJIP/gSSBNAP1AE0CJwPFAA0AlQAUAMXghAASA9WBXwFWAcQAMAPqAL+D6gC6g8AABiCEABYD1QF8gVEDwwA9A9WBVQFdAUcDwAAHIIACbAIUgVWAtIBFgDSA1IC2Q9VAlACAAAeghgJWAn+BtQC/AHUAPwD1AK8B9QCkAIAAB+CQAhABvwBRABMAU4BVQJECEQI/A9AAEAAKoJADPwDRwBVCfwHAADoDygALgDoDwgEAAAsgkAM/ANOAEUN/AMACN4IQgVCBs4FUAgAADCCAABADPgD1Aj4DwAAfg4CAfoHAgj+CAAGMYJADPwD1gBECPwHEADoBycIJQnoCDAGAAA1gkAM/APWAEUI/AcAAOgHigiMCEgIWAgABjaCQAjAB3wAVgn8BwAA+A+IBI4EiAT4DwAAN4JADPwDVwFFDPwDAAhoBFgHzgRoBCgHCAg5gkAM/ANEAFcJ/AcAALgPhgSABI4EsAcgAEeCQAz4A14BSgj4D7QH7AQACCQK/AsiCgACWIJADPwDzwhFCPwHAAC+CKAH/wSgBrwFgAhmgkAP/gBbB/4BAAT/B9UE9wfcBI8HpASkB2+CAAAACPwHVARUBNYEVAFUAlQFfAWACAAAcIIUBCQCxAF8BgAA/g9SCNIIUgFSBn4FAAlygiAAEAD4B5QIlgiUCPQInAiQCPAJAAQAAHOCAAAoASgB/g8oAQgA+AeWCPQInAjwCAAGeoIAAAQAJAQuCiQJpAikCGQILghECAQGAAB+ggQIBAgkBM4EBAMEAgQDzgQkBAQIBAgAAIKCBAAkACQALgDkDyQAJAAkAi4C5AEEAAAAi4KEAJQAlACWCJQIlAj0B5YAlACUAIQAAACNgoQARAA0ALYAJAEkAiQIJAguCCQM5AMAAJKCBABEAMQHTgREBFQEZAREBE4ERAREBAQAl4IECAQJRApmCdQFVAdEAg4DxABEAAQAAACZgoQIpAikBK4EpAL0AaQBpAKuBKQEpAiECJyCggiSCJIIlwSSApIB8geSCJcIkgiSBIIAnYIECEQERAJeBEQMdApECkQJ3ghECEQIBAilgkQARAgkBK4DJAAUABQAJACuDyQARABEAKaCAAgEBvQBVgFUAVQBVAFWAUwBzAMEAAAArIKEAEQIxAiuBKQDhACECKQILgdEAIQABACtggAABAD0B5YIlAjwCJQIlAiWCJQI9AgEBq6CAgDiDyIALwIiAbIAcACiAC8LIgjiDwIAr4IIBIgDCACcBwgIKAhICIgIHAaIAAgHCACxggAABAGEAOQPDgAEAeQHjghECEQIJAgABrOCJAgkBCQGLgHkALQIpAikCK4IpAckACQAt4IACAQIxA8OCAQIBAjwD4QIjgiECAQIAAC4goQApAikCK4PpAykDKQMpAyuDKQGpAiECLmCBAgEBPQDlgCUAJQAkACUD5YAjACMAAAAvYIECJQE1ASWApQClAmUCZQI9geUAJQAhADHggQAFAFUAVYB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5APWD/AL6AvwC9QL9gvkDyQAIAC/hAQAFACUD/YA9Af0BfQF9Af2AJQIlAcEAMSEkACUALQH1gfUB9QH9Af0B9YH1AbUAJAAyYQAADQCFAFWD5QJVAlUCVQJlglUD1QDAAHLhAQARAjUDtYK1A70CtAO1ArWCtQMRAlEANaEAAAEAPQO9gr0CrwAvAa0CpYK9AoECAAE3YQEAAQIZA8OCWQPBAk8Dx4J1AmUDwQIAADmhEABRAX8BP4G/Ab8BvwG/gv8CvwGRAAAAOyEFAhUBMQHDgjkC9QLtAu0C7YLtAs0CkQA7oQACLQE8gMDBPoJWAtaC/4LXwtaC/oLAAIRhQQAdAzUA9YB9ArUCNQJ9gbUBtQI9AiABBOFAAjEC3wLfgv8D3wHfAf+B3wLfAvECQAIF4UEDPQDFAhWBNQBVA1UAVQF1glUAFQOBAAahQQP9ABUDNYB1A/wAQQEpAEmCPQPJAAAACGFJAmkCJQF3gG0CZQJhA/2AdQFtAwUCQAAI4UECXQHRAHuDwQAVAWQBXQJVgk0DxQBAAErhQQIVARUANYB1An0BfQB9gH0A/QF1AMAACyFBASUB/QHlgQEAFQPdABWD1YAdAd0CIQENYXEDzQA9A92BXQHdAXUDX4ElAf0CDQIAAY6hQQAxAcUAMYD1APUA9QD1gdUBhQE9AMAADyFRABUBMQHBgB0AfQH9Ab2BfQG9A70BwAAPYUUANQPxAfuD8QD1A+ECO4EJAPkBSQIAABDhUACSgJKD+sLSgt4D0oLRgvnC1YPQgEAAkmFJAgkBvQAdgF0DXAB9AF0DXYBdAEUDQAASoUEBnQABAauCEQFVABUA0QGLgiECTQIBANphUQIVAwEAo4AhAX0BfAD9AX2A/QJhAcEAG2FAAAkCHQHdgdwD/AHdAJ2D3QHdAckDwQAcoUEAOQB9AHmB/wB7AEEDP4DTADMD0QAAAB0hUIKYgnSCkcFIg0CCPoPqw+qD6oJ+g8CCH6FAABkACwP7gssC3gPLAvsC64LLA9kAAAAhIUkBEwHRAAWAfQB9AP0Af4F9Af0AfQBAAGHhQABNAGEDwYAtA6wALQOhADeCCwH5AUgCJuFAAD0D1QFVgV0BwQAlALeApQP1AKUAoAApoUEDvQBtAi2A/QLtAO0C/QDtge0C/QHBACphQAA+g86AMMN6gMoCKoKrgq/D6oKqgogCKqFBARUAVwJ3gd0AQQM9ANeAFQA1A9UAEAArIWEAJQIRAUGBfQDtA+0AfQDBgVEBZQIlACvhQACdAPUA9YP9A/UD9AP9A/WD1QPdAEAALCFAgiKDf4F2wHeBf4B3gX+Bd8B/gWKBQAAyYW0BLQC9A+2AZQCBADUD/4K3Ar0CtQPAADNhQAA9AT0B/YF9AfwBQQHXAVeBVQHVAQAAM+FAAl0B0QB9A/2A7QG9AYeD/wEFAfUCBAE0IUUBlQGVAPOCiQHBAD0CVQHXgFUD/QJAATVhYoEqgL6D6sDqgECDvoB+wOqA6oJ+g8AAN2FBANcB1wH/gv8C5gLQAc2BxQHdAqEAkQA5IUEDPQDVAn2DwQBdAX0AH4PZAL0BWQJAADlhQAItAXkBQYF9AGwD7QB1AN+A2wFBAUAAOmFIgRqAwIBNwCyD/IKsgqzD6oK6g+iAAAA+4UCACoMSgMLBeIDvgN2D5cPdgO+BeIFAgUHhiQM5AF8Df4BdA3kBAACVAH2D0wBTAYEAAuGRABkC0QI7gVkAnAI9Av2CvQC9Ab0BwAIEYYCCPoHCgRrBWoPagsKC2oLawtqDyoBCgAthgAAAAD+D/8H/gLgB8AC/gP/BT4A/gcAADiGBAD0D/QGfga0BvQLJA7+AH4F/AN0ARQFToYAAAAM8AMQCFAHfgHUAbQHlAi0CLAEEABPhgAAAAz4AwgIKAk+B1wBXAVMCVwNWAMIAFCGAADADzgAiA+oCr4K3ArcCswK3ApICCgAUYYAAAAP8AAQBlAAfgbUCLQKtAiUArAGAABUhgAM+AMICCgJKAs+DWwFbAtMC1wJWAkIAFWGAAz4AwgLqAaoBj4JXAjcC9wI3AtYCggAWoYAAAAP8AAQClAIfg60CLQOlAi0CpAIUABbhgAAgA9wABALUAp+D1QItA6UCrQKMAgAAF6GAAAADPwDBAiUC38HtgO2A7YH5gcsCgAAX4YgAO4EqgSqAyYG8AEYDDgDXwBaB0oEGAJnhgAM+AMYAd4PvA+MCxgI8gCSCJIIkgcAAGuGAAAABPgEiASIBP4HiASIBIgG+AQACAAAcYYABPQFNAU0BfQHNAUsB+wHBAj8AwAMAAZ5hgAA+ASIBP4D+AIABAQEBAT8BwQEBAQABH2GAAAACNwLVAlUCfQHVAVUBVQF3AUACAAIfoYABPgJjgf+B/gGAAgEAPwPJABEAIQAAACAhiAAFAjKDwgEGALwCIgIiAT+B4gEiAX4B4GGAAj4CYgE/gf4DgAIeASCBQwD4AQcCAAIgoYAAPgE/gOOA/gHAAB0AUQBRAl8DMADAACKhgAA+An+B44H+AYACBgI6gwKB4gDeAQICIyGAAD4BIgE/gf4BgAEKAEoAf4PJAEkAQABk4YAAPgEjgf+B/gGAADyCJIIngcAAP4PAACVhogASgjqCVoJTgnqB0oFSgVaB+oHSgxICJyG+AWIBP4HiAT4BBICIgGiCWII/gciAAAAo4YAAPgJiAT+B/gGAAw8AAIOwAkOCHALIAykhiAEIgTSBVYFWgXSB1YFWgVWB9IFIAgAAKqGAAD4CYgE/gf4BgAMJADIAgAC/g8AAQABr4YAAPgJiAT+B4gE+A4ACPwPIgjiDyIIAADAhgAA+A3IBP4D+AoADMgIygj6D8gIyAgACMaGAAT4Bf4HiAT4BgAI/A8kCSQJ/A8ACAAAx4YAAPgE/geIBPAGCADoBwoJjAiICFgIAAbJhgAI+AX+B4gE+AoAAFgARAJTBkQJyAAQAMuGAAASBMoFSgVSBd4HVgVWBVYH1gUSCAAA1IYAAvgCzgP+A0gCMAP+D2IEkgRiBP4PAADZhgAA+Az+B/4H+AYACCQJJAm/DyQJJAkgCNuGAAj4Bf4HiAT4BgAAXgZIAf4PSAFIAgAE5IYAAPgESAT+A3gDIAC4D6YErASwBKAPAADuhgAEFATUBUQFXAXGB0QFXAVEBdQFFAgAAPmGAAj4Bf4HiAT4CgAA5A9kAvQPbALkDwAA/oYABHgE/gN4AwABlAj8B5AMfgKQBVYIAAYAh0AAXAD0BXQFfAX0B3QFfAX0DTQI/AcAAAKHAAj4Cf4Hjgf4ClAASAVuBdQPbAVEBUAECIcACPgF/geIBIgE8A5MCVQF1ANUBVwJQAkShwAA+AX/B/gGAgi+B0II8AsCCv4LIgoACBOH+AWIBP8HiATwBhoP5gUACCQK/gsiCiIKFYcAAPgEjgf+B4gE+AIwDM4DyA9OCHkIAAYXhwAA+AX8B4gEcAKMD1QAVAH0AVQI3A8AABiHAAR8Av8DxAd4DCsC/AEkA/4FAgL+BwAAHIcAABQEpAekBrQGtge0BqwGjAaUBxQIAAAhhwAA+ARIAv4DeAMABtQHXgVUBV4F1AcQADuHAAD4BYgE/gf4CgAA/A88Az4DPAv8BxAAR4cAAPgJ+ASOB/gGAAj8A7QC9Ae0CvwNAARJhwAA+AmOB/4HiAT4BnAAqgL4D6wC+gIAAEyHAAR4Av4DOAOAAP4PkAAkAAgB/g+AAAAATof4CYgE/geIBHgB4AdeBGoFagVqCP4HAABXhwAE+AWOB/4HiAfwCLwK1ArWD9QK/AqACFmHAAj4Bf4HiAR4AsAHvALUB1YB1AdUAdwHYIcAAPgJmAj+B/gKAAD0D1QK1A9UCvQPBABmhwAI+AT+B4gEcAL+D5ICDghgCWIH3ggACHSH+AmIBP4HiAR4AIAHfwKAD/4DEgj+BwAAdocACPgF/gf4BgAAfA1IA/wPaAN8BUgJAACChwAI+AX+B4gGcAT8B1YFPAL4DwQA/AMAAIOHAAj4Bf4HiATwDgQIVAbcAVYJVAlUBwAAjYcEAPwP7ATsAnwJgAd4AIgI/geIBPgGAAiehwAA+ATOA/4DSAIwAX4GqgL+AaoJggcAAJ+HAAT4Av4DyAJ2A34JWgVaBdoBWgV+BQ4JoocAAGIE6AfuBuQG4AfyBugG7gboB3QIAAi6hwAA+AmOB/4HiATwBR4J6g1+DyoBvgsACsCHAAj4Cf4H+AYACJQC9ALuDtQCBANUAgAAxocABPgCSAL+A0gCMAtkCHYH9AF2A3QNAATLhwAE+AX+B4gE+AQAAlwENAl8CTIAWgaQANGHAAj4Bf4H+AYACPQDdAN0A3YP9AMQAgAA8ocAAKALrAqsB6wHPgisA6wKvAesBqAHAAj5h4QEfAQ3Bb4FtgV4B8oHtgWyBboHNggAAPuHAAT8Av8DRAJ+ATsL2g9+A+oHKwdqCwAJDYgACPgF/gfwBnwPPAO8B+ADMAf+AAgDOAQViAAI+AX+B/gCAgA6D0oH3gFaD2oBag9AAB+IAAD4Cf4HiARwAiYPeAt0APoPUAR+AwAMIYgAANQF3AW+B78Ftwk/AJcFrQesBaQFAAAiiAAAqgWeBf4H/gX+Cf8A/gX+B54FqgcgCDuILAAXBN4FQAV2Bf8HfgVwBWQFvwc0CBIAQIgABPgHCAQIBPwHCgQIBPgHCAQIBPgHAARFiAAA+Af8B/oH+AMCABwBIAH+DyABLAEAAEaIAAggCbwEJAS8AKYPfAEkAiQFvAQgCAAATIiIAEgA5A8SAAAAJAAkACQIJAjkDyQAIABNiIgARADzDwgAIgwiAoQBIAgiCOIPIgAAAFOIQABEAPMPCQDIAf8HCADDBRAE8gcSAAAAVIgAAMwA8g8YAIYI9QeUBAAAJAjkDyQAAABXiEAARADyDxkCUALeA1QCVAYABPIHEgAAAFmIAADIAOQPAgBUD3wFdAdkACQAJAjkByAAW4gEAEIA+Q8IAPoD3wLaB/4CAgDyBxIAAABdiAAAJADyDwgAeglaCf4H+gUJBCAA5A8gAGGIAABEAPIPCAn4Ba4D/AOsDfgBAAjkDyAAYogAAIwA4A8cALwHnAeYB7wHvAQAAOQPIABjiIAAiABICMgPKAgaBDwEyACIA0gEKAgACGWIAAAIAYoA6g+YAEgBAAD+DyAAQADAAIAAaIggATQJtAS0B3QEPgT0BDQBtAK0BCAIAABpiAgBiADuD5wAQAkcCOQEFAOEAnQEDAgAAGuICAGIAO4PnABIAQAIiARIBEQCMgIQAQAAbIgIAYgA7g+cAEgBAADQABAJEAj+BxAAAABwiBQBFAV8BVwH3AReBNwEXAFcA3wFFAUQBHeIAAAEAnQCVA5UCfYIVAlUAlQGdAkECQAAgYgAAhAC9AK0DrQJvgS0AbQCtAZ0BRAJAAiEiAQBhQD3D44AZAEADCICogF+AKEDIQQgBIuIkAKIArwKgg6ICcgIjgmYAqoGygrKCqgIjYgAAYwA7A9YAQAA8AcsCSgJ6AsICvgJAASSiAgBiADqD5gAAAj8CSQJJAkkCSQJ/AkACJaICAGIAOoP2AAAAPgPiASIBP8HiASIBPgPnIgAAYoA6g/YAAAESAJIAf4PSAFIAkgEAACriAgBiADKD7gBAAz4A8gISAl+BkgGyAkYCK2IhAKkAqQKlA6MCaYIvAnWAtYG1AXEBbQIsYgAAYgA6g/wACAA/A8CABAH/gCQAxYMAAC0iAgBiADsD5gAAACoALgDrAKoCpgKqAagAMGIAAFUC9QHXgRUAVQDEAz+AhAD0gQUCAAGwojWAtYC3gquDp4JxgSAAZ4CwAbABf4JAAjFiKACrAKQCrwOgAmoBKgBvAKoBqgEqAgAAMaICAGIAO4PnABIAQAELAUgBT4FIAXsDwAAz4gABEQFfA18D3wJ/gl8A3wFfAV8C0QLAAjUiBQA1A90APQHbAVkBWYFzAbUAKQPJAAAANWICAGIAO4PWACIAAABxA+yCIgIsgjED4gB2IiABKwCrAqsDoQJ3gSEAaYCrgasBKQIAADZiAABiADrD9gAgAIqAeoHvgSqBKoEvgcIANyICAEIAc4PuAAAAOgPqAKoAv4PqAKqCuoH3YiQAr4CmAqYDr4JgASoBKgBvgKoBqgEiAjhiAgBiADsD9gAAAB8CVQJVAn8D1QJfAkAAOSIAAGKAOoP2AAADPwDRAC2ApQPlAKUAgAA84gAApwEhQK2DrQJ9gS0AbQCtgaFBJwIAAD4iAgBigDqD9AAgAT8BNQC1A/8D9QB/AKABPmIgAJEAnwBfAf8BP4EfAF8AnwCfAXEBAAA/YgIAr4CnAq+BpwF/ASAAZwCwAbABb4JAAQCiQAAxAD1D2wAAASUBN8HlAQAAP8HIABAAAeJgABIAO4HeAAABT4F/gW8ArwCvAW8BAQEEIkIAYkAyg+4AAABvgeqBKoFqgaqCL4HAAASiSACFAL0AgQOZAl8CT4JfAI8BnwFJAkABCWJAAGIAMwP+AAADvwBdARcATwJ3A8cAQAAKokAAIgB7A/YACAI7AcACPwLVAhUCXwKAAgyiQABlADUB7AAAAT4A+gD7AP4B+gD6AMIAkSJQAXEBfwD7A/8CcYJ/APsBewF/AlECQAAX4kAAIgA7g/cAQAJTAVeAVAPTAFeBVQJEAByiQAFDAV8A34PfAt8CQAJfgP8BfwL4AtACX+JBAD0D5QE1AQ8BBQEFAR8BJQElAT0DwQAgYkAAIIIugiqC/4GqgSqBL4GqgWqBLoIgACGiUQBXAG8D1wA3AjsC/wH/Af8B/wLPAgACIeJAgBeB9YH1g/eB1YHFgz+A7YCtgr+BwIAi4kACAAI/AlUBVQDVAFUAVQHVAn8CQAIAASPiUgISAT8A0gBSAoACPwFVANUD1QJ/AkABJOJAAgMCPwL5AbkBuwC5ALkBuIK+gsCCAAElokIAYgAzg+4AAgJAAj8BVQDVA9UCfwJAASaiQAIOAgKCOwL6AbqAuwC6A7sCwoIOAgABKeJAAg8CPwL/Af8B/wDwAPsB+gL6AsoCAAEqokAAKQErALmD6wCoAj8BVQDVAFUD/wJAASziQAAMAHsB7gH6AeoB/wNVANUAVQH/AkABLqJAAAwCB4I3gvQB9oD2gPYD94LHggwCAAEvYkACD4I7gv+B+4H7gPAA/YH/Av8CzQI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AAAAAPwProsgACQI7A8ABAQCeAiCBQwCgAV4CAQIAAiviyAAJAjkBwgCQAJEAPwPRAAEAPwHAAgABrCLIAAiCOQPCAQAAMQHRAhECEQIRAj8CAAGsosgACII5AcAAogIiAT+A4gAiAD+D4gAgACziyAAJADoDwAEiAKoAKgA/g+oAKgEiAMAALaLEAASBvQBBAWADDoCIgGiCGII/gciACIAuIsgACIA7A8ABLAAjgCIAPgPiACIAIgAAAC5iyAAIgjkBwgCYAD4DwYAgAD+ByAIGAgIBrqLIAAiCOQPCAIgAJAHCAmGCIgIkAggBiAAvIsgACII5AcIBGAAGA6GBWAEBgUYB2AIAAC9iwAAJAjkBwgCAAz8AyQGxAEkAvwHAAgABL6LIAAiCOQHCAIgCqAIXgVCAkIGfgXgCCAIv4sgACIE7AcEAgAICAb4AUoISghICMgHCADAiyAAIgTkBwgCQAlIBEgD/gDIA3gEQAgAAMGLIAAiCOwHCAIACOQPBAgECPwPRAhECAQIxIsAACII7AcEBIACugCCAP4PggCyAIoAAADFiyAAJAjoDwgEAAD8DyQJJAkkCfwPAAgAAMaLIAAiBOwHCAIACHwGRAFEAEQARAF8DgAIyIsgACII7AcIAmACEAAOAPgPKAEoASgBKAHJiyAAIgjkDwgEAAD8DyQAJAHkDyICIgIAAMqLIAAiCOQHCAQAAlAISAkGBcgEUAIQAQAAzYsgACII5AcABgIA6gMqASoB6gkCCP4HAADPiyAAIgTsBwQCIACiD5oEhgSiBKIEngcAANGLIAAkCOgHAAIkAqQCrAKUD7QCrAIkAgAA1YsAACII4gcCBAgASATIBwgC/gAIBwoMCALXiyAAJAjoBwgCoACoAqgCvAioCOgHqACgANqLAAAiDOwDAA74AygAKALICX4EiAfqCAgG3YsAACQI6AcIAiAApA+kCPwIpAikCKIPIADeiwAAIgjsBwAAsg0uA8IE8AkCCv4LIgoCCuGLAAAiAOwPAAD4DxYA1AdUCFwK0AkQCAAE4osgACQI7AcABBAAyAOuAqgK6AsICPgHAADliyAAIgjsDwAEJAG0CKwEZwQkBhQFhAgAAOaLIAAiCOQHAAIIAEoBSgH4D0gBTgEIAQAA54sgACQI6AcAAhgACAEoAe4HqAiICJgEAADriwAAIgjkDwAA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gAT/BJgEmA8YAL+MAAQQBPwF9APsA/AB9AHsA+QD1AUMBAAAwIwAABQIzAvmCvQK7ALgAv4K8gryCx4IAAjDjBAACADcA8QL4AvqA+oD/gvqC+kDKgAAAMSMAAj8DVQFVAH8BUAA+A+sAqgCqAroBwAAx4wQCBII9Av0BuQG9AL2AuwG9Ab0CxQIAADKjAAI/A1UAVQF/AFIAOgJSAR+AogFbAgIBtOMIAAsCOwH/AbsAv4C7AL8AvwG/AcMCAAI24wAABwIzAXuBewF7AHgAfwF7gX8BRwIIADcjAAI/A1UAVQF/AUAAb4C6gmqBKoDvgiAB96MAAAcCMYP9g30DfYF9AX0DfYNxQ8cCAAA4IwACPwFVAVUAfwFIAC0B6QEpgSkBLQHJADijAAIPgj6B/4H+gf6A+AD4gfaB5oHJgggAOOMAAQ6CO4H7gf+B+8D7gP+B+4H7gc+CAIA5IwACPwFVAVUAfwDqAjsBBgH2ga8CbgJEATmjAAI/A1UAfwFAAjUDxQI0AeQBP4DEAwUBuqMIAAcCMwL7Ab6BvgC7gLqBuoG2gsKCAgA7YwABPwHVAFUA/wFAAGkB/4FpAW8BaYHIAD0jAAEeAJYAfwPWAE4AMAL7ArkAvQG7AcACPqMAAD8DVQB/AIICGwF+A9oAfgPbgPoBUAI/IwACPwNVAFUA/wGwA/sAv4C7Av+CuwHIAL9jAAArAh8BPwH/AP+A/wD/AP8B7QEpAQAAAiNAAj8BVQB/AUAAPwP5wrkCvwK5ArnD3wACo0AACgI/g9eDVwFXAV8BV4FXgXsDxwICAgPjQAMggO2CjoHugm7A7oFOgC6B7oPCgQAAB2NAAAACPwJBAQEBAQC9AEEBAQE/AkACAAAHo0ACAAI8AsQCBAEHgLUARQEFAT0BQQIAAAfjSAIEAj4CRQIFgQUAtQBHAQQBPAJAAgAACGNAAAUCNQLVAhUBlwBVARUBFQI1AsUCAAAIo0ACP4JAgT6AwIA/g4AAAgDiAhoCP8HCAAjjRAAFAjcC1wIXARcA14AXARcBNwFFAgAACSNAAAeCMAFQAReAkABZgRaBFoI1gsSACAAJY0ACP4IAgb6Af4MAABwCI4EiAN4BAgIAAAmjQAEfwf5AAEC/wIACP8HIAToACYDIQQAACeNAAAICMQLXghBBkQBTwRUBFQI0gsKCAAAKI0AAPAHDADsCSwELAK8ASoEKgTqBQgIAAApjQAAfA/0AAQC/AAADvwBNAzUAhQD8gQECCqNCAAICNQLVAhSBFoDUgB0BFQE1AUECAgAK40IACgI7AtqCFoESANoAGoEXATEBQgICAAsjQAI/g3yAwIC/gAADCQCIgYqCeIIIQgACC2NAAj8DeQDBAD8DhAAzAEKAcgJCAj4BwAALo0AAPwJBAT0AwQA/A4QAAgEDgQIBAgEOAQvjQAACAj8C2oIagZ+AWoEagRqCP4LCAgAADCNAAAoCLgJuAS4ArgIuAsICP4BCAYOCAgEMY0ACPwIBAb0AfwCAAhQBP4EUAdUCVAJAAQ0jQAI/A30AwQA/AYAAIAP/gSIBIgEiA8AADWNAAAgCPwLdAh0BHQDfgB0BHQE/AUgCAAAN40QAAgI3AtCCEgESANOAFgEagjiCxQAAAA4jQAAAAjcC1IIWwRAA1IATgRiBOIFHggAADmNAAhACN4LdghfBFYDVgBfBFYE1gUWCAAAOo0AABQI1AtOCGQGXAFABFwEVAjUCxwAAAA8jQAE/AL0AQQE/AAABugBCAh+BIgH6ggIBj6NAgg6COoFagR+BGoDagB+AmoE6gU6CAIAP40AAPwN9AMEAPwFwAD4D64CqAKoCugPCABBjQgABAjfBUAEagNqAGoCfgJqBOkFKggAAEKNAAj8BuQBBAT8BAAAyA/WBKQE1ARMD0AAQ40AAPwN5AP8DAAM+AMICEoI6g9ICEgIAABEjRAIEgjUBUAEaAJmA1YATAJUBNQFDAgAAEqNAAD8DeQDBAD8DgAAUANoCOYPaABIBxAES40AAPwN5AP8AAAI1A8UCNQHEAD+AxAMFgZMjQAA/A/0AQQE/AWAANQPfgVUBVgF1A8QAE6NAAj+BfIDAgD+BQAApAlUB/4BFAU0CQAAT40AABwIhgu0CLQEtgK0ALQEtgSFBRwIAABQjQAI/AkEBPQDBAD8DgAAvgDqC6oGqgm+B1SNAAj8B+QBBAT8BQAAqA+kBKYEtASkByAAVo0ACPQElAL+D5QB9AoACPgH1gMcCPQLAAhYjSAELgSeBV4EXgJeA0gAbAJeBJwFJAQkAFqNAAj8DeQD/AAACFoF/A9YAfgPXgX4CUAAW40AAKwIvAj8BbwEvgK8ALwE/AW0BCQJAABejSAALgicC04IfARAA24AXAROBJwFLAgoAGCNAAB+BAID+gACAn4AmAd/BXwFfwX8BwAAYY0AAPwN9AP8DAAA+AcOAOwPzAvIC9APAABijQAM4gO+Cv4H3gw/A/4M3gc+Af4PBgQAAGSNIAKkAaQIJAbkAT4IJAjkDyQApAAgAwACZo2ACSQE5AM+COQHJACACTQEygKIA3gECAhrjYAJJATkAz4I5AekAIAH5AE+COQHJACAA3CNIAgoBKgDKAQoBPwPKAkoCSgJKAkgCAAAdI0QBtQBFAL+A1QEVARQBAAE/gUIBBAEIAR1jRAG1AEUAf4DVARUBAAFzAQwBEwEggUABHaNIAykAyQE/gekCKQIAAgkCPwLJAgkCAAAd40QCNQHFAL+B5QIlAgACOQJJAokCjwKgAmBjRAG1AEUAf4DVARQBAQFUgUiBaQEiAQIBIWNAAjYBxgE/AeYCBAI1AtMCmQKZArcCwAIio0gDKgD/AeoCAAI+AmICAgKfgnICioKAAiLjSAGqAEoAv4DiAQgBBgFVgVUBVwF9AUABJWNIAaoASgC/AOoBQAFXATcBNwF3ATcBAAEmY0gDKgDKAL8B6gIAAj0CzAIvAiQCvQJAAifjQAIpAckAv8HpAgECPQLkAheCZAI9gsACKONFAAUBJ4D9AMQBP4EqgT+BQAE5AUcBQAEqI0QDNQDFAL+B5QIpAjvC14JSgluCN4LAACzjQAAAAg8BKQDJAQkCOQPJAkkCTwJAAgAALSNAAjeBxIE8geeAAAO/AEAAAQA/AAABwAIvo0ACN4HEgTyB54AAAj4DwAI/g9ACEAIAADDjQAI3gfyB5IEngQAACQMIgP+ACIDIgQgCMuNAAieDxII8geeDAAICAf/AEgLSgbKCUgAzI0ABN4HEgTyA14CAAhOBEgD/gBIA0gESAjRjQAE3gcSBPIHngQAAPoHtAj0CgQK/AkABNuNAASeDxIE8geeAAAM+APICX8GSAXYCAgI3Y0ABNwHFAT0A5wCAAD8DxQFFAUUBfQFAATfjQAI3gcSBPIHngAACPwPVAjUAVQGfAUACeGNAASeB/IHkgQOAuAM+AMOCPgHCADoAQAA6I0ABJ4H8gfyB44EIAC4A6gKrAq4CqgGqADqjQAAHgfyB5IEPgz4BxYA1AdUCFwK0AkQBO+NAAjeBxIE8geeBJAAiA/WCKQIvAjED4AA840ACN4H8geeBAAACA3+AwAA/gdACJgIBAX1jQAE3gfyB5IEHgKACEgE/wRIAyoFqgmABPeNAATeB/IHkgQeAoAIpge8ALQPzAjMCKAE+o0ABJ4H8gOSAp4CAABeB8IA4g9OAVAGAAQKjgAAAAQeD/IHngQAAOQPpAL0D6wC5A8AAA+OAADeDxIE8geeBAAAuA+ACv4KkAqsDyQAEI4ABN4H8geSBB4IQAnoBS8HGAWpC00LJAkijgAE3gfyB5IEngKAAL4C6gmqBqoBvg8AACmOAACeD/IHngQABJQApA6EAdQPggK6BIIIKo4ABN4HEgT+B4AAqAaoAK4IqA+IAJgCgAQxjgAA3g8SBP4HAAz8AxQI9AXWBvQFlAgAADSOAACeDxIE8gcOCPAKagZ6A24K+goABgAAQo4ACN4HEgTyB54EAAAaDQoDvg8KAxoFCAlEjgAI3gfyB5IEDgJgACQHlACmD5QApAcAAEiOAAAeD/IHkgQMALAPRAkUCUIIUgnKDwAAS44AANwPFAT0BxwEQAd8AuwPrABsCvwHAABfjgAA3g8WBPYHngwACPwLfA1+BXwN/AsQCGSOAAieB/IHngSAAPYPAATcAwoG4A+OCJAIZo6eDxII/geADOwHqALoDw4A6AeoAuwPAABsjgAEPgPyA7ICfgS6BXoHZgVsB7QHMARIAG2OAADeBxIE8geeAgAAvAevBbwFrwW8BwAAco4ACJ4PEgjyB44A5AOWB7wHvAPWD/QDAAKBjgAAngfyB5IC7gbQAt4B+gfqB9YB8AIABI2OAAjeB/IHkgSeBIAB/g+mCvAPrgquCgAAj44AAJ4H8gMeAMAHlADmB9QD9APWA/QPBACrjgAJAAn8CVQFVAVWA1QLVAn8B0AAIAAAAKyOgAT+BKoCqwn+BwAA8gCSCJIIkgieBwAAr46ABP4EqwKqCf4HAAD+DwIKmgliCJoLAgiyjgAJ/AlWBVUD/A8AALAMjgLCD4ICngQgCLqOgAT+BKsD/g8AAPcHEADQA14BkAT3AwAAyo4AAAQC/AKsAqwC/g+sAqwCrAL8AgQCAADMjgAA/AKsAv4PrAL8CgAG/wEIAPgPAAgABs2OAAAGAvoCugK6Av4HugK6AroC8gIGAgAA0o4AAPwCrAL+D6wC/AJAAEQA/A9EAEQAAADfjgAA/AKsAv4PrAL8CBAEDgP4AAgDOAQICOKOAAD8AswC/g/MAvwCAAgkB+QEJAQkByAI+I4AAPwCrAL+D/wCAAD4D4gE/weIBPgPAAD9jgAA/AKsAv4PrAL8CkAIJgmaDxoJJglCCAOPAAD8AqwC/g/8AgAAFAhUBIYClANUBBAICY8QAvQD9APuB+4H9AMQBn4CkAPSBBQIAAYUjwAA/AKsAv4P/AIAAOgPqAL+D6gC6g8AABWPAAD8Av4Prg/8AhAIagkCCXoPAgl6CUIIG48AAPQC/g/UAnQA4A8UAJQB/A+UAfQPAAAdjwwM4AM+AOgHIAIKAvoCugL6D7oC+gIAAimPEABcBNwH/AfMB+APwAfcB9wH3AccBAAAKo8AAPwCrALeD/wCHADED+IH4Q/GDwgAEAAvj/wCrAKuD/wC/AIABi4E6gdqBWoF7g8gBDiPAAD8AqwC/g/8AhgAxA+zAvIPhAHoDwAAO48AAPwCrAL+D6wCfAAUD6wKrA+sCrwPAABJjwAA/AKsAv4PrAL8ApwGvAr+CrwP/AMAAF+P4gfiB/4P/gf+B34Avgf+B/4P/gfiBwAEZo8AAAgCaAJYAk4CSgLoD0gCSAJIAggCAABnjwAARAJ8AkYC9A9EAQAA/gcACAAIAAcAAGiPRAJ0Ak4C5A9EAQAICAf+AAgA+AcACAAGaY8EAnQCTgLkD0QBAAFEAEQA/A9EAEQAAABsjwAAfAJGAvQPRAEAAKQA9AKuBKQLpAAgAG6PRAB0Ak4C5A9EARAAyAeGCIUIiAgwBgAAb48EAnQCTgLlD0QBJAkwBA4D6AAIAzgECAhwjwAIpAi0BrwCtgE2CTQItAW0BrQGpAUgCHSPAAB8AkYB9A9AAPgPiAT/B48EiAT4DwAAe48AAHwCRgL0D0QBAAkkCKQIlA+sCKQIIAh9jxAAVAXUBV4FVA9UAxAI/gQQA5YFUAgABn+PAAB8AkYC9A8EANAMNAMcABQAMg9SAIAAg48AAHQCTgLkD0QBAAloBIgEDgOoBSgIQAiFjwAAOgEnAfIHIgEAAPQPVAH/B1QB9QcAAIaPfAJEAvYPBADwDxQB/AAcA/wIFAn0BwAAiI9QBFwF3AVcBV4FQAVAD14FXAVcBVwEEASJjwAM9AMeAPAHFAFCAU4BegHqB0oBSgEAAJCPPAJEAvYPRAAAD7wKrAqsD6wKrAq8DwQAkY8AAHgCTALoD0gBAAT8B3QFdAV0BfwPIASTjwAAfAJGAvQPIAD4D7QC8g+UARgI8AcAAJWPRAB0Ak4C5A9AAhAC9A60Cb4JtAJ0BRAJlo8AAHwBRgH0B0ABFAC0B7QF9gW0BZQHgACZjwAAdAJOAuQPFADuB7QK5A90BIoDeAQACJuPIAAkASwBPAEkAecPJAE0ASQBJAEgAAAAnI8AAEIFXgVWBdYFVgV3D1YF1gVeBQIFAACejwQAkg+SBP4EkgcQAEQBdAHGD3QBRAFAAJ+PAAT8A6QPpAS8BwAAWAFIAc4PaAFIAUAAo48AAEQJVAnHB3QBBAjwBJQC/g+UAvQEAAimjxAIzAfoAUAIEAf+AOAPCABaAcYPaAEAAKiPRABVCcYHdAEACHAG/gEAAFQBxw90AUAAqY9EAFUJxgd0AUAADgjkBwAAVAHHD3QBQACrjwgAWgnsB0ABHATyBIgEAARVAccPdAEAAK2PBADMD1IBegfWANYPAABUAccPdAFEAQAAr48IAFoJ7AdIAUgPawVoBwwAXQHvD0wBAACwjwAAAAz8A0QA1A9UCFQE1AFUAlQFVAlACLGPAACAAn4CIgbqBqoCKgpqCqoG6gJiAwACso8ADPwDbAnsCf4H7AnsBf4H7AXsBfwLQAm5jwAIIgTsAwgEAAgIC8gIPggICggK+AkABLqPQghGBMgHAAQECMQLPAgECgQKBAr8CQAIu49ICFIE1gMEBBAIEAgQCP8LEAgQCBAIAAi8j0IIQgTMBwAIAAqCCWIIPgjACAAJAAoAAL2PAAgkBOgDAAQECAQKBAr0CxQIDAgECAAAvo8gCCIE7AMABAgICAvICD4ISAiICAgLAAjBjyAIJgToAwAEJAgkCCQI/AsiCCIIIggABMKPAAgkBOgDCAQgCCQKJAr8CSQIJAgkCAAAxI8gCCQE6AMABDAECAmsCmgKKAooCggJAADFjyQIJAToBwAEJAgkCPQLJAgECPwJAAqACcePIAgiBOwDAAQICCgIyAgICggK/gkICAgIyI8kCCQE6AcACAQLxAg8CBQIFAoUCvQJBATOjwAIRgzIAwAE/AkECQAI/AsECAQJ/AgAANCPIAgkBOgHAAgQCtQJNAkUCVQJlAkUCgAI0Y9CCEIExAcACAAL/ggSCBII8gsSCBIIAADUjwAIQgTMBwAIAAv+CDIK0goSCdIKMgoCCtiPAAgiBOwDCASACEQIJAj8CwQIJAjECIAI2Y8ACCQE6AcACCgKKAnKCEwIuAgICQgKAADbjyAIIgTsAwAESAhIC/4ISAhICP4LSAhICNyPIAgkBOgHAAgQChQJ9AgUCPQLFAqQCQAA3Y8ABCIE7AMABFQEVARUBP4FVARUBMQFAADejwAIIgTsBwAEFAksCSYJ9AskCSQJBAkAAN+PIAgkBOgDAAQACfwIJAhkCOQIJAk8CgAI5o8ACE4EwAcEBfwEBgj8CwAI/AsECvwLAAjqjwAIJAToBwAI+AtICkgK/gtICkgK+AsAAOuPRAhEBMgHAAQACPgLSApOCkgKSAr4CwAI8I9CCEIEzAcABIgJaAgICP4LCAhqCIoJAAj0j5AI1AS0AwAE/AkECvQKlAr0CgQK/AsAAPePQghGBMgHAAgkC6gIYAj+C2AIqAgkCwAK+Y8ACCQE6AMIBGAICAv6CAwK+AsICOgIAAD9j0IIQgTEAwAE/AlUClYKVQpUClwKwAsACACQQAhCBMwHBAgACv4LKgpqCKoJXgpACgAAAZBCCEIEzAcABEgITgpICfgISglKCkgKAAgCkCAIJgToBwAEFAjUC1QKfApSClIK0gsQCAOQAAhECMgHAAScCEAK/gkACP4JQAqcCoAKBpAACE4MwAMIBOoIjgqICvgJiAiOCOoICAgJkAAIJAjoBwAIIAqsCWgIPgjoCygKKAogCQqQAAgiBOwHAAQiCPoLRggwCv4LAAg4CMAADZAAAJII9AaUBQAI9gsQCF4JEAmUCvILAAgPkAAIJAjoBwAELAgsC9wIXAicCqoKqgkgCBCQAAgiBOwDAAQSBaoIrgpSCuIJUgiKCAAEEpAgBCIE7AMABHQFVwXUBPwFVgRVBdwEAAQUkAAITgTABxAESAlUCFQK8glUCEgJUAkQCBeQAAgkDMgDEAQECHQK1ApUCtQL9AoECgAIGZAAAFQEfALYAwAE+AV4BXwFeAX4BQgEAAQakCAIIgTkAwAE+gmuCK4I+guuCK4K+gkAABuQAAgkBOgHQAguC/QIAAokCvwLJAokCgAAHZAACCYI6AcACEgK/gkICPwLEgjyCxIIAAAekAAA0gi8BpgFAAi8CrQK9Au0CrwKAAoAAB+QQghCBMwHAAh0ClQJ1Aj+C9QIVAl0CgQKIJAACCQI6AcABCAIrAuoCrwKqAqoCyAIAAAikAAIJgTgBwQIlAqSCq8K6guuCqoKCAoQCCOQAggmBOQDAAR8CVwJXAn+C1wJXAl8CQQJLpAACE4IwAcQCJQKVApUCP4LVAl8ChAKAAgxkAAIQgzMAwAE/gkCCOoJegnqCQIK/gkACDKQAAhGCMgHAAQQCP4LqAr8C6oKqAoICgAIOJBCCEQExAcQCHgKVgnWCHQI3AtQCnAKAAE7kCAIJAToAwAEnAhUCnwKVAlcCdQIHAgAADyQJAgoBOgHgAt8BWwN7A9sDWwN/A8ACAAAPpAACCIM4gMIBOgF/Aj8CwsI6ggEDOgPCABCkAAIRgTIAwAEKAluCdgIqArICa4IqAgICUWQQAhEBNgDAAX8CBQI1AnUCdQL9AncCQAIR5AACCQE7AcACP4Lagj+CX4Jagt+DMAPAABKkAAIRgzAAwQF/AgXCuQJDAhGCvQLVAhECEuQAAgiDOQDAAR6CXoJegn6C3oJegl6CQABTZAACCIE7AMABfwI1Au0CPYLtAj0C7wI4AtOkAAIQgjMBwAI4As+COIJegnqCT4I4AsAAE+QAAQiAuwDgALcBTwFvAW8BTwFPAf8BwACU5AgCCQE6AcABAgI+gu+CrgKvgr6CwgIAABUkAAIRgTIAwAE1An0CdQJ3gvUCfQJ1AkQCFWQAAhECMgHAAj8CtwL3AreCtwL/AqICgAIV5AACCIE7AMABO4IagpqCX8IagrqCi4IIARZkJAI9gaQBQAIuA6kDrwO9g+sDqwOpA6ACFyQAADRDLYCEAVCBPoJBgpcCPYLQgjBCgAAXpCQCPMEFAOABH4IAgvyCD4Kfgh1CXUKMAFgkAIIQgjCBwgEfAlcCdwI3gtcCfwJiAoACGOQAghCDMQDEAT8CfwK/Ar+CvwK/AqQCwAIZZAACCQM6AMABEwJfApkCuwLZApiCmoLQABokIAI1ggwBwQG9Al+DVQNRAsQCI4LeAoICmmQAAhGDMgDAAT0CTQI/Al2CfwJNAr0CQAIbZAACBEE9gMABP4Jvgq/Cr4Kvwr+Cx4IAARukAAEJgLoA4ACfAQUBXQEVgZUBXQEFAUAAHKQkAjUBLQHAAb8CQwItAqMCtwLjAq8CgAKdZAACCYI6AcABHwJbgtsCWwJfA3+D3wJBAF3kIAI1AS0AwAF/AjsC/wM7A78D+wMfAkACXiQAQgmBOQDgASuCu4K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SgJABAAAyJEAAJYBUgD+B1UAAAb/ASEA4QAhAz8MAATKkQAAKgOiAP4PowCqAKACrgKSD6oCpgIiAsuRBACsAfwPogCoAD4C+gK+AroHvgL6Ai4CzJEAAAAEvgSqBKoEqgT+B6oEqgS+BAAEAADNkQAAEAT0BfQF9AX8B/QF9AXyBfIFEAQAAM6RAAB8CVQJ/AdUBXwBAAgkCPQPLADkAAAAz5EAACAE/Af8B/wH/Af8B/wH/Af8ByAEIADRkRAAsAiQCZgLlgjxD5IIlAiYCpAIMAgAAN2RUAhYC1QI8gdUBEQFAAAgAP4PIAAgAAAA45FQCFgLVAjyB1QERAUQAM4ICAkIDPgDAADnkUAIWAtUCPIHVAYADP4DAAD8BwAA/g8AABWSUAhYCfYHVARUAQAIRAj8D0QIxA98CEAAHpJQCFgLVAjyB1QEWAUGASUJJAkEBfwDAAA0klAIWAtUCPIHVAUQBEgA1w9SAEwE0AcQAESSUAlcCPIHVAREARAETgRIA/4ASANIBEgIcZJQCFwJ8gdUBAAN+AMIAAgH7gQIBIgHAAh0kkAIXglAC2AJXgnQD1YJZA00CVQJRAgAAICSUAhYC1QI8gdUBwAA/g9KCMoBSgZ+CQAIg5JQCFwJ8gdSBAQNZAQ0AywAJgC0DzQIRAaFklAIXAnyB1IEhAT+DwIA6gMqAcII/gcAAJiSWARUBfIHUgREBRACGAGUD+YEnASEDwAArZJQCFwF8gdUBFQBAAioBP4FqAaqCaoIAAazklAIXAX2B0AFEAD8BJIGkAGSD/QIGAgQBLeSQAhQCVwE8gdEBggN9gcQAF4BEAn2BwAA0pIAAFAIXAXyB1QFAABIBa8Fkg+uBaIFQATqklALWAT2B0gEWAUIAOgPqAL+D6gC6g8AAO2SUAlYBVQE8gdUBAABegzMA0gAzA96CAAG/JIAAFALXAjyB1QH/AsMBKQD5AMMC/wHAAAEk1AIWAn2B1QERAUABNgCVgjUD3QATAVABSKTUAhYBfYHVARUAQAIKAmeBRgHWgcqC6gIJpMoBC4F+QMqBioHgAe+AOsPqgCqBL4DAAArk1AIWAlUBPIHRAcABL4E6gOqBqoJvgcAAC+TWAhUCfIHVAQEBSQA/gdkBWQFfgXkBwAAMpNQCFgJ9gdUBAAFogQqAOoPqgEqAr4CoAQ2k0gLXAjyB1QERAEUAFQP1Ah+CNQDVAVACUqTWAhUCfIHVAQEBfQEtAKUAf4PtAH0AgQES5NQCVgI9gdUBQQA4A8+ALIDqgI+CeAHAAB1k0gIXAnyB8QHMAwuA+AEqgb/C6oKvgoICH6TaAhsCWoE+QdqBwIM/giuCv4Prgr9CgAIjJNIBM4E+QdKBewFrQL+D6wA/A+vAvwEAACWk1AIWAhUCfIHVAQACfQLsAq+ArAC9gsACK6TQAhQC1wI8gfUBQAA/AvsCu4C7Ar8CwAK4ZNQCFgIVgnxB1IECg3qCG4HawFuD+oJCAQYlFAIXAXyB1QFAADyC3oLcwvzD3ILfgvyCzWUMAhaCvwHHAd0ALQHvgdUDP4FEAfWCAAGUZRQCFwJ8gcEB34Aqg/uCboPAAlOD0gJSA9wlAgIXAnyB0QFCADoD8QHkgL0D4QCaA8AAH2UUAhcBfIHVA0ACBgI3gXcA9wL3gusCygAiJSYAIYI9Q+UBIQEIAAgACAA/g8gACAAIACJlAAAmACGCPUPlASUBAAABAgECPwHBAAEAJOUAACYAIYI9A+UBKACHABKAIgJCAj4BwAAmZSYAIYA9Q+UBJQEAADyAIIA/giSCJIHAgCdlJgAhgj1D5QEAAToAQgBCAH+BwgJCAnoDZ6UmACGCPUPlASEDIAIOAgABP4DgAEIADAAn5SYAIYI9Q+UBAQE8AGQAJAA/g+QAJAA8AGglLgAhgjlD6QEBADwDxACkAF+AJAJ8A8AAKKUmACGAPUPlAQAAP4PAgIyAfoBAgj+BwAApZS4AIYI5Q+kBKQAAAz8AyQBJAkkCfwPAACmlAAAmACGCPQPlASEDDAIDgboAQgDOAQICKeUmACECPYHlASEAhAATgJICUgJCAz4AwAAqZSYAIYA9Q+UBAQEEAHuAQgJyAsICPgHAACulJgAhgj0D5QEhAwACEIO/glCCEIO/gkACLGUmACGCPUHlAQAAsgISAT+BEgHKgmqCQAEs5SAAKwI6geoBIACEAD8D5AEkASQBPwPEAC7lJgAhgT1B5QElAIEAIAPgAT+BJAEkA8AAL6UmACGCPUPlAQABP4BkgCSAP4PkgCSAP4BwZSYAIYI9Q+UBBQEwADODMgC/gFIAkgEQAjDlJgAhgj1D5QEhAQQAEgBVgJEDcgAEAAAAMWUmACGCPUHlASUAgAAvg+CBIIE/gTADwAA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AAT+AtAI3gfQAPYCAASblgAA/w8ZAO8AbAa3AK4EoAenALgCrgIiAJyWAAD+DwIAOgHGABAC9AL8AvYP/AL0AhACoJYAAP4PMgDOCQQEbAFkDWwJZAtyCeoBAAyjlgAA/g8yAM4AAAnuBZgDvwCYA+oPqAIAAKeWAAD+DzIAzAhABLYHgASqCfgMyAvOCCgJqJYAAP4PMgDMCOIHFATUC+wI7gl8DewPBAiqlgAA/g86AcYIUAS4AvQAEwj0BrgE6AwIALGWAAD+DwIB/gDADfYB8gf6C/IN+QH1DaAItpYQBFQFVAVUAlQK/gdUAVQCVAO8BJAEAAC7lhAIEAl4CXwJeAd4BXwFeAV4B3gJSAgACL6WAAAUBqQB5AAcAyAA/g+oBPoHqASoBAAAwJYAAFAAWADED+AK3grwCvAPxArECtgKEADBlgAG/gFCAPoHAgAiAPoHUgX6B1IFUgUAAMSWCAzoAx4IyAcIBCAD/AeqBKgE/AeqBKgExZYkBrwBZAj8ByQA8A+uBKgE/geqBKgEAADGlggICAV8BV4DXAPcD34BXQNcBVwFRAkAAceWAAAEDvwBrADsD+wK7ArsD+wK7Ar8CgQIzJYAAPAPAAT+BwAE/gcwAv4PqAT6B6gECATPlhAAuASmBLQE7A8gAPgPrgSoBPoHqAQIBNGWJAC0BI4ChA+8AkAEMAD+B0gF/AdKBUgF1ZaAD3wANAe0AjQJ/AcwAPwPqgT0B6gECATWlgAA7gSqBPoDrgLgBjAA/g+oBPoHqASoBNmWAAAICL8EvAS+BbwGiAK+ArwFvgW8BCQE3JYgAKQGlADGD7QCAAD+D6gEqgT6B6gEqATelgQIfAl8BaoDUg04AfwPqgSoBP4HqAQIBOKWgA/0ANQD1gLECPQHIAD+DygF/AcqBQAE45YAAPQJ1gX0A9YF9AUgAP4PqAT8B6oEqATolgQA9A8UAFQBFAD8DxQAVAFUChQI9A8EAOqWGADKCsoKygqKCr4KigrKCsoKyg8YAAAA75YACJgIygjqCcoGngTKBIoG2gnKCJgIAAjwlgAKGAmaBboFCgM+ARoJOgmKBxgBAAIAAPKWAAEMBWUFZQdFBV8FRQVlB2UHBQ0cCQAA85YcDMYDdgh2CX4HRgF2CXYJdglGCVwHAAD2loAAmACaAboFSgXeBcoFWg26C4oBmACAAPeWGADKD8oKygqKCr4PigrKCsoKyg8YAAAA+ZaAAJgA+gf6CuoK/grKCvoLegrKCRgEAAD7lgAAGADaB/oCygLeB9oK+grKCxgIAAYAAP6WAAFYC1wLXAvMBtwC3AJ8C0wLXAcAAAAAAJcAAFgAWg96AUoP3gFaD3oBSglYB0AAAAAElwAAHgAOCK4HhgHeBYYG1gLeCoYHHgAAAAaXAAhMCeYFdgsmCD4NRg32D3YNZg0MDQAAB5cYDNoDegn6B8oF3gXKB/oF+gXKB1gLAAkJlwAADAFmBeYG5gbGB94Gxg7mDuYHTAUAAAqXAAg4CYoLqgmKD74Jig+qD6oJCgs4CwAIDZcAAQwBpg+2C4YL3g+GC7YLpguMCAAAAAAOlxgCWgtKC2oLyg9uD0oPWgf6B0oLWgsYCBOXAAAOAA4I1guuCq4GBgKuBr4K5gsOCAAEFpcAAJgEigK6D4oCPgCKBroBug+KApgEAAQclwAAmAS6AroPugI+AL4H+gX6BfoFyAcAAB6XGADKD/oF+gXKBd4MCgj6C/oFygXYCwAIJ5cAAAAMTAPmD/YBRgMeCsYGdgPmC0wHAAEylxgIyg16CXoPygueAooOegv6CkoPWAIAADiXAABMB+YH9g/GB14DBgz2A/YC5grMBwAAOZcABuwBdQdtBW0FBQcvAuUCpQ+tAu0CoABClwAO7AFlBP0E/QZ1BOcHZQb9BvUG9QQgAEiXAAgMCeYL/gtGCa4PpgnmDU4LtgjkCAAAUpcQABQA/A+8ArwCvgK8ArwKvAr8BxQAEABWlwgC6AIOAugBAAD8D7wCvgK8CrwK/A8UAFmXEADcD9wC3grcDxAAWAlWCfQHXAHwAUAAXJcQCNwH3ALeCtwHAACIAqQK6geiAuoDgABelwABKAEoASgB/g8AAAAA/g8oASgBKAEAAWCXAAQIB3wHXgdcD1wAXgBcD1wHfAcIBwAEYZcADvwBBAQ0B3QHVA8GADQPdAc0B1QHAABilwAA8g8SBPIHXgVSBfIHEgQSBPIPAgAAAGmXAAAEAuQCvgK0AvQPtAK0Ar4C5AIEAgAAdJcEAu4C/A+uAuQCAAIwAP4PAAD+BxAICAZ2lwQA7gKsAvwPrgJAAP4HQgh+CEII/ggABouXAADkAq4C/A/uAgQKIAgkCb8PJAkkCQAAjZcEAO4CrAP+DuQCAABICcYJdAZEBegEQAiRlwQC7gL8D64CZAjgBwQIkAt+CNAIEAsAAJiXBAD+ArQC9A++AkAI9AcQAF4BEAn0BwAAoJcEAv4C9A+0Au4C/AaKA+gP6AGICvgHAACtlwQC7gL8D24A/g98CawH/ASsCPwIBAgAANOX/AKsAq4PrAb8BgAE7AeuBawPrAXsBQgE5pcAAJIAkgCSAJIA/w+SAJIAkgSSBIADAADnl6gAqAD8D6gAqAIAAXQMhAN8CAQI/AcAAOmXAAD0AtQC3g/UAvQCAACoAP4PqACoBIgD7ZcAAFAFUAVQBf4HAAQABP4HqASoBKgEAADzlxAAFADUB1QFVAVWBVQFVAVcBdQHFAAQAPWXIADoB2YFdAXkByAAEAEuBagICAj4BwAA9pcQANwHVgVcBdQHBACwB44EogSiBJ4HAAD7lxAA3AdVBVoF1AcEAPgPVANUA1QD/A8ACP+XlAC+ANUH4Af+B+4HzgfAB94HxgeaAAAAAZgACAQI/AusBqwGrAKsAqwGrAb8CwQIAAACmAQIBAj8DwQAAAj8C6wKrAKsBqwG/AsAAAWYBAEEAfwBBAEECPwHrAasAqwGrAb8CwAIBpgACPwHAAD4AwAA/g8AAPwHrAasAqwK/AsImEgIyAQkBBADBAj8C6wKrAKsAqwK/AsACBCYJAgkCPQPPADkCAAI/AusAqwCrAr8CwAAEZgAABQH9AAUAvQDAAj8B6wGrAKsAvwLAAgTmOgAiAD8D4gE6AIACPQHtAa8ArQK9AsAABeYAA74ASgMvAKoA1gI/AusCqwCrAb8BwAIGJgAAFgA1AdSAMQJDAT8B6wCrAKsBvwPAAAtmAAAfAhMBUwEfAcADPwJrAqsAqwG/AcACDuYEADeBRAEfwIUAZAA/g1WA1YDVgH+BQAEPJgAAHgGWAH8D1gBOAr8CawGrAKsBvwHAAhGmAAEvASsAvwPrAKcCPgJrAqsAqwG/AcACEyYQAxcA1wE3AdcCQAM/A1cCVwJXAn8DQAMTZggAawPtAVWBaQHDAD8B6wGrAKsCvwLAABPmAAM7AM8CK4JLAUkAvwLrAqsAqwG/AcACFSYAAzkAywIpgosBSQA/AusCqwCrAr8CwAIWJgAD/wAfAasAKwP/AEACPwHrAasAvwLAAhbmAQK/AvcCt4C/AsAAPwHrAasAqwG/AsAAF6YAACsBJgC3gGcAogI/AusBqwCrAL8BwAIZ5gADvoBKg+qB9oHgAcCCPoLrgaqAvoHAgxvmAAB/A3aARoJ+gO8AwAJ/AesBqwC/AsACHWYAAAECPQLFAgUBBQC3AEUBBQI9AsECAAAdpgAAAQIBAj8BwQAAAj6CQoE7gMKCPoJAAB3mAAAAAD8AxACEAEACPQFFATcAxQE9AkECHmYBAEEAfwBhAAACPoFCgQKA+4ACgIKBPoFepgADPwDAAD4AwAA/g8AAPwIDAbsAQwC/Ax7mAAESAQmApABAgj6BAoC7gEKAAoC+gQCCH2YAAASBvIBEgDyBwAC+ggKBu4BCgD6DgAAfpj8DwIA+gcKBPoCAAj6BAoG7gEKAPoOAAB/mAAA9ACEAP8PhARgAvoICgbuAQoA+g4ACIGYMAwMAuIJIAjvBxAA+gkKBO4DCgj6CQAAgpgwBAwD4gIAAt4HAAD6DAoC7gEKAPoNAASEmCIAKgjqBzYA4gAACPoECgbuAQoA+g4AAIWYAAjwB5AAngD0AQAI/AkMBOwDDAj8CQAIhpgQAFABTAJqDdAAAAj0BBQG3AEUAPQOAAiHmAAO/AEkDD4D5AYMAPAEFAbcARQA9A4ACIiYAACiCJIIige2BAAM+gkKBO4DCgj6CwAAiphIBFgESAP+AHgDSAjgBBQC3AEUAvQEAACRmCAAuAsgCPwFKAMgCPQJFATcAxQE9AkAAJOYAAAsCKwHvACqBwAE8ggSBt4BEgTyCQAAlpgABM8C1AHUD7IBAAryCBoG1gESBPIFAAiXmAAE/ATUAvwP1AH8AOAJFATcAxQI9AkAAJiYQAxcA1wE3AdcCQAM9AwUC9wIFAr0DAQMnJgACPIHGgGzBKoCEgj6BAoC7gEKAPoOAACdmKwAFAZeBXQFlA4cAPQJFAbcARQA9A0ABKCYBAr8C+wK7gL8CwAA9AkUBNwDFAj0CwAApJgACPwL/Av+C8wLPAPwCAoE7gMKCPoJAAComAAAAA78AQQE7AUsBfwHLAXEDPwHAAgABLGYAA7+AUIE+gNCAv4AAAPYBFYJUAncDQAAxJgEAPQN/AH8B6QP/gdmBPYD+gP6BwQIAATGmEAGygFqAGcG6wFiDP8DYQT9A2EH/wEABs6YAAAADv4BAgQaAqIB4gAaBwIA/gcACAAG0pgoBMoEDgLsAwAK/AcEAvQBBAL8BwAMAADYmHQN1AH8CdQH/APUASQN/AMUBuQB/AcADNuYUAhSBvoBQgBCAPoPQgBCAM4DFAUqCUgF3pgAAAQABAAEAAQABAAEAPwAIAdQCIgIiAbfmAAAEAAQCPgPtAiyCbQCtAb4CZAIEAgAAO+YCATkB9IE0gT0BgAO/gFiDKIFIgPiBAAI8pgIBPQHsgSyBPQGIAAcDIoD+AAIAzgECAj8mBAE/AeyBLIE9AYAAOwDLAHsCQQI/AcAAP2YCAAIBPwHugS6AvQGAAD4A5YE9AQEBPwE/pgQBPwHsgS6BPIGNAToASYA/A8kAOQDAAAFmQQA8g9aCVoF8gkAAIoM+gOIAP8PiQAAAAqZgACUAFwI/g/cCdwJ3AfcBf4NXAiUCAAAEJkQAJAAqAjuD9wLgAO2B9YHlgWuCKIAAAATmQQI8gdxBnUDIQSJBP8DWAAfAvgD2wYQABiZCAjsD1oJVgX0DQQAlAKUCPMHlACEAogEKJkQBPgHtASyBOwGHAD0D5QFlgWUBfwHAABSmQAA8A++BLIE9A5AAGoNegNvASoP+g0oBWWZMAAMCOoPCAQ4AAAO/AEEAAQA/A8ACAAGbZkwAAwIygcYAAAO/AE0DNQCFAPyBBIIAABumXAADAjqDwgEOAIACDAEDgPoAAgDKAQYCHCZIAAUAMoPGAIAAOgDJwAkAPwPJAAkAuQBcZlgABQAyg8YBEAA8AcsCSgJ6AsICvgJAARymTAADAjKBxgCCADiAyoBKgHqCQII/gcAAHWZcAAMCOoPCAQwAAQE/AeUBJQElAL8DwQCdpkgABQIygcYAggIoASuA7gApA/UCJQIAAR6mTAACgjlBwQCCApgCBQEhQOGAwQEdAhABHyZIAAUCMoPCAS4AoEI+geIAIgA/A+LAIAAf5kgABAAzg8YBIAClAj8DxAE/gKQBVYIAAaAmSAAHADKDwgEGACQBpgAlAjyD5QAmAKQBIGZIAAUCMoHGAIACFQJxAVsAkQDwgRaCEAAhZkgABQEygcIAjgA0A9IBQYFRARcBcQPAACGmSAAFATKBxACBAD8B/QHVQVWBWQFDAcAAIuZMAAMCMoHGAKQALgCbgQ8BWwJrAq4AIAAjZkgABQEygcYAwAIdAV2BXQD9AF2A3QFAAiPmTAAjg8oBBgEQAA+D7AK5A+cCoQKvA8AAJKZEAAcAOoHCAFgBN4F/gbeAv4G3gX+BAAAlpkAAAQA9A9XBVQFXAVUBVQFVwX0DwQAAACZmZAAVABUD7QKlAq8CpQKsgrSCtIPUACQAKiZAAC8ArwC/g78D/QP+A72DvIP/g7YAgACrJkACAAM/AFUAVQFVAH8DVQBVAtUCQAHAACzmQAG/gCqB/4CqgoAB/wHEAj+CRAI+AgABsGZAAb+AKoC/gmqC6oHAADWDAgDDgXRBBAIxZkABv4AqgP+C6oOgA3+AyIA4gAiAz4MAADGmQAG/gCqBv4CqgsAB/4PAgSiBXIEigUABdCZAA7+AKoG/g6qCaoHAACKCPoPjAiICAAI0pkABv4Aqgf+AoIKEAfMASoB6AkICPgHAADVmQAAFAjMBeYB5AXsAeAD/gHyA/IFHgMAANuZAAN/ANUDfwNVBcEDHAwkA/8CJAQ8BAAI3ZkABv4Aqgf+A6oPAAAYAPgHjgiICFgIQAb/mQAG/gCqBP4Bqg8AADwHigS4Bq4JIAgAAA6aAAb+AKoD/guKByAApAe0Aq4LNAjUByAAEpoABv4Aqgf+A4oPQACiCWYJ+g9aCeYNIAgTmgAG/gCqA/4GqgoKB+gIJgXyAyQH6AkICBmaAAb+A6oB/gmAD/wH7APsB+oDagX6BwAAMJoADP4Dkgj+B0QA9gXcC9YL3Af2C1QGQAA3mgAO/gCqAv4LqgcAAPQJagnSD2oP5g8gCEWaAAb+BqoB/gmCBwAA/AdUCuwLnAnECwAAVZoABn4H/gKqCQIHqA/6A94F2gf5AKkPAABXmgAG/geqAf4NggNwCLgG9gBUDLgC0AwAAFqaEAg6DP4D+gP6C9oDyAvsA9YLrAssBiQAX5oADv4Aqgf+DgAHfga6AP4PbAAUAywEAABsmgAAAAIEAnQCRAJEAkQCRAp8CEAHwAAAAG6aAAJ6AkIJQgj+BwAAEAyQA34AkAEQBhAIb5oAAnoCQglyCM4HAAD+DwAA/gcAAP4PAABwmgACegJCCkII/gcAAPwHEAj+CQgI+AgABnGaAAB6AkIKQgn+B/gPBAgUC+QIlAkECgAAc5oAAnQCRAlECPwHAABUDIgCiANUBBIIAAB0mgAAegJCCkII/gcAAPgPSABKAEgA+AAAAHaaAAJ0AkQIRAz8AzAISAVIAv4FSAR4CAAAeZoAAnoKQgl6CMYHEADOAykB6AkICPgHAAB7mgAAegJCCkIK/gcAAIgIiQj6D4gIiAgICHyaAAB0AkQJRAn8BwAA6AeKCGwICAgYBgAAfpoAAAQCLAKmAqQCrAKgAr4C8gqyCJ4HAACCmgAADgKqAqoCrgKgAq4CqgLqCI4IgAcAAISaAAJ6CkIJfgjABxAAVAw0AxwAMg9SAEAAhZoAAPoCggr+CIAHEAB/AQAPPgFIAUYBIACGmgACegJCCWII3gdAAEgPtgSkBLQETA9AAIeaAAJyAkIJQgj+BwAIqAS5Am4CCAPIDAAAjJoCAnoBQglCCP4HIACYBSQEpgUIBNAHEACPmgACegJCCkII/gcAACwJqwaJBKgHrgggCJGaAAB0AkQJRAn8BwAApAesAq4LNAj0DyAAl5oCAnoBQgl+CMAH/AOUD9YH1A9UAdwPAACamgACeglCCX4IwAeSCFYJ3gdaBVYH0gcgCKGaAAB6AkIJQgj+BxwN6gF+CSoPqgG+CwAKpJoCAnoBQgh8CuIFvga6Bb4PagPSBS4JAAComgAAYAAgAPwP5AL8AuwC7Ar8DyAAYAAAALiaMAD+D/YC/gr+BzAABAm0BK8CZAIUBcQI0ppgCPwH5AB8CvwHQAC0CnYGUAK2DrQCAADTmjAA/g/+Av4PdABwCNwHBgjkC/wJ7AsACNSaYAz8A3wJ/A8AAHwI7Av+CuwO/g7sC3wA2JoAAAIAwg9eAFYPVwVWBVYHXgBCCMIHAADmmgAAEAS+Bd4FvgK+B4ALZAtqCxQLFAoAAOqaAADQCP4E3gLeCf4H0AWEBdIHqgmqCKAI7poAALAEvgK+Cr4JvgawBoQE0gaqBKoEkAgGmwAAsAS+Ar4PvgI+ALINAAZsBGoGkggQARObAADQCl4G3gfeB/4DzgPkB+oHWgdSCgAAJZsAAP4PAAA+ACoAAAAqAD4AKggACP4HAAAnm/4PAACuB64ApgDwD6YArgSuAwAI/gcAADGbAADsAa4NrAt0B34H9gE2CGgJLgRsAwQAPJsAAAAIfARUAtQBfgBUB1QIVAt8CwAKAAhBmwAAfAxUA/4HVAh8CwAKrAiACP4LQAgABkKboANkAiQBpAEACHwEVAJUAf4HVAl8CwAERJsAAPgHTgL4AwAIfAZUAf4HVghUC3wLAAhFmwAAfA/UAP4HVAt8CgAK6Aj+C2gIqAkABE+bAACsCpwH3ASaB4AAPA5UAf4HVAi8CgAKVJsADPwDBAi0C7QLlgfEA7QHtA+0D5QLAAhamwAIMAj4BVQBVg30AVwFVAlQAfAFAAgAAG+b0AAIALgPvgr8CrwK/Ar8CrgKeA+AAIAArpsQDPgBVg30A1wB4AUJAE4B+A9MAUoBAADomxAM+AFWBfQDXAHwBGQClAiWB5QA9AYAAHycAAAQBPgFVAVWBVQF9AVcBVAF8AUABAAAgZwIAEgA+A/+CvwK/Ar8CvwK+Ar4D0AAAACNnCAI+AlWBfQFXAX0BRAA7AfoCQgJ+AgABJycEAD4BVYF9AVcBfQFAAFKAfgPTgFKAQAApJwQAPgFVgX0BVwF4AE8CFQJ/A9UCXwJAACrnBAA+AFWBfYFXAXgBPwHVAI8APgPBAD8A7icEAD4BVYF9gVcBfQFAAB0A1QI1gdUAHQDxJwQBPgF9gVcBfQFAACcAowLqAq0CrwGgADNnAgA/AL7Aq4CeACSD1YFfwV2BW4F7w8FANacAAF6CTgPfg+4D7oPkA+uDzQPLA9ECEAA3pwQAPgF/gX0BAABqgyYAz4AmAKuD6gCAADlnAAIAAT8AVwBXAVeAV4FXAFcBVwJQAcAAPOcAADgDxwE/AH8BfwD/Av8CQwH/AcACAAG9JwAAPwDBAH8CQAE/AFcCV4DXgtcCVwHQAAonQAA/AGUAPwPlAD4DPwBXAVeA1wLXAcAADudEAgiDqQBBAD8CQQM/AFcBV4DXAtcBwAAXZ0AAJII/gcQBv4N1ADoBVwDXglcC1wHQAC0nUAA7A9cBfYHVAUECPgFXANeBVwLXAdAAPmdAAD8DwIAuguOB8oP/w++B74Hvg8mBgAAH54AAQABfAFEAVQBVgFEAWQBZAlcCMAHAAAgngAACA/+AAgA+AGAADwATgFmCWQI3AcAACGeFAQ0AsQBPAMAAPwChAKWApYKpAicBwAAI54AAPwDBAH8AQAA/AKEApYChAq8CIAHAAAlngAA/AcEBuQFFAUABPwAjAKmCqQInAcAACaeAAA0ACQL5Aj8DwAA/AKMAqYKpAicBwAALZ4AAPwBlAD8D5QA+AB8AowCpgqkCpwHAAAvnkAAUATcB3QGdAbUBl4GVAZ0C9wKUAZAADOeJAISAvoDMwNuAyADLgOyC7oLfgkQBwgANZ4AAvwClgKECLwHAADoB4oIjAhICFgIAAY9ngAAsA+IBKYErAcAAPwChAKWCqQInAcAAD+eEAgmDyAABAL8AQAA/AKMAqYKpAicBwAAQ54AAPwPtAK0ArwKwA18AowCpgqkCpwHAABFngAAFAn8BxAA/gfcCAAK/AKOAqQKnAcAAEmeAADsBwwEyAP/AwoMAAj8Ap4KhAi8BwAASp4AANQHXgVUBV4F1AcAAvwClgqECrwHAABPngAM/gOSCP4P/AeSAP4PeAKeCoQKvAcAAGSeQADsD1wFVgX0B1QFAAD8ApYKhAq8BwAAZp4AAH4JMgteDUwFMgtOCPgCpgK0CpwIgAdwngAAwA88AIQH/AbOB/wH/Ab8CvwKfAYEAH+eAACAD3wAVA90CVQJVgB0B1QJVAl0CQAEl54AAAAO6gGqD+IK+grgAOoH+griCuoKAAifnoAPfAB+D3QEVA9gAWoNmAM+AJgCyg+AAqWeVABUClQJJAWkBp4CpAI0BVQIVAhUAAAApp4gCSwJrAjsBawGvgSsBqwFrAgsCCAIAAC1ngAAlAukBp4EpAcACPoL/gv6CwoK+gsACLieAACcBXwEXgLcBVwAAAxIA/4ASANIBAAIu54ADPwDBACkAfQPpQAGAqQB9A+kACQDAAC8ngAG/gEKADoFmgWqBwMFKgWaBCoGKggAAL2eAAz8AwQAVAr0ClQMBgs0CPQKNA5UCAAAw54ACBQI9Ae+BrwC/AO8ArwGvgb0BxQIAADEngAAEAj0C7QKvgr0A7QCvga0BvQLEAgAAM2eKAGsAKwEXARMAzwKTA9cAqoCqgSoBAAAzp4AAGoBGgW+BKkCiA5IApYCjAREBTwBAADPnqAEmgJaCD4HWgDZBggAwA9+BEgEyAcAANGeAAAACV4FVgFSDf4BUgVWCVIBXgUACQAA0p4AAAANfgFqAWoN/gFqBWoJagF+BQAJAADUngAAfg1mBf4Beg1+BQAAkACIAKYMiAOwANieAA5+AGYF/gNqAX4FAACQD34AkAMWBAAI2Z4AAFwNXAH8AVwFXAEAAcgGPgBIBIoFAAHbnggIBAruC6EDpAvmA6QL7gu2A/QLFAoUAN6eAAx8AWwF/ANkATwDgA+ABP8EiASIDwAA354ADn4AagX+AWYFfgEIBSgJ9ga0BowBgADongAADArkC74DvAv+A7wL/Au+A+QLDAoAAO+eAAx+AWYN/gFqCX4HwAd0BWYFdAXkBwAADp8AAHwJQAd+Ae4PLgDuD34BQAF+AQAPAAATnwQEdAW0BL4EtAfgDWgEqAU+AqgFaAwABCCfAAAAAL4PKgmqAOAPKgiqCioAvgcACAAEO58ACsAL/Av8B/wD/gP8A/wP/APAA8ADAAJKn0wIfAzMA8wCtAKMAvYCvAKsAuwPFAAgAEufAABQADQPlAAkDIwBpg+UBSQAVA8kAEAAUJ9AAEQIRARMAzQAJgAmADQATA9EAEQAQABSnxAA8A/wD5wIsAqQCN4I1ArUCpQI0A8QAGGfAADsB/AH3gb0B9QHAAA4AWYCSA2QACAAYp/wD/wF0AXeBfQPEAAIAPQPdwBoBLADAAB/nwAA8AfwBxwEEAWQBF4ElAQUBRQE1A8QAISfAADeBxAF3gQUBNQHEABIAVYCRA3IAFAAjZ8AAPIPugKzAroK9gcAAO8HqguqCzoKAASQnwAM/AMECOQH1AbUAgYPtAO0D7QP9A8ABJmfEAgQBBAC0Ak+CBAE8AcSCZQIVAhQCBAEnJ8AAOgH+Af+B/wHTAr8C1gL2ApYCsALAACfnwAAEAD4A1QBVgH0B1wJVAlQCfAJAAgABgCsAAAEAgQBhABkABwAAAAAAP4PIAAgAAAAAawAAEQARAEkATQBDAEAAQABfg8QABAAAAAErIAARABEDyQIFAgMCAAIAAj+CRAAEAAAAAesgABEAEQPJAk0CQwJAAkACX4JEAAQAAAACKwgACQApA6kCpQKjAqACoAKvgsIAAgAAAAQrIAARABEDyQJNAkMCQAJAAl+DxAAEAAAABGsQABEAEQPJAo0CgwKAAoACn4PEAAQAAAAEqwAAEQARA9ECjQKDA8AAAAMfgMQBBAIAAATrEAAhAhECCQEFAIMAQACAAT+CBAIAAAAABWsAACEAEQGRAk0CQwJAAkACX4GEAAQAAAAFqwAAEQARAkkCTQFDAMABQAJfgkQABAAAAAZrEAARAAkD6QKlAqMCoAKgAq+ChAAEAAAABqsAACAAEQIRAkkDxwJAAkAD34JEAAQAAAAG6wAACQApACkBJQKzAqACoAKvgQIAAgAAAAcrAABBAGEAGQAHAAAAP4HIAAgAP4PAAAAAB2sgABEAEQBNAEMAQABfgEQARABfg8AAAAAJKwAAEAAJACUDpwKgAq8CogKiAq+CwAAAABArCAAJACkDqQKlAqMCoAKgAq+CxQAFAAAAHCsAAAEAwQBhAB0AAwAIAAgAP4PAAAAAAAAcawAAEAARABEASQBHAEEARABEAF+DwAAAAB0rAAAgABEAEQPJAgcCAQIEAgQCP4JAAAAAHesAACAAEQARA8kCRwJBAkQCRAJfgkAAAAAeKwAAEAAJACkDpQKjAqACpAKkAq+CwAAAACArAAAgABEAEQPJAkcCQQJEAkQCX4PAAAAAIGsAABAAEQARA80CgwKAAoQCn4PAAAAAAAAg6wAAIAARAhECCQEHAIEARACEAT+CAAIAACJrAAAQAAkAKQPlAqMCoAKkAqQCr4KAAAAAIysAAEEAYQARAA8ACAAIAD+BwAA/g8AAAAAkKwAAIQARAAkDxwIEAgQCP4JAAj+CQAAAACcrAAAgABEACQPFAkcCRAJfgkACX4PAAAAAKisAAAEAgQBxAAkAJwAkACQAP4PAAAAAAAAqawAAEAARAAkASQBFAEMASgBKAF+DwAAAACqrAAAQABEASQBJAEUDwwAKAEoAX4PAAAAAKysAACAAIQARA4kCBQITAhICEgI/gkAAAAAsKwAAEAAJACkDqQKlAqMCqgKqAq+CwAAAAC5rAAAQABEAEQPNAoMCigKKAooCn4PAAAAAL2sgABEAEQGJAkUCQwJKAkoCSgJfgYAAAAAwawAAEAARAAkD6QKlAqMCqgKqAq+CgAAAADErAACBAPEACQAnACQAJAA/g8AAP4PAAAAAOCsAAIEAgQCBALkAwQCBAIEAvwCAAIAAAAA4awAAEAARAFEAUQBdAFEAUQBXA9AAAAAAADkrAAAQABED0QIRAh0CEQIRAhcCEAAAAAAAOesAABAAEQPRAlECXQJRAlECVwJQAAAAAAA6KwAACAAog6iCqIKugqiCqIKrgsgAAAAAADwrAAAQABED0QJRAl0CUQJRAlcD0AAAAAAAPGsAABAAEIPQgpCCnIKQgpCCl4PQAAAAAAA86wAAEAIRAhEBEQEdANEBEQEXAhAAAAAAAD1rAAAQABEBkQJRAl0CUQJRAlcBkAAAAAAAPasAABAAEIJQglCBXIDQgVCCV4JQAgAAAAA/KwAAAQCBALEAwQCBAL8AgAA/g9AAEAAAAD9rAAARABEAXQBRAFEAVwBAAF+DxAAEAAAAACtAACEAIQO5AiECIQIvAgACP4LIAAgAAAAEa0AAEQARAZ0CUQJRAlcCQAJfgYQABAAAAAcrYAAhAD0DoQIhAicCAAI/gkQCP4LAAAAADStAAAEAgQCxAMEAgQCfAIAAP4PAAAAAAAASa0AAEQARAZ0CUQJRAlcCQAJfgkABgAAAABQrQAAAAIEAsQDBAIEAsQDBAL8AgACAAAAAGytAABAAEQARABEAMQPRABEAHwAQAAAAAAAba0AACAAJAEkASQB5AEkASQBPA8gAAAAAABwrQAAQABEDkQIRAjECUQIRAh8CEAAAAAAAHOtAAAgACQPJAkkCeQJJAkkCTwJIAAAAAAAdK0AACAAog6iCqIK4gqiCqIKvgsgAAAAAAB1rQAAIACiDqIKIgsiCKIAogC+DyAAAAAAAHatAAAgAKIOogqiCuIB4g+iCL4PIAAAAAAAfa0AACAAIg8iCiIK4goiCiIKPg8gAAAAAAB/rQAAIAgiCCIEIgRiAyIEIgQ+CCAAAAAAAIGtAAAgACIGIgkiCeIJIgkiCT4GIAAAAAAAjK0gACQAJA8kCOQJJAg8CIAI/gsAAAAAAADArQAAQABEAEQAxAdEAHwAQAAAAP4PAAAAANOtIAAkACQI5AkkCCQEPAMABP4JAAgAAAAA3K0AAEAARADED0QARABEAMQPfABAAEAAAADgrQAAQABED0QIxAlECEQIxAl8CEAAAAAAAPitAAAAAgQCBAIEAgQCBAIEAvwCAAIAAAAA+a1AAEABRAFEAUQBRAFEAUQBfA9AAAAAAAD8rQAAQABED0QIRAhECEQIRAh8CEAAAAAAAACuAAAgAKIOogqiCqIKogqiCr4LIAAAAAAAAa4AACAApA6kCqQLJAikAKQAvA8gAAAAAAAIrgAAQABED0QJRAlECUQJRAl8D0AAAAAAAAmuAAAgACQPJAokCiQKJAokCjwPIAAAAAAAC64AAEAIRAhECEQERANEBEQIfAhAAAAAAAANrgAAQABEBkQJRAlECUQJRAl8BkAAAAAAADCuAAIEAgQBhABkABwAAAAAAP4PAAAAAAAANK6AAIQARA4kCDQIDAgACAAI/gkAAAAAAAA4rgAAQAAkAKQOlAqMCoAKgAq+CwAAAAAAAECugABEAEQPJAkUCQwJAAkACX4PAAAAAAAARa6AAIQARAYkCTQJDAkACQAJfgkABgAAAABKrgAAhABECEQJJA8cCQAJAA9+CQAAAAAAAEyuAAAEAeQAHAAAA8QAPAAAAP4PIAAgAAAATq4AAEQAJAEcAUAPJAAcAQABfg8QABAAAABQrgAARAA0DwwIwAgkCBwIAAj+CRAAEAAAAFSuAAAkAJwOhAqgCpQKjAqACr4LCAAIAAAAXK4AAEQAJA8cCUAJJAkcCQAJfg8QABAAAABdrgAAZAAUDwwKQAo0CgwKAAp+DwgACAAAAGGuAABEACQGHAlACSQJHAkACX4GEAAQAAAAZa4gACQAlA+MCoAKtAqMCoAKvgoQABAAAABorgQBxAA8AAADxAA8AAAA/gcgAP4PAAAAALyuAAAEAcQAPAAAA8QAPAAgAP4PAAAAAAAAvq4AAEQANAEMAUAPJAAcARABfg8AAAAAAADNrgAAZAAUD0wKQAokChwKEAp+DwAAAAAAAM+uAABEADQIDARABiQBHAIQBP4IAAgAAAAA0a4AAEQANAYMCUAJJAkcCRAJfgkABgAAAADYrgQBxAA8AAACxAE8ACAA/gcAAP4PAAAAAOiuQAAkABwAAA9kCRwJEAl8CQAJfg8AAAAA9K4AAAQDxAA8AAACxAG8AJAA/g8AAAAAAAAsrwAAAAIEAmQCHALAAwQCBAJ8AgACAAAAAC2vAABAAEIBQgFOAWABQgFCAV4PQAAAAAAANK8AACAAog6qCqYKsAqiCqIKrgsgAAAAAAA8rwAAQABCD1IJTglgCUIJQgleD0AAAAAAAD2vAABAAEIPWgpGCnAKQgpCCl4PQAAAAAAAQq8AAEAAQglCCU4FYANCBUIJXglAAAAAAABDrwAAQABCCVoJRgVwA0IFQgleCUAAAAAAAEmvAABEAFwBQAF0AUQBXAEAAX4PEAAAAAAAZK8AAQQBPAGAAQQBfAEAAP4HQAD+DwAAAAC4rwAARABEAEQAfADAD0QARAB8AEAAAAAAALyvAABAAEQORAh8CMAJRAhECHwIQAAAAAAAwK8AACAAog6iCr4K4AqiCqIKvgsgAAAAAADIrwAAIAAkDyQJPAngCSQJJAk8DyAAAAAAAAywAABEAEQAfADAB0QAfABAAAAA/g8AAAAARLAAAAQCBAKEAnwCAAIEAgQC/AIAAgAAAABIsAAAQABED0QIfAhACEQIRAh8CEAAAAAAAEqwAAAgACQPJAg8ACAFJAukCzwFIAEAAAAATLAAACAAog6iCr4KoAqiCqIKvgsgAAAAAABTsAAAIACiDqIKvgsgACIFogs+CyAFAAAAAFSwAAAgACQPJAk8CSAJJAkkCTwPIAAAAAAAV7AAAEQIRAhECHwEQANEBEQIfAhAAAAAAABdsAAAIACiD6IKvgqgCqIKogq+CiAAAAAAAHywAAAEAeQAHAAAAsQBPAAAAP4PAAAAAAAAjLAAAEQAJA8cCUAJJAkcCQAJfg8AAAAAAACYsAAA/AEAAQABAAEAAQABAAD+DyAAIAAAAJmwAAB8AEABQAFAAUABQAEAAX4PEAAQAAAAmrAAADwAIAEgASAPIAAgAQABfg8QABAAAACcsAAAfABAD0AIQAhACEAIAAj+CRAAEAAAAKCwAAA+AKAOoAqgCqAKoAqACr4LCAAIAAAAobAAAD4AoA6gCqALIAigAIAAvg8IAAgAAACosAAAPAAgDyAJIAkgCSAJAAl8DxAAEAAAAKmwAAA+ACAPIAogCiAKIAoACn4PCAAIAAAAq7AAAHwAQAhACEAEQANABAAE/gkQCBAAAACtsAAAfABABkAJQAlACUAJAAl+BhAAEAAAAK6wAAA8ACAJIAkgBSADIAUACX4JEAAQAAAAr7AAADwAIAkgCSAFoAMgBQAJfAkQCBAAAACxsAAAPgCgD6AKoAqgCqAKgAq+CggACAAAALOwAAA+AKAAoASgCqAKkAqACr4ECAAIAAAAtLAAAPwBAAEAAQABAAD+ByAAIAD+DwAAAAC1sAAAfABAAUABQAEAAX4BEAEQAX4PAAAAAMSwAAB8AEAAQA9ACQAJfgkQCRAJfg8AAAAAxbAAADwAIAAgDyAKAAp8ChAKEAp+DwAAAADHsAAAfABACEAIQAQABH4DEAQQBP4IAAgAAMmwAAB8AEAAQAZACQAJfgkQCRAJfgYAAAAA0LAAAPwBAAEAAQABAAEAAQAA/g+QAJAAAADlsAAAfABABkAJQAlACUAJAAl+BigAKAAAAAixAAD4AQABAAEAASABIAEgACAA/g8AAAAACbEAAHwAQAFAAUABQAFIAQgBCAF+DwAAAAAMsQAAfgBAAEAPQAhACEgICAgICP4JAAAAABCxAAA8ACAAoA6gCqAKqAqICogKvgsAAAAAE7EAADwAoA6gCqALKACoDwgKCAq+DwAAAAAYsQAAfABAAEAPQAlACUgJCAkICX4PAAAAAB2xAAB8AEAGQAlACUAJSAkICQgJfgYAAAAAI7EAADwAoACgBKAKqAqoCogKiAS+AAAAAAAksQAA+AEAAQABIAEgASAA/AcAAP4PAAAAACWxAAB8AEABQAFIAUgBCAF+AQABfg8AAAAAKLEAAHwAQABAD0AIUAgQCPwJAAj8CQAAAAAssQAAPAAgAKAOoAqoCogKvgqACr4LAAAAADexAAB8AEAIQARIBEgCCAF+AgAE/ggACAAAQLEAAPgBAAEAAQABUAFQAVAAUAD+BwAAAABBsQAAfgBAAUABQAFAAVQBFAEUAX4PAAAAAESxAAD+AIAAgA6ACIAI1AgUCBQI/gkAAAAAULEAAH4AQABAD0AJQAlUCRQJFAl+DwAAAABVsQAAfgBABkAJQAlACVQJFAkUCX4GAAAAAHixAAAABHwEQARABMAHQARABEAEAAQAAAAAebEAAEAAXgFQAVABcAFQAVABUA9AAAAAAAB8sQAAgACeDpAIkAjwCJAIkAiQCIAAAAAAAICxAABAANwO0ArQCvAK0ArQCtALQAAAAAAAiLEAAEAAXg9QCVAJcAlQCVAJUA9AAAAAAACLsQAAQAReCFAEUAJwAVACUARQBEAIAAAAAI2xAABAAF4GUAlQCXAJUAlQCVAGQAAAAAAAkrEAAEAAXglQD1AJcAlQCVAPUAlQCUAAAACTsQAAIAA8BTALMAuwCzALMAswBTABIAAAAJSxAAI8AiACIALgAyACIAIAAP4PQABAAAAAzLEAAAACPAIgAuADIAIgAgAA/g8AAAAAAADosQAAAAR8BMAHQARABEAEwAdABEAEAAQAAASyAACAALwAoACgAKAPoACgAKAAgAAAAAAABbIAAEAAXgFQAVAB0AFQAVABUA9AAAAAAAAIsgAAQABeD1AIUAjQCVAIUAhQCEAAAAAAABSyAABAAF4PUAlQCdAJUAlQCVAPQAAAAAAAFbIAAEAAXg9QClAK0ApQClAKUA9AAAAAAABYsgAAgACeAJAAkA+QAJAAAAD+DwAAAAAAAHSyAACAALwAoA+gAKAAoACgD6AAgACAAAAAhLIAAEAAXg/QCVAJUAlQCdAJUA9AAAAAAACQsgAAAAR8BEAEQARABEAEQARABAAEAAQAAJGyAABAAF4BUAFQAVABUAFQAVAPQAAAAAAAlLIAAIAAng6QCJAIkAiQCJAIkAiAAIAAAACYsgAAIAC8DrAKsAqwCrAKsAqwCyAAAAAAAJmyAABAANwO0ArQC1AI0ADQANAPQAAAAAAApbIAAEAAXgZQCVAJUAlQCVAJUAZAAAAAAACmsgAAQAheCVAJUAVQA1AFUAlQCUAIAAAAAKyyAAAAATwBIAEgASABIAEAAP4PAAAAAAAAyLIAAPwBAAEAAQABAAGAAAAA/g8AAAAAAADJsgAAfABAAUABQAFAAUABAAF+DwAAAAAAANCyAAA+ACAAoA6gCqAKoAqACr4LAAAAAAAA2LIAAD4AIA8gCSAJIAkgCQAJfg8AAAAAAADbsgAAfABACEAIQARAA0AEAAT+CQAIAAAAAN2yAAB8AEAGQAlACUAJQAkACX4GAAAAAAAA5LIAAPwBBAEEAQQBBAEAAQAA/g8gACAAAADlsgAAfABEAUQBRAFEAUABAAF+DxAAEAAAAOayAAB8AEQBRAFED0QAQAEAAX4PEAAQAAAA6LIAAHwARA9ECEQIRAhACAAI/gkQABAAAADrsgAAfABED0QJRAlECUAJAAl+CRAAEAAAAOyyAAA8AKQOpAqkCqQKoAqACr4LCAAIAAAA7bIAADwApA6kCqQLJAigAIAAvg8QABAAAADusgAAPACkDqQKpAskAKAPgAi+DxAAEAAAAPSyAAB8AEQPRAlECUQJQAkACX4PEAAQAAAA9bIAAHwARA9ECkQKRApACgAKfg8QABAAAAD3sgAAfABECEQERAREA0AEAAT+CBAIEAAAAPmyAAB8AEQGRAlECUQJQAkACX4GEAAQAAAA/7IAADwApACkBKQKpAqgCoAKvgQIAAgAAAAAswAA/AEEAQQBBAEAAP4HIAAgAP4PAAAAAAGzAAB8AEQBRAFEAQABfgEQARABfg8AAAAABLMAAHwARABED0QIAAj+CRAIEAj+CQAAAAAQswAAfABEAEQPRAkACX4JEAkQCX4PAAAAABOzAAB8AEQIRAhEBAAEfgMQBBAE/ggACAAAVLMAAPwBBAEEAQQBBAEgASAAIAD+DwAAAABVswAAfABEAUQBRAFUAVABEAEQAX4PAAAAAFizAAD8AIQAhA6ECJQIkAgQCBAI/gkAAAAAXLMAAHwARADEDsQKzArICogKvgsAAAAAAABfswAAfADEDsQKxAtUAFAPEAq+DwAAAAAAAGSzAAB8AEQPRAlECVQJUAkQCRAJfg8AAAAAZbMAAHwARABED0QKVApQChAKEAp+DwAAAABnswAAfABECEQERAREAlQBEAIQBP4IAAgAAGmzAAB8AEQGRAlECVQJUAkQCRAJfgYAAAAAbrMAAHwARAlECUQPVAlQCRAPEAl+CQAAAABwswAA/AEEAQQBBAEgASAA/gcAAP4PAAAAAHGzAAB8AEQBRAFUAVABEAF+AQABfg8AAAAAdLMAAHwARABED1QIUAgQCP4JAAj+CQAAAAB4swAAPAAkAKQOrAqoCogKvAqACr4LAAAAAICzAAB8AEQARA9UCVAJEAl+CQAJfg8AAAAAhbMAAHwARABEBlQJUAkQCX4JAAl+BgAAAADEswAAAAR8BEQERATEB0QERAREBAAEAAAAAMWzAABAAF4BUgFSAXIBUgFSAVIPQAAAAAAAyLMAAIAAnA6UCJQI9AiUCJQIlAiAAAAAAADLswAAQABeD1IJUglyCVIJUglSCUAAAAAAAMyzAABAAN4O0grSCvIK0grSCtILQAAAAAAA1LMAAEAAXg9SCVIJcglSCVIJUg9AAAAAAADVswAAQABeD1IKUgpyClIKUgpSD0AAAAAAANezAABACF4EUgRSAnIBUgJSBFIEQAgAAAAA2bMAAEAAXAZUCVQJdAlUCVQJVAZAAAAAAAD8swACfAJEAsQDRAJEAgAA/g9AAP4PAAAAABi0AAJ8AkQCRALEA0QCRAIAAP4PAAAAAAAAHLQAAIAAvA6kCOQIpAikCAAI/gkAAAAAAABQtAAAgAC8AKQApACkD6QApACkAIAAAAAAAFG0AABAAF4BUgFSAdIBUgFSAVIPQAAAAAAAVLQAAIAAvA6kCKQIpAukCKQIpAiAAAAAAABYtAAAQADeDtIK0grSCtIK0grSC0AAAAAAAGC0AABAAF4PUglSCdIJUglSCVIPQAAAAAAAYbQAAEAAXg9SClIK0gpSClIKUg9AAAAAAABltAAAQABcBlQJVAnUCVQJVAlUBkAAAAAAAKS0AACAALwApACkD6QApAAAAP4PAAAAAAAAt7QAAEAAXAhUCNQJVARUAwAE/gkACAAAAADAtAAAgAC8AKQPpACkAKQApA+kAIAAgAAAANy0AAAABHwERAREBEQERAREBEQEAAQABAAA3bQAAEAAXgFSAVIBUgFSAVIBUg9AAAAAAADgtAAAQABeD1IIUghSCFIIUghSCEAAAAAAAOO0AABAAF4PUglSCVIJUglSCVIJQABAAAAA5LQAAEAA3g7SCtIK0grSCtIK0gtAAAAAAADstAAAQABeD1IJUglSCVIJUglSD0AAAAAAAO20AABAAF4PUgpSClIKUgpSClIPQAAAAAAA77QAAEAAXghSBFICUgNSAlIEUgRACAAAAADxtAAAQABeBlIJUglSCVIJUglSBkAAAAAAABS1AAD8AQQBBAEEAQQBAAEAAP4PAAAAAAAAFbUAAHwARAFEAUQBRAFAAQABfg8AAAAAAAAYtQAAfABED0QIRAhECEAIAAj+CQAAAAAAABy1AAA8AKQOpAqkCqQKoAqACr4LAAAAAAAAJLUAAHwARA9ECUQJRAlACQAJfg8AAAAAAAAntQAAfABECEQERAREA0AEAAT+CQAIAAAAACm1AAB8AEQGRAlECUQJQAkACX4JAAYAAAAAKrUAAHwARAlECUQJRAVAAwAFfgkAAAAAAAAwtQAA/AEEAQAA/AEEAQQBAAD+DyAAIAAAADG1AAB8AEQBAAF8AUQBRAEAAX4PEAAAAAAANLUAAHwARA8ACHwIRAhECAAI/gkQAAAAAAA4tQAAPACkDoAKvAqkCqQKgAq+CwgAAAAAAEC1AAB8AEQPAAl8CUQJRAkACX4PEAAAAAAARbUAAHwARAYACXwJRAlECQAJfgYQAAAAAABMtQAA/AEEAQAA/AEEAQAA/gcgAP4PAAAAAFy1AAB8AEQAAA98CUQJAAl+CRAJfg8AAAAAYbUAAHwARAYACXwJRAkACX4JEAl+BgAAAACgtQAA/AEEAQAA/AEEAQQBIAEgAP4PAAAAAKG1AAB8AEQBAAF8AUQBRAFQARABfg8AAAAApLUAAHwARA8ACHwIRAhECFAIEAj+CQAAAACotQAAPACkDoAKvAqkCqwKqAqICr4LAAAAALu1AAA8AKQAgAS8CqQKrAqoCogEvgAAAAAAvLUAAPwBBAEAAPwBBAEgAP4HAAD+DwAAAADMtQAAfABEAAAPfAlECRAJfgkACX4PAAAAABC2AAR8BEQERAREBAAHfAREBEQERAQAAAAAEbYAAEAAXgFSAUABfgFSAVIBUg9AAAAAAACctgAAgAC8AKQApACAD7wApACkAKQAAAAAAKu2IAAgAL4OsgqyC2ABPgWyCzILMgUAAAAAsbYAAEAAXAZUCVQJwAlcCVQJVAZAAAAAAADwtoAAvACkAKQAgA+8AKQApAAAAP4PAAAAACi3AAAABHwERAREBAAEfAREBEQERAQABAAAKbcAAEAAXgFSAVIBQAFeAVIBUg9AAAAAAAAvtwAAQABeD1IJUglACV4JUglSCVIAQAAAADC3AABAAN4O0grSCsAK3grSCtILQAAAAAAAOLcAAEAAXg9SCVIJQAleCVIJUg9AAAAAAAA7twAAQABcCFQEVARAA1wCVARUCFQIAAAAAES3AAF8AUQBRAEAAXwBRAFEAQAA/g8AAAAAYLcAAPwBBAEEAQAA/AEEAQQBAAD+DwAAAAB8twAA5AEkASQBJAE8AQABAAD+DyAAIAAAAH23AAB0AFQBVAFUAVwBQAEAAX4PEAAQAAAAgLcAAHQAVA9UCFQIXAhACAAI/gkQABAAAACEtwAAPACsDqwKrAqsCqAKgAq+CwgACAAAAIy3AAB0AFQPVAlUCVwJQAkACX4PEAAQAAAAjbcAAHQAVA9UClQKXApACgAKfg8QABAAAACRtwAAdABUBlQJVAlcCUAJAAl+BhAAEAAAAJe3AAA6ACoBKgUqC64LIAsAC34FCAAIAAAAmLcAAOQBJAEkATwBAAD+ByAAIAD+DwAAAACZtwAAdABUAVQBXAEAAX4BEAEQAX4PAAAAAJy3AAD0AJQAlA6cCAAI/gkQCBAI/gkAAAAAqLcAAHQAVABUD1wJAAl+CRAJEAl+DwAAAACptwAAdABUAFQPXAoACnwKEAoQCn4PAAAAAKu3AAB0AFQIVARcBAACfgEQAhAE/gQABAAArbcAAHQAVABUBlwJAAl+CRAJEAl+BgAAAAC1twAAdABUAVQBVAFcAUABAAF+DygAKAAAAMm3AAB0AFQGVAlUCVwJQAkACX4GKAAoAAAA7LcAAOQBJAEkASQBPAEAASAA/g8AAAAAAADttwAAdABUAVQBVAFcAUABEAEQAX4PAAAAAPC3AAD0AJQAlA6UCJwIgAgQCBAI/gkAAAAA9LcAADwALACsDqwKrAqgCogKiAq+CwAAAAD8twAAdABUD1QJVAlcCUAJCAkICX4PAAAAAP23AAByAFIPUgpSCl4KQAoICggKfg8AAAAA/7cAAHQAVAhUBFQEXAJAARACEAT+BAAIAAABuAAAdABUBlQJVAlcCUAJEAkQCX4GAAAAAAe4AAA8ACwBLAUsC6wLIAsICwgFfAEAAAAACLgAAOQBJAEkATwBAAEgAP4HAAD+DwAAAAAJuAAAdABUAVQBXAFAARABfgEAAX4PAAAAAAy4AAD0AJQAlA6cCIAIEAj+CQAI/gsAAAAAGLgAAHQAVABUD1wJQAkQCX4JAAl+DwAAAAAZuAAAdABUAFQPXApACggKfAoACn4PAAAAABu4AAB0AFQIVARcBEACEAF+AgAE/gQABAAAHbgAAHQAVABUBlwJQAkQCX4JAAl+BgAAAAAkuAAA5AEkASQBJAE8AQABSAD+DwAAAAAAACW4AAB0AFQBVAFUAVwBQAEIASgBfg8AAAAAKLgAAPQAlACUDpQInAiACCgIKAj+CQAAAAAsuAAAfABMAMwOzArMCuAKhAqUCr4LAAAAADW4AAB0AFQAVA9UClwKQAoICigKfA8AAAAAObgAAHQAVAZUCVQJXAlACQgJKAl+BgAAAABAuAAA5AEkASQBPAEAAJAA/gcAAP4PAAAAAFy4AAAABPQElASUBJQHlASUBJwEAAQAAAAAXbgAAIAAugKqAqoC6gKqAqoCrg6AAAAAAABguAAAgAC6DqoIqgjqCKoIqgiuCIAAAAAAAGS4AABAAFoPWgtaC3oLWgtaC14LQAAAAAAAbLgAAIAAug+qCaoJ6gmqCaoJrg+AAAAAAABtuAAAgAC6DqoKqgrqCqoKqgquDoAAAAAAAG+4AACAALoIqgiqBOoCqgSqCK4IgAAAAAAAcbgAAIAAugaqCaoJ6gmqCaoJrgaAAAAAAACwuAACdAJUAlQC1ANUAlwCAAD+DwAAAAAAAMy4AAAABPQElAeUBJQElASUB5wEAAQAAAAA4bgAAIAAugbqCaoJqgmqCeoJrgaAAAAAAADouAAAAAF6AUoBSgFKD0oBSgFOAQABAAAAAOm4AACAALoCqgKqAqoDqgKqAq4OgAAAAAAA+LgAAEAAeg9qCWoJ6glqCWoJbg9AAAAAAAD5uAAAQAB6D2oKagrqCmoKagpuD0AAAAAAAPu4AABACHoIagRqBOoCagRqBG4IQAgAAAAABLmAALwArACsAKwPrACsAgAC/g8AAAAAAAA8uQAAgAC0ALQAtAe0ALwAAAD+DwAAAAAAAFi5AACAAPoAyg/KAMoAygDKD84AgAAAAAAAWbkAAIAAugKqA6oCqgKqAqoDrg6AAAAAAABcuQAAgAC6DqoIqguqCKoIqguuCIAIgAAAAGC5AABAAFoP2gtaC1oLWgvaC14LQAAAAAAAbbkAAIAAugaqCaoJqgmqCaoJrgaAAAAAAAB0uQAAAAT0BJQElASUBJQElAScBAAEAAAAAHi5AACAALoOqgiqCKoIqgiqCK4IgAAAAAAAfLkAAEAAWg9aC1oLWgtaC1oLXgtAAAAAAACEuQAAgAC6D6oJqgmqCaoJqgmuD4AAAAAAAIe5AACAALoIqgiqBKoCqgSqCK4IgAAAAAAAibkAAIAAugaqCaoJqgmqCaoJrgaAAAAAAACOuQAAQAB6CWoPaglqCWoJag9uCUAAAAAAAKy5AADkASQBJAEkATwBAAEAAP4PAAAAAAAArbkAAHQAVAFUAVQBXAFAAQABfg8AAAAAAACwuQAA9ACUDpQIlAicCIAIAAj+CQAAAAAAALS5AAA8ACwArA6sCqwKoAqACrwLAAAAAAAAvLkAAHQAVA9UCVQJXAlACQAJfg8AAAAAAAC9uQAAdABUD1QKVApcCkAKAAp+DwAAAAAAAL+5AAB0AFQIVARUAlwBQAIABP4EAAgAAAAAwbkAAHQAVAZUCVQJXAlACQAJfgkABgAAAADIuQAA/AEEAQQBBAH8AQAAAAD+DyAAIAAAAMm5AAB8AEQBRAFEAXwBAAEAAX4PEAAQAAAAzLkAAHwARA9ECEQIfAgACAAI/gkQABAAAADOuQAAPAAkDyQIJAE8BQALgAs+BQgBCAAAANC5AAA8AKQOpAqkCrwKgAqACr4LCAAIAAAA0bkAADwApA6kCqQLPAiAAIAAvg8IAAgAAADYuQAAfABED0QJRAl8CQAJAAl+DxAAEAAAANm5AAB8AEQPRApECnwKAAoACn4PCAAIAAAA27kAAHwARAhECEQEfAMABAAE/gkQCBAAAADduQAAfABEBkQJRAl8CQAJAAl+BhAAEAAAAN65AAB8AEQJRAlEBXwDAAUACX4JEAAQAAAA4bkAADwApA+kCqQKvAqACoAKvgoQABAAAADjuQAAPACkAKQEpAq8CoAKgAq+BAgACAAAAOS5AAD8AQQBBAH8AQAA/gcgACAA/g8AAAAA5bkAAHwARAFEAXwBAAF+ARABEAF+DwAAAADouQAAfABEAEQPfAgACP4JEAgQCP4JAAAAAPW5AAB8AEQARA98CgAKfgoQChAKfg8AAAAA97kAAHwARAhECHwEAAR+AxAEEAT+CQAIAAD5uQAAfABEAEQGfAkACX4JEAkQCX4GAAAAAPq5AAB8AEQJRAl8CQAFfgMQBRAJfgkAAAAAOLoAAPwBBAEEAQQB/AEgACAAIAD+DwAAAAA5ugAAfABEAUQBRAF8ARABEAEQAX4PAAAAADy6AAB8AEQARA9ECHwIEAgQCBAI/gkAAAAAQLoAADwAJACkDqQKvAqICogKvgsAAAAAAABIugAAfABED0QJRAl8CRAJEAkQCX4PAAAAAEu6AAB8AEQIRAhEBHwEEAMQBBAI/gkACAAATboAAHwARAZECUQJfAkQCRAJEAl+BgAAAABOugAAfABECEQJRAl8BRADEAUQCX4JAAAAAFS6AAD8AQQBBAH8ASAAIAD+BwAA/g8AAAAAVboAAHwARAFEAXwBEAEQAX4BAAF+DwAAAABYugAAfABEAEQPfAgQCBAI/gkACP4JAAAAAFy6AAA8ACQApA68CogKiAq8CoAKvgsAAAAAZLoAAHwARABED3wJEAkQCX4JAAl+DwAAAABnugAAfABECEQIfAQQBBADfgQACP4JAAgAAGm6AAB8AEQARAZ8CRAJEAl+CQAJfgYAAAAAcLoAAPwBBAEEAQQB/AGQAJAAkAD+DwAAAAB0ugAAfABEAEQPRAh8CCgIKAgoCP4JAAAAAHi6AAA8ACQApA6kCrwKlAqUCr4LAAAAAAAAhboAAHwARAZECUQJfAkoCSgJKAl+BgAAAACHugAAPAAkCSQJJAk8BagDKAV+CQAIAAAAAKi6AAAABHwERAREBMQHRAREBHwEAAQAAAAAqboAAEAAXgFSAVIBcgFSAVIBXg9AAAAAAACsugAAgAC8DqQIpAjkCKQIpAi8CIAAAAAAALC6AABAAN4O0grSCvIK0grSCt4LQAAAAAAAuLoAAEAAXg9SCVIJcglSCVIJXg9AAAAAAAC5ugAAQABeD1IKUgpyClIKUgpeD0AAAAAAALu6AABACF4EUgRSAnIBUgJSBF4EQAgAAAAAvboAAEAAXgZSCVIJcglSCVIJXgZAAAAAAAD8ugACfAJEAkQCxANEAnwCAAD+DwAAAAAAABi7AAAABHwExAdEBEQERATEB3wEAAQAAAAANLsAAIAAvACkAKQApA+kAKQAvACAAAAAAAA1uwAAQABeAVIBUgHSAVIBUgFeD0AAAAAAADa7AABAAF4BUgFSDlIAUgFSAV4PQAAAAAAAOLsAAIAAvA6kCKQIpAukCKQIvAiAAAAAAAA7uwAAQABeD1IJUgnSCVIJUgleCUAAAAAAADy7AABAAN4O0grSCtIK0grSCt4LQAAAAAAARLsAAEAAXg9SCVIJ0glSCVIJXg9AAAAAAABHuwAAQAheCFIIUgTSAlIEUgheCEAIAAAAAFC7AACAALwApACkB6QAvAEAAf4PAAAAAAAAWLsAACAALg8qC2oLKgsuCwALfgsAAAAAAABjuwAAIAA+CPIJMggyBL4CgAT+CQAIAAAAAKS7AACAALwApA+kAKQApACkD7wAgAAAAAAArLsAAEAA3g7SCtIK0grSCtIK3gtAAAAAAADAuwAAAAR8BEQERAREBEQERAR8BAAEAAAAAPi7AAD8AQQBBAEEAfwBAAAAAP4PAAAAAAAA+bsAAHwARAFEAUQBfAEAAQABfg8AAAAAAAD8uwAAfABEAEQPRAh8CAAIAAj+CQAAAAAAAP+7AAB8AEQPRAlECXwJAAkACX4JAAAAAAAAALwAADwApA6kCqQKvAqACoAKvgsAAAAAAAAJvAAAPAAkACQPJAo8CgAKAAp+DwAAAAAAAAy8AAB8CEQERANEBHwIAAQAA34EAAgAAAAADbwAAHwARAZECUQJfAkACQAJfgkABgAAAAAPvAAAPAAkCSQJJAk8BYADAAV+CQAIAAAAABG8AAA8AKQPpAqkCrwKgAqACr4KAAAAAAAAFLwAAPwBIAEgASAB/AEAAAAA/g8gACAAAAAVvAAAfgBIAUgBSAF+AQABAAF+DxAAEAAAABa8AAB+AEgBSAFID34AAAEAAX4PEAAQAAAAGLwAAHwAUA9QCFAIfAgACAAI/gkQABAAAAAbvAAAfgBID0gJSAl+CQAJAAl+CRAAEAAAABy8AAA8AKgOqAqoCrwKgAqACr4LCAAIAAAAHbwAADwAqA6oCqgLPAiAAIAAvg8IAAgAAAAfvAAAPACoDqgKqAs8AAAPAAq+DwgACAAAACS8AAB+AEgPSAlICX4JAAkACX4PEAAQAAAAJbwAAHwASA9ICkgKfAoACgAKfA8QABAAAAApvAAAfgBIBkgJSAl+CQAJAAl+BhAAEAAAAC28AAB8AMgPyArICvwKgAqACr4KCAAIAAAAMLwAAPwBIAEgAfwBAAD+ByAAIAD+DwAAAAAxvAAAfgBIAUgBfgEAAX4BEAEQAX4PAAAAADS8AAB8AFAAUA98CAAI/gkQCBAI/gkAAAAAOLwAADwAKACoDrwKgAq+CogKiAq+CwAAAABAvAAAfgBIAEgPfgkACXwJEAkQCX4PAAAAAEO8AAB+AEgISAh+BAAEfgMQBBAE/gkACAAARbwAAH4ASABIBn4JAAl+CRAJEAl+BgAAAABJvAAAPAAoAKgPvAqACr4KiAqICr4KAAAAAIS8AAD8ASABIAEgAfwBIAAgACAA/g8AAAAAiLwAAHwAUABQD1AIfAgQCBAIEAj+CQAAAACMvAAAPAAoAKgOqAq8CogKiAq+CwAAAAAAAJS8AAB+AEgPSAlICXwJEAkQCRAJfg8AAAAAlbwAAH4ASABID0gKfAoQChAKEAp+DwAAAACXvAAAfgBICEgISAR8BBADEAQQBP4JAAgAAKC8AAD8ASABIAH8ASAAIAD+BwAA/g8AAAAApLwAAHwAUABQD3wIEAgQCP4JAAj+CQAAAACnvAAAfgBIAEgPfAkQCRAJfgkACX4JAAAAAKi8AAA8ACgAqA68CogKiAq+CoAKvgsAAAAAvLwAAPwBIAEgASAB/AGQAJAAkAD+DwAAAAC9vAAAfgBIAUgBSAF8ASgBKAEoAX4PAAAAAMC8AAB8AFAAUA9QCHwIKAgoCCgI/gkAAAAAxLwAAD4AKACoDqgKvAqoCqgKvgsAAAAAAADNvAAAfgBIAEgPSAp8CigKKAooCn4PAAAAANG8AAB+AEgGSAlICXwJKAkoCSgJfgYAAAAA1bwAAHwASADID8gK/AqoCqgKvgoAAAAAAAD0vAAAAAR8BFAEUATQB1AEUAR8BAAEAAAAAPW8AACAAL4BpAGkAeQBpAGkAb4PgAAAAAAA9rwAAEAAXgFUAVQPdABUAVQBXg9AAAAAAAD4vAAAgAC8DqgIqAjoCKgIqAi8CIAAAAAAAPy8AABAAN4O1ArUCvQK1ArUCt4LQAAAAAAABL0AAEAAXg9UCVQJdAlUCVQJXg9AAAAAAAAHvQAAQAReBFQEVAJ0AVQCVAReBEAEAAAAAAm9AABAAF4GVAlUCXQJVAlUCV4GQAAAAAAAJL2AALwIqAToAqgEqAi8CAAG/gQQCBAAAABIvQACfAJIAkgCyANIAnwCAAD+DwAAAAAAAFm9AABAAFwPWAp4ClgKXAoACnwPAAAAAAAAgL0AAIAAvACoAKgAqA+oAKgAvACAAAAAAACBvQAAQAB+AWQBZAHkAWQBZAF+D0AAAAAAAIS9AACAALwOqAioCKgLqAioCLwIgAAAAAAAiL0AAEAA3g7UCtQK1ArUCtQK3gtAAAAAAACJvQAAQABeD1QLVAvUCVQBVAFeD0AAAAAAAJC9AABAAF4PVAlUCdQJVAlUCV4PQAAAAAAAk70AAEAIXghUBFQE1AJUBFQEXghACAAAAACVvQAAQABeBlQJVAnUCVQJVAleBkAAAAAAAJm9AABAAF4PVAtUC9QLVAtUC14LQAAAAAAA1L0AAIAAvACoAKgPqAC8AAAA/A8AAAAAAADwvQAAgAC8AKgPqACoAKgAqA+8AIAAAAAAAAy+AAAABPwEkASQBJAEkASQBPwEAAQAAAAAEL4AAIAAvA6oCKgIqAioCKgIvAiAAAAAAAAUvgAAQADeDtQK1ArUCtQK1AreC0AAAAAAAES+AAD8ASABIAEgAfwBAAAAAP4PAAAAAAAARb4AAH4ASAFIAUgBfgEAAQABfg8AAAAAAABIvgAAfABQD1AIUAh8CAAIAAj+CQAAAAAAAEy+AAA8ACgAqA6oCrwKgAqACr4LAAAAAAAAVL4AAH4ASA9ICUgJfgkACQAJfg8AAAAAAABXvgAAfgBICEgESAR+AwAEAAT+CQAIAAAAAFm+AAB+AEgGSAlICX4JAAkACX4JAAYAAAAAWr4AAH4ASAlICUgJfgUAAwAFfgkAAAAAAABbvgAAPgAoCSgJKAU+BYADAAV+CQAIAAAAAGC+AAD8ASAB/AH4ACAB/AEAAP4PIAAAAAAAYb4AAH4ASAF+AX4BSAF+AQABfg8QAAAAAABovgAAPACoDrwKvAqoCrwKgAq+CwgAAAAAAHW+AAB+AEgGfgl+CUgJfgkACX4GEAAAAAAAfL4AAPwBIAH8AfgAIAH4AP4HIAD+DwAAAACPvgAAfAB8CAAIfARQAnwC/gIQBP4IAAgAAKi+AAB+AEgPfgl+CUgJfgkACX4PKAAAAAAA0L4AAPwBIAH8AfgAIAEgAfwBIAD+DwAAAADUvgAAfABQD3wIfAhQCHwIEAgQCP4JAAAAANe+AAB+AEgPfgl+CUgJfAkQCRAJfgkAAAAACL8AAPwBIAH8AfgAIAEgAfwBkAD+DwAAAAAJvwAAfgBIAX4BPAFIAXwBKAEoAX4PAAAAAFG/AABAAH4PZAp+CmAKfgpkCn4PQAAAAAAAVb8AAEAAfgZkCWQJfgl+CWQJZAZ+AEAAAADMv4AAvACoAKgAvACAD7wAqACoALwAgAAAANC/AACAALwOqAi8CIALvAioCKgIvAAAAAAAWMAABPwEkASQBPwEAAT8BJAEkAT8BAAEAABowAAAQAB+D2QJfglACX4JZAlkD34AQAAAAKzAAAEAAcAAPABAAIAAAAEAAP4PIAAgAAAArcBAAEAAIAEcASABQAFAAQABfg8QABAAAACwwIAAQAAgDx4IIAhACEAIAAj+CRAAEAAAALTAIAAgAJAOjgqQCqAKoAqACr4LCAAIAAAAtsAAACAAsA6OCpALEACgD4AIvg8IAAgAAAC8wEAAQAAgDxwJIAlACUAJAAl+DxAAEAAAAL/AQABACCAIHAQgBEADQAIABP4IEAgQAAAAwcBAAEAAIAYcCSAJQAlACQAJfgYQABAAAADIwAAAAAHAADwAwAEAAP4HIAAgAP4PAAAAAMnAAABAACAAHAFgAQABfgEQARABfg8AAAAAzMAAAMAAIAAcD2AIAAj+CRAIEAj+CQAAAADQwAAAIAAQAI4OsAqACr4KiAqICr4LAAAAANjAAABAACAAHA9gCQAJfAkQCRAJfg8AAAAA3cAAAEAAIAAcBmAJAAl+CRAJEAl+BgAAAADkwAACAAHAADwAwAAAAQACAAD+D5AAkAAAAOzAIAAgAJAOjgqQCqAKoAqACr4LFAAUAAAA9cBAAEAAMA8OCjAKQApACgAKfg8kACQAAAD3wEAAQAggBBwEEAIgAUACAAT+BCgIKAAAABzBAAIAAcAAPADAAAABIAIgACAA/g8AAAAAHcFAAEAAMAEOARABIAFIAQgBCAF+DwAAAAAewUAAQAAwAQ4BEAEgD0AACAEIAX4PAAAAACDBgACAAGAAHA4gCEAIgAgQCBAI/gkAAAAAJMFAACAAEACODpAKoAqgCogKiAq+CwAAAAAswUAAQAAwDw4JEAkgCUgJCAkICX4PAAAAAC3BQABAADAADg8QCmAKSAoICn4PAAAAAAAAL8FAAEAAMAgOBBAEIAJAAQgCCAT+BAAIAAAxwUAAQAAwBg4JEAkgCUgJCAkICX4GAAAAADjBAAAAA4AAfADAAAADIAD+DwAA/g8AAAAAOcEAAEAAMAAOATABQAEIAX4BAAF+DwAAAAA8wQAAgABgABwPYAiACBAI/AkACP4JAAAAAEDBAAAgABAAjg6QCqAKiAq+CoAKvgsAAAAASMEAAEAAMAAODzAJQAkICX4JAAl+DwAAAABLwQAAQAAwBA4EMARAAggBfgIABP4EAAQAAFTBAAIAAcAAPABAAIAACAFIAEgA/g8AAAAAWMGAAEAAYAAcDiAIQAiACCgIKAj+CQAAAAB0wQAAgABgABwPYAiACCgI/gkACP4JAAAAAHjBAABAADAAjg6wCoAKlAq+CoAKvgsAAAAAjMEAAIAEQARABCAEnAcgBEAEQASABAAAAACNwQAAUABQAUgBRAFmAUgBSAFQD1AAAAAAAJDBAACgAKAOkAiICOQIiAiQCKAIoAAAAAAAlMEAAFAA0A7QCsgK5grICtAK0AtQAAAAAACcwQAAUABQD0gJSAlmCUgJSAlQD1AAAAAAAJ3BAABQAFAPSApICmYKSApIClAPUAAAAAAAn8EAAFAIUARIBEQCZgFEAkgEUARQCAAAAAChwQAAUABQBkgJSAlmCUgJSAlQBlAAAAAAAKXBAABQAFAPUAtIC2YLSAtQC1ALUAAAAAAAxMEAACACEALOAxACAAD+DyAAIAD+DwAAAADgwQAAQAJAAiACnAMgAkACAAD+DwAAAAAAAPzBAARABEAEIAcQBAwEMAQgB0AEQAQABAAADcIAAFAASA9oCkQKRgpECmgKSA9QAAAAAAAYwgAAoACgAJAAiACGD4gAkACgAKAAAAAAABnCAABQAFABUAFIAcYBSAFQAVAPUAAAAAAAHMIAAKAAoA6QCJAIjAuQCJAIoAigAAAAAAAfwgAAUABQD1AJSAnGCUgJUAlQCVAAAAAAACDCAABQANAO0ArICsQKyArQCtALUAAAAAAAKMIAAFAAUA9QCUgJxglICVAJUA9QAAAAAAArwgAAUAhQCFAISATGAkgEUAhQCFAIAAAAAC3CAABQAFAGUAlICcYJSAlQCVAGUAAAAAAAL8IAACgIKAUoBSQFogMkBSgFKAUoCAAAAAAywkAAUAlQCVAPSAnGCUgJUA9QCVAJQAAAAFDCAABQAEgAxgdIAFABAAH+BwAA/g8AAAAAWMIAACgAKA9mCygLaAtAC34LAAt+CwAAAABswgAAoACgAJAAjA+QAKAAAAD+DwAAAAAAAHDCQABQAFAPSAjGCUgIUAgACP4JAAAAAAAAfcJAAFAAUA9ICsQKSApQCgAKfg8AAAAAAACIwgAAoACQAJAPiACGAIgAkA+QAKAAAAAAAJDCAAAoAKgO6AqkCqIKpAroCqgLKAAAAAAApMIAAIAEQARABCAEHAQgBEAEQASABAAAAACowgAAoACgDpAIkAiMCJAIkAigCKAAAAAAAKzCAABQANAO0ArICsQKyArQCtALUAAAAAAAtMIAAFAAUA9QCUgJRglICVAJUA9QAAAAAAC1wgAAUABQD1AKSApGCkgKUApQD1AAAAAAALfCAABQCFAEUARIAkYDSAJQBFAEUAgAAAAAucIAAFAAUAZQCUgJRglICVAJUAZQAAAAAADcwgACAAHAADwAwAAAAQABAAD+DwAAAAAAAN3CQAAgADABDgEQASABQAEAAX4PAAAAAAAA4MKAAEAAIAAcDyAIQAhACAAI/gkAAAAAAADjwkAAQAAwDwwJEAkgCUAJAAl+CQAAAAAAAOTCIAAgABAAjg6QCqAKoAqACr4LAAAAAAAA68IAACAAkA6OCpALIAAgBYALPgsABQAAAADswkAAQAAwDwwJMAkgCUAJAAl+DwAAAAAAAO3CQABAADAADA8wCiAKQAoACn4PAAAAAAAA78JAAEAIMAgMBDAEQANABAAE/ggACAAAAADxwkAAQAAgBhwJIAlACUAJAAl+CQAGAAAAAPbCQABAADAIDAkQDyAJQAkAD34JAAAAAAAA+MIAAYABfACAAIABfACAAQAA/g8gAAAAAAD5wkAAIAAcASABYAEcAWABAAF+DxAAAAAAAPzCQABgABwPYAhgCBwIYAgACP4JEAAAAAAAAMMgABAAjg6QCrAKjgqwCoAKvgsIAAAAAAAIw0AAIAAcDyAJYAkcCWAJAAl+DxAAAAAAAA3DQAAgABwGIAlgCRwJYAkACX4GEAAAAAAAE8MgABAAjgCQBJAKzgqQCoAKvgQIAAAAAAApwwAAYAA8BkAJPAlgCQAJfgkQCX4GAAAAAGjDAAKAAXwAgAOAAXwAgAEgAiAA/g8AAAAAacNAADAAHgEgAWABHgEgAUgBCAF+DwAAAABsw4AAQAA8AEAOwAg8CEAIkAgQCP4JAAAAAHDDIAAQAIwOsAqwCowKkAqgCogKvgsAAAAAecNAADAADgAwD2AKHgowCkAKCAp+DwAAAACEwwAAgAH8AAAB/ACAASAA/A8AAP4PAAAAAIjDAADAADwAwA48CMAIEAj8CQAI/gkAAAAAjMMAACAAHACgDpwKoAqICr4KgAq+CwAAAADYwwAAQAQgBBwEIARAByAEHAQgBEAEAAAAAN/DAABQAEgPRglICWgJSAlGCUgJUAAAAAAA4MMAAFAAyA7GCsgK6ArICsYKyAtQAAAAAABkxAAAoACQAI4AkACgD5AAjgCQAKAAAAAAAPDEAACABGAEHARgBIAEYAQcBGAEgAQAAAAA9MQAAKAAkA6MCJAIoAiQCIwIkAigAAAAAAD4xAAAUADQDswKyArQCtgKxArIC1AAAAAAAADFAABQAEgPRglICVAJSAlGCUgPUAAAAAAADMVAAiACHAJgAmACHAIgAkACAAD+DwAAAAAoxQABgAF8AIABgAN8AIAAAAEAAP4PAAAAACnFQAAgABwBIAFgARwBIAFAAQABfg8AAAAALMVAAGAAHA9gCOAIHAhgCEAIAAj+CQAAAAAwxSAAEACODpAKsAqOCpAKoAqACr4LAAAAADnFQAAgABwPIApgChwKIApACgAKfg8AAAAAO8VAACAAHAggCGAEHAQgA0AEAAT+CQAIAAA9xUAAIAAcBiAJYAkcCSAJQAkACX4GAAAAAETFAADwAAgBBAIIAfAAAAAAAP4PIAAgAAAARcUAADgARAFEAUQBOAEAAQABfg8QABAAAABIxQAAOABED0QIJAg4CAAIAAj+CRAAEAAAAEnFAAA4AEQPRAhEDDgIgASAA74EEAgQAAAASsUAADgARA9ECEQBOAUAC4ALPgUIAQgAAABMxQAAHACiDqIKogqcCoAKgAq+CwgACAAAAFPFAAA8AMIOwgrCCzwAAAWACz4FCAAIAAAAVMUAADgARA9ECUQJOAkACQAJfg8QABAAAABVxQAAOABED0QKJAoYCgAKAAp+DwgACAAAAFfFAAA4AEQIRAREBDgDAAIABP4IEAgQAAAAWcUAADgARAZECUQJOAkACQAJfgYQABAAAABexQAAOABICUQJRA84CQAJAA9+CRAAEAAAAGDFAAD4AQQCBAL4AQAA/g8gACAA/g8AAAAAYcUAADgARABEAUQBOAF8ARABEAF+DwAAAABkxQAAOABEAEQPRAg4CP4JEAgQCP4JAAAAAGjFAAAYACQApA6kCpgKvAqICogKvAsAAAAAcMUAADgARABED0QJOAl8CRAJEAl+DwAAAABzxQAAOABECEQIRAQ4An4DEAQQBP4IAAgAAHXFAAA4AEQARAZECTgJfgkQCRAJfgYAAAAAfMUAAPAACAEEAggB8AAAAAAA/g+QAJAAAAB9xQAAOABEAUQBRAE4AQABAAF+DygAKAAAAIDFAAA4AEQPRAhECDgIAAgACP4JSABIAAAAhMUAABwAog6iCqIKnAqACoAKvgsUABQAAACHxQAAPADCDsIKwgs8AAAPAAq+DxQAFAAAAI3FAAA4AEQPRApECjgKAAoACn4PJAAkAAAAj8UAADgARAhEBEQCOAEAAgAE/gQoCCgAAACRxQAAOABEBkQJRAk4CQAJAAl+BigAKAAAAJXFAAA4AMQPxArECrgKgAqACr4KJAAkAAAAl8UAABwAogCiBKIKnAqACoAKvgQUABQAAACYxQAA+AEEAgQC+AEAAP4PkACQAP4PAAAAALTFAADwAAgBBAIIAfAAIAAgACAA/g8AAAAAtcUAADgARABEAUQBKAEQARABEAF+DwAAAAC4xQAAOABEAEQPRAgoCBAIEAgQCP4JAAAAALnFAAA4AEQPRAgkBKgAkAyQA5AEvggAAAAAu8UAADgARABED0QJKAkQCRAJEAl+CQAAAAC8xQAAHAAiAKIOogqUCogKiAq+CwAAAAAAAMTFAAA4AEQPRAlECSgJEAkQCRAJfg8AAAAAxcUAADgARABED0QKKAoQChAKEAp8DwAAAADGxQAAOABED0QKRAooDxAAEAwQA3wEAAgAAMfFAAA4AEQIRAREBCgCEAEQAhAE/ggACAAAycUAADgARAZECUQJKAkQCRAJEAl+BgAAAADKxQAAOABECEQJRAkoBRADEAUQCX4JAAAAAMzFAAA4AEQERAVEBSgFEAUQBRAFfg8AAAAAzsUAADgARAhECUQPKAkQCRAPEAl+CQAAAADQxQAA+AEEAgQC+AEgACAA/g8AAP4PAAAAANHFAAA4AEQARAFEATgBEAF8AQABfg8AAAAA1MUAADgARABED0QIOAgQCP4JAAj+CQAAAADYxQAAGAAkAKQOpAqYCogKvAqACrwLAAAAAODFAAA4AEQARA9ECTgJEAl8CQAJfg8AAAAA48UAADgARAhECEQEOAIQA34EAAT+CAAIAADsxQAA+AAEAQQCBAH4AIgAiACIAP4PAAAAAO3FAAA4AEQBRAFEATgBKAEoASgBfg8AAAAA8MUAADgAKABED0QIOAgoCCgIKAj+CQAAAAD0xQAAHAAiAMIOwgq8CqQKpAq+CwAAAAAAAPfFAAA8AMIOwgrCCzwApA8kCSQJvg8AAAAA/MUAADgARA9ECSQJOAkoCSgJKAl+DwAAAAD9xQAAOABEAEQPRAo8CiQKJAokCn4PAAAAAP/FAAA4AEQIRAREBDgCKAEoAigE/gQACAAAAcYAADgARAZECUQJOAkoCSgJKAl+BgAAAAAGxgAAOABECEQJRA84CSgJKA8oCXwJAAAAAAjGAAD4AQQCDAPwAJAAkAD+DwAA/g8AAAAAEMYAABgAJACkDqQKvAqkCr4KgAq+CwAAAAAZxgAAOABEAEQPJAo8CiQKfgoACn4PAAAAABvGAAA4AEQIRAhEBDgCKAF8AgAE/ggACAAAJMYAAAAEMARIBIQEhAeEBEgEMAQABAAAAAAlxgAAQABcAVIBYgFiAWIBUgFcD0AAAAAAACjGAACAAJwOlAiiCOIIogiUCJwIgAAAAAAALMYAAEAAzA7SCtIK8grSCtIKzAtAAAAAAAAuxgAAQADMDtIK0gtyANIP0gjMD0AAAAAAADPGAABAAMwO0grSC3IAUgVSC0wLQAUAAAAANcYAAEAATA9SClIKcgpSClIKTA9AAAAAAAA3xgAAQABcCFIEYgJiAWICUgRcCEAAAAAAADnGAABAAFwGUgliCWIJYglSCVwGQAAAAAAAO8YAAEAATAlSCVIFcgNSBVIFTAlAAAAAAABAxgAAGAIkAsQDJAIkAhgCAAD+DyAAIAAAAEHGgACcAKIB4gGiAZQBnAEAAX4PEAAQAAAARMaAAJgApA7kCKQIpAiYCAAI/AsgACAAAABRxkAATABSD3IKUgpSCkwKAAp+DxAAEAAAAFXGQABcAGIGYgliCVQJXAkACX4GEAAQAAAAXMYAADgBRAHEAUQBOAD+B0AAQAD+DwAAAABgxgAAmACkAMQOpAiYCAAI/AkgCP4LAAAAAHjGAAIwAkgCRALEA0QCOAIAAP4PAAAAAAAAfMaAAJwAkg6iCOIIogicCAAI/gkAAAAAAACUxgAAAAQ4BMgHRAREBEQEyAc4BAAEAAAAAJXGAACAAJwB4gGiAaIBogHkAZwPgAAAAAAAqcYAAEAATAZyCVIJUglSCXIJTAZAAAAAAACwxgAAgACcAJQAogCiD6IAlACcAIAAAAAAALHGAABAAFwBYgFiAeIBYgFiAVwPQAAAAAAAtMYAAEAAXA9kCGII4gtiCFQIXAhAAAAAAAC4xgAAQADMDtIK0grSCtIK0grMC0AAAAAAAMDGAABAAEwPUglSCdIJUglSCUwPQAAAAAAAw8YAAEAATAhSCFIE0gJSBFIITAhAAAAAAADFxgAAQABcBmIJYgniCWIJYglcBkAAAAAAAMzGgACYAKQApACkB6QAmAEAAf4PAAAAAAAAzcYgACwAMgLyAjICMgKsAoAC/g4AAAAAAADQxkAATABSD1II0glSCAwIgAj+CQAAAAAAANTGIAAsADIPMgtyCzILLAsAC34LAAAAAAAA6MZAAFgAZADkB2QAWAEAAfwHAAD+DwAAAADsxgAASABUDtQIVAjICIAI/AkACP4LAAAAAPDGAAAsADIPcgsyC2wLQAt+CwALfgsAAAAA+cYAACwAMg9yCjIKbApACv4KAAp+DwAAAAAEx4AAmACkAKQApA+kAJgAAAD8DwAAAAAAAAjHQABcAGIPYgjiCWIIXAgACP4JAAAAAAAADMcgACwAsg6yCvIKsgqsCoAKvgsAAAAAAAAXx0AATABSCFII0glSBEwDAAT+CQAIAAAAABnHQABMAFIGUgrSCVIJTAkACX4GAAAAAAAAIMcAAIAAnACiD6IAogCiAKIPnACAAAAAAAAhxwAAQABcAeIBYgFiAWIB4gFcD0AAAAAAACTHAABAAFwOZAjiC2IIYgjiC1wIQAAAAAAAKMcAAEAAzA7SCtIK0grSCtIKzAtAAAAAAAA1xwAAQABMBtIJUglSCVIJ0glMBkAAAAAAADzHAAAABDAESASEBIQEhARIBDAEAAQAAAAAPccAAEAAXAFiAWIBYgFiAWQBXA9AAAAAAABAxwAAgACcDqQIogiiCKIIpAicCIAAAAAAAETHAABAAMwO0grSCtIK0grSCswLQAAAAAAATMcAAEAAXA9iCWIJYgliCWIJXA9AAAAAAABNxwAAQABMD1IKUgpSClIKUgpMD0AAAAAAAFHHAABAAFwGZAliCWIJYglkCVwGQAAAAAAAWMcAAjgCRAJEAkQCRAI4AgAA/g8AAAAAAAB0xwAA8AAIAQQCBAIIAfAAAAD+DwAAAAAAAHXHAAA4AEQBRAFEAUQBOAEAAX4PAAAAAAAAeMcAADgAKABED0QIRAg4CAAI/gkAAAAAAAB8xwAAHAAUAKIOogqcCoAKgAq+CwAAAAAAAH3HAAA4AMQOxArECrgLAAiAALwPAAAAAAAAg8cAABwAog6iCqILHAAABYALPgsABQAAAACExwAAOABED0QJRAkoCTgJAAl+DwAAAAAAAIXHAAA4ACgARA9ECkQKOAoACn4PAAAAAAAAh8cAADgARAhEBEQCRAE4AgAE/ggACAAAAACIxwAAOAhEBEQDRAQoCDAEAAN+BAAIAAAAAInHAAA4AEQGRAlECSgJOAkACX4JAAYAAAAAiscAADgARAhECUQJRAU4AwAFfgkAAAAAAACOxwAAOABECUQJRA8oCTgJAA9+CQAAAAAAAJDHAAIEAcQAPABEAIQABAEAAP4PIAAgAAAAkcdAAEQAJAEcASQBRAFEAQABfg8QABAAAACUx4AARAAkDxwIJAhECEQIAAj+CRAAEAAAAJbHAABEADQPDAgUACQFIAuACz4FCAEIAAAAmMdAACQAlA6MCpQKpAqkCoAKvgsIAAgAAACgx0AARAAkDxwJJAlECUQJAAl+DxAAEAAAAKHHQABEACQPHAokCkQKRAoACn4PEAAQAAAAo8eAAEQIJAgcBCQERANAAgAE/ggQCBAAAAClx4AARAAkBhwJJAlECUQJAAl+BhAAEAAAAKbHQABECCQJHAkkBUQDRAUACX4JEAAQAAAArMcAAAQBxAA8AMQBAAD+ByAAIAD+DwAAAACtxwAARAAkABwBZAEAAX4BEAEQAX4PAAAAALzHAABEACQAHA9kCQAJfgkQCRAJfg8AAAAAwccAAEQAJAAcBmQJAAl+CRAJEAl+BgAAAADIxwACBAHEADwAxAAEAQQCAAD+D5AAkAAAAN3HgABEACQGHAkkCUQJRAkACX4GKAAoAAAAAMgAAgQBxAA8AMQABAEkAiAAIAD+DwAAAAAByEAARAAkARwBJAFEAVQBEAEQAX4PAAAAAATIgABEACQAHA8kCEQIhAgQCBAI/gkAAAAACMhAACQAFACMDpQKoAqoCogKvgsAAAAAAAAKyAAAJACkDpwKpAskAIQPkAi+DwAAAAAAABDIQABEACQPHAkkCUQJVAkQCRAJfg8AAAAAEchAAEQAJAAcDyQKRApQChAKfg8AAAAAAAATyIAARAAkCBwIJAREBEQDEAQQCP4JAAgAABXIgABEACQGHAkkCUQJVAkQCRAJfgYAAAAAFshAAEQAJAkcCSQJRAVUAxAFEAl+CQAAAAAcyAAABAKEAXwAhAAkAyAA/g8AAP4PAAAAAB3IAABEACQAHAEkAUQBEAF+AQABfg8AAAAAIMgAAIQAZAAcDyQIRAgQCP4JAAj+CQAAAAAkyAAAJAAUAIwOlAqgCogKvAqACr4LAAAAACzIAABEACQAHA8kCUQJEAl+CQAJfg8AAAAAL8gAAIQAZAgcCCQERAQQA34EAAj+CQAIAAA4yAACBAHEADwARACEAAQBUABQAP4PAAAAADzIgABEACQAHA8kCEQIjAgoCCgI/gkAAAAAcMgAAIQERAREBCQEnAckBEQERASEBAAAAABxyAAAUABSAVIBSgFmAUoBUgFSD1AAAAAAAHTIAACgAKQOpAiUCMwIlAikCKQIoAAAAAAAeMgAAFAA0g7SCsoK5grKCtIK0gtQAAAAAACAyAAAUABSD1IJSglmCUoJUglSD1AAAAAAAIHIAABQAFIPUgpKCmYKSgpSClIPUAAAAAAAhcgAAFAAVAZUCUwJbAlMCVQJVAZQAAAAAACLyCAAKgEqBSoLKgumCyoLKgsyBTIBIAAAAIzIgAJEAiQCnAMkAkQCRAIAAP4PQABAAAAAxMgAAEACRAIkApwDJAJEAgAA/g8AAAAAAADgyAAEhAREBEQHJAQcBCQERAdEBIQEAAQAAOTIAACgAKQOpAiUCIwIlAjUCJQIpAiAAAAA/MgAAKAApACkAJQAjA+UAKQApACgAAAAAAD9yAAAUABSAVIBSgHGAUoBUgFSD1AAAAAAAADJAACgAKQOpAiUCIwLlAikCKQIoAAAAAAABMkAAFAA0g7SCsoKxgrKCtIK0gtQAAAAAAAMyQAAUABSD1IJSgnGCUoJUglSD1AAAAAAAA3JAABQAFIPUgpKCsYKSgpSClIPUAAAAAAAEckAAFAAVAZUCVQJzAlUCVQJVAZQAAAAAAAYyQAAoACkAJQAjAeUAKQBAAH+DwAAAAAAAFDJAACgAKQAlACMD5QApAAAAP4PAAAAAAAAbMmAAKQApACkD5QAjACUAKQPpACkAIAAAACIyQAAhASEBEQEJAQcBCQERASEBIQEAAAAAInJAABQAFQBVAFUAUwBVAFUAVQPUAAAAAAAjMkAAKAApA6kCJQIjAiUCKQIpAigAAAAAACQyQAAMACyDqoKqgqmCqoKqgqyCzAAAAAAAJjJAABQAFIPUglKCUYJSglSCVIPUAAAAAAAmckAAFAAUg9SCkoKRgpKClIKUg9QAAAAAACdyQAAUABUBlQJVAlMCVQJVAlUBlAAAAAAAMDJAAIEAcQAPADEAAQBBAIAAP4PAAAAAAAAwckAAEAARAAkARwBJAFEAQABfg8AAAAAAADEyQAAgABEACQPHAhkCIQIAAj+CQAAAAAAAMfJQABEACQPHAkkCUQJQAkACX4JAAAAAAAAyMlAACQAFACMDpQKpAqgCoAKvgsAAAAAAADQyQAAQABEDyQJHAkkCUQJAAl+DwAAAAAAANHJAABAAEQAJA8cCiQKRAoACn4PAAAAAAAA08kAAIAARAgkCBwEZANABAAI/gkACAAAAADVyQAAgABEBiQJHAkkCUQJAAl+CQAGAAAAANnJIAAkAJQPjAqUCqQKoAqACr4KAAAAAAAA2skAAEAARAgkCRwPJAlECQAPfgkAAAAAAADcyQABhAF8AIQDgAB8AIQBAAD+DyAAAAAAAN3JQAAkABwBZAFgARwBZAEAAX4PEAAAAAAA58kgABQAjA60CqALHAC0DwAKvg8IAAAAAADxyUAAJAAcBmQJYAkcCWQJAAl+BhAAAAAAAPjJAACEAXwAgAF8AIQBAAD+ByAA/g8AAAAADMoAAGQIPAxAAzwEZAgABH4DEAT+CAAIAABMygAChAF8AIQBgAN8AIQBIAIgAP4PAAAAAE3KQAAkABwBZAEgARwBJAFEARABfg8AAAAAUMqAAEQAPADEDkAIPAhECJQIEAj+CQAAAABUyiAANACcDqQKsAqMCpQKoAqICr4LAAAAAFzKQAAkABwPZAlgCRwJJAlECRAJfg8AAAAAvcoAAFIASgFGAUoBaAFKAUYBSg9SAAAAAADTygAAUgBKCUYFSgVoA0oFRgVKCVIAAAAAAEjLAACkAKQAnACkAKAPpACcAKQApAAAAAAAScsAAFQAVAFMAVQB0AFUAUwBVA9UAAAAAADUywAAhARkBDwERASABEQEPARkBIQEAAAAAAzMAAKEAXwAhAGAA3wAhAEEAgAA/g8AAAAADcxAACQAHAFkASABHAEkAUQBAAF+DwAAAAAQzIAAZAA8DsQIQAg8CGQIhAgACP4JAAAAABzMQAAkABwPJAlgCRwJJAlECQAJfg8AAAAAIsxAACQAHAlkCSAFHAMkBUQFAAl+CQAAAAAozAABCAHIAD4AyAAIAQgBAAD+DyAAIAAAACnMQABEACQBHgEkAUQBRAEAAX4PEAAQAAAALMyAAEQAJA8eCCQIRAhECAAI/gkQABAAAAAuzAAARAA0Dw4IFAEkBSALgAs+BQgBCAAAADDMIAAkAJQOjgqUCqQKpAqACr4LCAAIAAAAOMxAAEQAJA8eCSQJRAlECQAJfg8QABAAAAA7zEAARAgkCB4EJAJEA0QCAAT+CBAIEAAAAD3MgABEACQGHgkkCUQJRAkACX4GEAAQAAAAPsxAAEQIJAkeCSQFRANEBQAJfgkQABAAAABEzAAACAHIAD4AyAEAAP4HIAAgAP4PAAAAAEXMAABEACQAHgFkAQABfgEQARABfg8AAAAATMwAACQAFACODrQKgAq+CogKiAq+CwAAAABUzAAARAAkAB4PZAkACX4JEAkQCX4PAAAAAFnMAABEACQAHgZkCQAJfgkQCRAJfgYAAAAAYMwAAggBiAB+AMgACAEIAgAA/g+QAJAAAABkzIAAhABkDh4IJAhECIQIAAj+CUgISAAAAJjMAAIIAcgAPgDIAAgBKAEgACAA/g8AAAAAmcxAAEQAJAEeASQBRAFUARABEAF+DwAAAACczIAARAAkAB4PJAhECIQIEAgQCP4JAAAAAKDMQAAkACQAng6kCqQKhAqQCr4LAAAAAAAAqMxAAEQAJA8eCSQJRAlUCRAJEAl+DwAAAACpzEAARAAkAB4PJApEClQKEAp+DwAAAAAAAKvMgABEACQIHgQkBEQCRAEQAhAE/gkACAAArcyAAEQAJAYeCSQJRAlUCRAJEAl+BgAAAAC0zAAACAHIAD4AyAAIASAA/gcAAP4PAAAAALzMAABEACQAng6kCoQKkAq+CoAKvgsAAAAA0MwAAggCiAF+AIgACAEYApAA/g8AAAAAAAAIzQAAgASIBEgEKAQ8BygESASIBIAEAAAAAAnNAACgAKQCpAKUAs4ClAKkAqQOoAAAAAAADM0AAKAApA6kCJQIzgiUCKQIpAigAAAAAAAbzQAAoAikCKQIlATOApQEpAikCKAIAAAAAB3NAACgAKQGpAmUCc4JlAmkCaQGoAAAAAAALM0AAFQAVA9OC1QLVAtUCwALfgsQABAAAABczQAAQAJEAiQCngMkAkQCAAD+DwAAAAAAAHjNAASIBEgESAcoBBwEKARIB0gEiAQABAAAlM0AAEABRAEkARQBHg8UASQBRAFAAQAAAACVzQAAUABUAVQBVAHOAVQBVAFUD1AAAAAAAJjNAACgAKQOpAiUCI4LlAikCKQIoAAAAAAAnM0AAGAAZA9UC1QLzgtUC1QLZAtgAAAAAACkzQAAUABUD1QJVAnOCVQJVAlUD1AAAAAAAKXNAABgAGQPVApUCs4KVApUCmQPYAAAAAAAp80AAFAIVAhUBFQEzgJUBFQEVAhQCAAAAACpzQAAUABUBlQJVAnOCVQJVAlUBlAAAAAAAOjNAACgAKQAlACOD5QApAAAAP4PAAAAAAAABM6AAKQApACkD5QAjgCUAKQPpACkAIAAAAAgzgAAgASIBIgESAQ8BEgEiASIBIAEAAAAACHOAABQAFQBVAFUAU4BVAFUAVQPUAAAAAAAMM4AAFAAVA9UCVQJTglUCVQJVA9QAAAAAAA1zgAAUABUBlQJVAlOCVQJVAlUBlAAAAAAAFjOAAAAAggBiAB+AIgBCAIAAP4PAAAAAAAAWc4AAEAARAAkAR4BJAFEAQABfg8AAAAAAABczgAAgABEACQPHggkCMQIAAj+CQAAAAAAAGDOAAAgACQAlA6OCpQKpAqACr4LAAAAAAAAaM5AAEQAJA8kCR4JJAlECQAJfg8AAAAAAABpzgAAQABEACQPHgokCkQKAAp+DwAAAAAAAGvOAABAAEQIJAQeBiQBQAIABP4EAAgAAAAAbc4AAEAARAYkCR4JJAlECQAJfgkABgAAAAB0zgAAJAIkAZQAZAAcAAAAAAD+DyAAIAAAAHXOAABUAFQBNAE0AQwBAAEAAX4PEAAQAAAAeM4QAFQAVA80CBQIDAgACAAI/gkQABAAAAB8zgAAKgCqDqoKmgqGCoAKgAq+CwgACAAAAITOAABUAFQPVAk0CQwJAAkACX4PEAAQAAAAhc4AAFQAVA80CjQKDAoACgAKfg8QABAAAACJzgAAlABUBlQJNAkMCQAJAAl+BhAAEAAAAJDOIAEkAZQAdAAcAAAA/gcgACAA/g8AAAAAlM4AAJAAVAA0DxwIAAj+CRAIEAj+CQAAAACgzgAAkABUADQPDAkACX4JEAkQCX4PAAAAAKHOAACQAFQANA8MCgAKfAoQChAKfg8AAAAAo86QAJQAVAg0CAwEAAJ+AxAEEAT+CQAIAADkzgAAJAIkAaQAZAAcAAAAIAD+DwAAAAAAAOjOAACQAFQAVA88CAwIAAgQCBAI/gkAAAAA7M4AAFAAVAA0DrQKjAqACpAKkAq+CwAAAAD0zgAAkABUAFQPNAkMCQAJEAkQCX4PAAAAAPXOAACQAFQAVA80CgwKAAoQChAKfg8AAAAA984AAJAAVAQ0CDQEDAKAARACEAT+CAAEAAAAzxABJAGUAFQAPAAgACAA/gcAAP4PAAAAAATPAACUAFQANA8cCBAIEAj+CQAI/gkAAAAACM8AAFAAVAA0DpwKkAqQCrwKgAq+CwAAAAAQzwAAkABUADQPHAkQCRAJfgkACX4PAAAAABPPkACUAFQINAQcBBACEAF+AgAE/ggACAAAHM8AACQCJAGkAGQAHACQAJAA/g8AAAAAAABUzwAEJAQkBCQEpAckBCQEJAT8BAAEAAAAAFjPAACAAJQOlAiUCNQIlAiUCLwIgAAAAAAAXM8AAEAAyg7KCsoK6grKCsoK3gtAAAAAAABkzwAAQABKD0oJSglqCUoJSgleD0AAAAAAAGXPAABAAEoPSgpKCmoKSgpKCl4PQAAAAAAAac8AAEAASgZKCUoJaglKCUoJXgZAAAAAAABwzwAAJAIkAqQDJAIkAvwCAAD+D0AAQAAAAIzPEAEkAaQBFAEUAXwBAAD+B0AA/g8AAAAAxM8ABCAEJASkByQEJASkByQE/AQABAAAAADgzwAAgACUAJQAlACUD5QAlAD8AIAAAAAAAOHPAABAAFIBUgFSAdIBUgFSAX4PQAAAAAAA6M8AACAAqg6qCqoK6gqqCqoKvgsgAAAAAAD8z0AAVABUANQHVABUAHwBAAH+DwAAAAAAADTQAABAAFQAVADUB1QAfABAAAAA/g8AAAAANdAAAEAAVABUAdQBVAF8AQABfg8AAAAAAAA40EAAVABUD1QI1AlUCHwIAAj+CQAAAAAAADzQIAAqAKoOqgrqCqoKvgqACr4LAAAAAAAAUNAAAJAAlACUD5QAlACUAJQP/ACAAAAAAABs0AACIAIkAiQCJAIkAiQCJAL8AgACAAAAAHDQAABAAFQPVAhUCFQIVAhUCHwIQAAAAAAAdNAAACAArA6sCqwKrAqsCqwKvAsgAAAAAAB80AAAQABSD1IJUglSCVIJUgl+D0AAAAAAAKTQAAIkAiQBpABkABwAAAAAAP4PAAAAAAAAqNAAAJAAlABUDjQIDAgACAAI/gkAAAAAAACs0EgAKgCqDpoKmgqGCoAKgAq+CwAAAAAAALTQAACQAFQAVA80CQwJAAkACX4PAAAAAAAAudAAAJQAVAZUCTQJDAkACQAJfgkABgAAAADA0AAA/AEkASQBJAEkAQABAAD+DyAAIAAAAMHQAAB8AFQBVAFUAVQBQAEAAX4PEAAQAAAAxNAAAPwAlA6UCJQIlAiACAAI/gkQABAAAADI0AAAPACsDqwKrAqsCqAKgAq+CwgACAAAANDQAAB8AFQPVAlUCVQJQAkACX4PEAAQAAAA0dAAAHwAVA9UClQKVApACgAKfg8QABAAAADT0AAAfABUCFQEVAJUAUACAAT+CBAIEAAAANXQAAB8AFQGVAlUCVQJQAkACX4GEAAQAAAA3NAAAPwBJAEkASQBAAD+ByAAIAD+DwAAAADd0AAAfABUAVQBVAEAAX4BEAEQAX4PAAAAAODQAAB8AFQAVA9UCAAI/gkQCBAI/gkAAAAA5NAAAHwAVADUDtQKgAq8CogKiAq+CwAAAADs0AAAfABUAFQPVAkACXwJEAkQCX4PAAAAAO3QAAB8AFQAVA9UCgAKfAoQChAKfg8AAAAA8dAAAHwAVABUBlQJAAl+CRAJEAl+BgAAAAAw0QAA/AEkASQBJAEkAQABIAAgAP4PAAAAADHRAAB8AFQBVAFUAVQBQAEQARABfg8AAAAANNEAAPwAlACUDpQIlAiACBAIEAj+CQAAAAA40QAAfABUANQO1ArUCsAKiAq+CwAAAAAAAEDRAAB8AFQPVAlUCVQJQAkQCRAJfg8AAAAARdEAAHwAVAZUCVQJVAlACRAJEAl+BgAAAABM0QAA/AEkASQBJAEAASAA/gcAAP4PAAAAAE3RAAB8AFQBVAFUAUABEAF+AQABfg8AAAAAUNEAAPwAlACUDpQIgAgQCP4JAAj+CwAAAABU0QAAfABUANQO1ArACogKvAqACr4LAAAAAFzRAAB8AFQAVA9UCUQJEAl+CQAJfg8AAAAAXdEAAHwAVABUD1QKRAoQCnwKAAp+DwAAAACg0QAAAAT8BJQElASUB5QElASUBAAEAAAAAKHRAACAAL4CqgKqAuoCqgKqAqoOgAAAAAAApNEAAIAAvg6qCKoI6giqCKoIqgiAAAAAAACo0QAAQABeD1oLWgt6C1oLWgtaC0AAAAAAALDRAACAAL4PqgmqCeoJqgmqCaoPgAAAAAAAsdEAAIAAvg6qCqoK6gqqCqoKqg6AAAAAAAC10QAAgAC+BqoJqgnqCaoJqgmqBoAAAAAAAPTRAAAAAnwCVALUA1QCVAIAAP4PAAAAAAAALNIAAAABfAFUAVQBVA9UAVQBVAEAAQAAAAA00gAAQABeD1oLWgvaC1oLWgtaC0AAAAAAADzSAACAAL4PqgmqCaoJqgmqCaoPgAAAAAAAQdIAAIAAvgaqCaoJqgmqCaoJqgaAAAAAAACA0gAAgAC8ALQAtAe0ALQAAAD+DwAAAAAAAJzSAAAAAXwBVA9UAVQBVAFUD1QBAAEAAQAAuNIAAAAE/ASUBJQElASUBJQElAQABAAEAAC50gAAgAC+AqoCqgKqAqoCqgKqDoAAAAAAALzSAACAAL4OqgiqCKoIqgiqCKoIgAAAAAAAv9IAAIAAvg+qCaoJqgmqCaoJqgmAAIAAAADA0gAAQABeD1oLWgtaC1oLWgtaC0AAAAAAAMjSAACAAL4PqgmqCaoJqgmqCaoPgAAAAAAA8NIAAPwBJAEkASQBJAEAAQAA/g8AAAAAAADx0gAAfABUAVQBVAFUAUABAAF+DwAAAAAAAPTSAAB8AFQAVA9UCFQIQAgACP4JAAAAAAAA+NIAADwALACsDqwKrAqgCoAKvgsAAAAAAAAA0wAAfABUD1QJVAlUCUAJAAl+DwAAAAAAAAHTAAB8AFQAVA9UClQKQAoACn4PAAAAAAAABdMAAHwAVAZUCVQJVAlACQAJfgkABgAAAAAM0wAABAH8AQQBBAH8AQQBAAD+DyAAIAAAAA3TAABEAHwBRAFEAXwBRAEAAX4PEAAQAAAADtMAAEQAfAFEAUQPfABEAQABfg8QABAAAAAQ0wAAhAD8DoQIhAj8CIQIAAj+CRAAEAAAABTTAAAkALwOpAqkCrwKpAqACr4LCAAIAAAAHNMAAEQAfA9ECUQJfAlECQAJfg8QABAAAAAd0wAARAB8D0QKRAp8CkQKAAp+DxAAEAAAAB/TAABEAHwIRAREBHwDRAIABP4IEAgQAAAAKNMAAAQB/AEEAfwBAAD+ByAAIAD+DwAAAAAp0wAARAB8AEQBfAEAAX4BEAEQAX4PAAAAACzTAABEAHwARA98CAAI/gkQCBAI/gkAAAAAfNMAAAQB/AEEAQQB/AEEASABIAD+DwAAAAB90wAARAB8AUQBRAF8AUQBUAEQAX4PAAAAAIDTAABEAHwARA9ECHwIRAhQCBAI/gkAAAAAhNMAAEQAfADEDsQK/ArECsAKiAq+CwAAAACM0wAARAB8D0QJRAl8CUQJUAkQCX4PAAAAAJjTAAAEAfwBBAH8AQQBIAD+BwAA/g8AAAAAmdMAAEQAfABEAXwBRAEQAX4BAAF+DwAAAACc0wAARAB8AEQPfAhECBAI/gkACP4JAAAAAKDTAABEAHwAxA78CsAKiAq8CoAKvgsAAAAAqNMAAEQAfABED3wJRAkQCX4JAAl+DwAAAACr0wAARAB8CEQIfAREAhADfgQABP4IAAgAALTTAAAEAfwBBAEEAfwBBAFQAVAA/g8AAAAAuNMAAIQA/ACEDoQI/AioCCgIKAj+CQAAAAC80wAARAB8AMQOxAr8CtgKmAqYCr4LAAAAAMnTAABEAHwGRAlECXwJaAkoCSgJfgYAAAAA0NMAAAQB/AEEAfwBBAFQAP4HAAD+DwAAAADs0wAERAREBHwERATEB0QEfAREBEQEAAQAAO3TgACiAKICvgKiAuICogK+AqIOgAAAAAAA8NMAAIAApA68CKQI5AikCLwIpAikAIAAAAD00wAAQABSD14LUgtyC1ILXgtSC1IAQAAAAPzTAABAAFIPXglSCXIJUgleCVIPQAAAAAAAAdRAAFIAUgZeCVIJcglSCV4JUgZAAAAAAABc1AAERAREBPwHRAREBEQE/AdEBEQEAAQAAHjUgACkAKQAvACkAKQPpAC8AKQApACAAAAAedRAAGIAYgJ+AmIC4gNiAn4CYg5AAAAAAAB81AAAgACkDrwIpAikC6QIvAikCKQAgAAAAIDUAABAAFIPXgtSC9ILUgteC1ILUgBAAAAAiNQAAEAAUg9eCVIJ0glSCV4JUg9AAAAAAACL1EAAUghSCF4EUgTSAlIEXgRSCFIIQAAAAI3UQABSAFIGXglSCdIJUgleCVIGQAAAAAAA6NSAAKQApAC8D6QApACkALwPpACkAIAAAAAE1QAEhASEBPwEhASEBIQE/ASEBIQEAAQAAAjVAACAAKQOvAikCKQIpAi8CKQIpACAAAAADNUAAEAAUg9eC1ILUgtSC14LUgtSAAAAAAAU1QAAQABSD14JUglSCVIJXglSD0AAAAAAADzVAAAEAfwBBAEEAfwBBAEAAP4PAAAAAAAAPdUAAEQAfAFEAUQBfAFEAQABfg8AAAAAAABA1QAAhAD8DoQIhAj8CIQIAAj+CQAAAAAAAETVAAAkALwOpAqkCrwKpAqACr4LAAAAAAAATNUAAEQAfA9ECUQJfAlECQAJfg8AAAAAAABP1QAARAB8CEQERAJ8AUQCAAT+CAAIAAAAAFHVAABEAHwGRAlECXwJRAkACX4JAAYAAAAAWNUIAOgBGAIcAhgC6AEIAAAA/g8gACAAAABZ1QQAdACMAY4BjAF0AQQBAAF+DxAAEAAAAFzVBABkAJQOlgiUCGQIBAgACP4JIAAgAAAAYNUEADQAzA7OCswKtAqECoAKvgsQABAAAABo1QQAdACMD44JjAl0CQQJAAl+DxAAEAAAAGnVBAA0AEwPTgpMCjQKBAoACn4PEAAQAAAAa9UEAGQIlAiWCJQEZAIEBAAI/gkQCBAAAABt1QQAZACUBpYJlAlkCQQJAAl+BhAAEAAAAHTVAADIACgBHAFoAYAA/gdAAEAA/gcAAAAAddUAAGQAlACWAZQBYAF+ARABEAF+DwAAAAB41QAAZACUAJYOlAhkCP4JIAggCP4JAAAAAITVAABkAJQAlg+UCWQJPgkQCRAJfg8AAAAAh9UAAGQAlAiWCJQIZAT+AhAEEAj+CQAIAACJ1QAAZACUAJYGlAlkCT4JEAkQCX4GAAAAAKXVBABkAJQGlgmUCWQJBAkACX4GKAAoAAAAyNUIAMgBKAIsAigCyAEIAEAAQAD+DwAAAADM1QQAZACUAJYOlAhkCAQIIAggCP4JAAAAANjVBAB0AIwPjgmMCXQJBAkQCRAJfg8AAAAA29UEAGQAlAiWCJQEZAQEAxAEEAj+CQAIAADk1QAA6AEYAhwCGALoAQAA/g8AAP4PAAAAAOzVAAA0AEwAzg7MCrQKgAq+CoAKvgsAAAAA9NUAAGQAlACWD5QJdAkQCX4JAAl+DwAAAAAA1ggA6AAYARwCGAHoAAgAoACgAP4PAAAAAAHWBAB0AIwBjgGMAXQBBAFQAVABfg8AAAAABNYEAGQAlACWDpQIZAgECFAIUAj+CQAAAAAI1gQANABMAE4PTAs0CwALKAt+CwAAAAAAABHWBAB0AIwAjg6MCnQKBApQClAKfg8AAAAAFdYEAGQAlAaWCZQJZAkECVAJUAl+BgAAAAAc1gAA6AEYAhwCOAPoAKAA/g8AAP4PAAAAADjWAAAIBGgEmASYBJwHmASYBGgECAQAAAAAOdYAAIQAtALMAswCzgLMAswCtA6EAAAAAAA81gAAhAC0DswIzAjOCMwIzAi0CIQAAAAAAEDWAABEAFQPbAtsC24LbAtsC1QLRAAAAAAASNYAAIQAlA6sCqwK7gqsCqwKlA6EAAAAAABJ1gAAhACUDqwKrAruCqwKrAqUDoQAAAAAAE3WAACEAJQGrAmsCe4JrAmsCZQGhAAAAAAAVNYEAmQClAKWA5QCZAIEAgAA/g9AAEAAAABV1oQAtALMAs4CzAK0AoQCAAL+DhAAEAAAAFjWhAC0AMwOzgjMCLQIhAgACP4JIAAgAAAAXNYAAFQAbA9uC2wLVAtECwALfgsQABAAAABp1oAAlACsBu4JrAmUCYQJAAl+BhAAEAAAAIzWAAAEAmQClAKWA5QCZAIAAP4PAAAAAAAAjdYAAIQAtADMAs4CzAK0AgAC/g4AAAAAAACf1gAAhAC0CMwIzgTMArQEAAT+CQAIAAAAAKHWAACEAJQGrAnuCawJlAkACX4JAAYAAAAAqNYABAgEaASYB5gEnASYBJgHaAQIBAAEAADE1gAABAEkAVQBVAFWD1QBVAEkAQQBAAAAAMjWAACEALQOzAjMCM4JzAjMCLQIhAAAAAAAzNYAAEQAVA9sC2wL7gtsC2wLVAtEAAAAAADU1gAAhACUDqwKrAquC6wKrAqUDoQAAAAAAOjWAABEAFQPbAtuC2wL1AuAC/4LAAAAAAAA/NaAALQAzADOD8wAtAIAAv4PAAD+DwAAAAAA14AAlACsAK4NrAiUCQAJ/gsACP4LAAAAABjXAAAEATQBTAFOD0wBNAEAAP4PAAAAAAAAINdAAEQAVA9sC+4LbAtUCwALfgsAAAAAAAA01wAABAEkAVQPVAFWAVQBVA8kAQQBAAEAAEnXAACEAJQGrAmsCa4JrAmsCZQGhAAAAAAAUNcAAAgE6AQYBRgFHAUYBRgF6AQIBAAAAABR1wAAhAC0AswCzALOAswCzAK0DoQAAAAAAFTXAACEALQOzAjMCM4IzAjMCLQIhAAAAAAAWNcAAEQAVA9sC2wLbgtsC2wLVAtEAAAAAABZ10AARABUD2wLbAtuCGwBbAFUD0QAAAAAAGHXAACEAJQOrAqsCq4KrAqsCpQOhAAAAAAAZdcAAIQAtAbMCcwJzgnMCcwJtAaEAAAAAABp1wAARABUD2wLbAtuC2wLbAtUC0QAAAAAAGzXAAAEAmQClAKWApQCZAIAAP4PAAAAAAAAcNcAAIQAtA7MCM4IzAi0CAAI/gkAAAAAAACI1wgAyAAoARgCHAIYAugBAAD+DwAAAAAAAIzXBABkAJQAlA6WCJQIZAgACP4JAAAAAAAAkNcEADQAzA7MCs4KzAq0CoAKvgsAAAAAAACY1wQAdACMD4wJjgmMCXQJAAl+DwAAAAAAAJnXBAA0AEwATA9OCkwKNAoACn4PAAAAAAAAndcEAGQAlAaUCZYJlAlkCQAJfgkABgAAAAAQ/gAAAAAAAAAAAAAAAAAACAALAAYAAAAAABH+AAAAAAAAAAAAAAAAAAAAAAIABAAIAAAAEv4AAAAAAAAAAAAAAAAAAAAADAASABIADAAT/gAAAAAAAAAAAAAAAAAAAAAMAwgCAAAAABT+AAAAAAAAAAAAAAAAAAAACIwFCAMAAAAAFf4AAAAAAAAAAAAAAAAAAAAAfgMAAgAAAAAW/gAAAAAAAAAAAAAAAAQAAgBCA2ICEgAMABf+gA+ABIACgAKAAYABgAGAAYACgAKABIAPGP4+ACQAKAAoADAAMAAwADAAKAAoACQAPgAZ/gAAAAAAAAAAAABmBkQEAAAAAAAAAAAAADD+AAAAAAAAAAAAAAwDCAIAAAAAAAAAAAAAMf4AAAAAAAAAAAAA/gcAAAAAAAAAAAAAAAAy/gAAAAAAAAAAAADgAAAAAAAAAAAAAAAAADP+/w8AAAAAAAAAAAAAAAAAAAAAAAAAAAAANP6ZCWYGAAAAAAAAAAAAAAAAAAAAAAAAAAA1/gAIAAQABAACAAIAAgACAAIABAAEAAgAADb+AgAEAAQACAAIAAgACAAIAAQABAACAAAAN/4ACAAEAAQABAAEAAIABAAEAAQABAAEAAg4/gIABAAEAAQABAAIAAQABAAEAAQABAACADn+AAgABAACAAIAAgACAAIAAgACAAQACAAAOv4CAAQACAAIAAgACAAIAAgACAAEAAIAAAA7/gAOAAYAAgACAAIAAgACAAIAAgAGAA4AADz+DgAMAAgACAAIAAgACAAIAAgADAAOAAAAPf4ACgAJAAWABIACgAKAAoAEAAUACQAKAAA+/goACgASABQAJAAoACQAFAASAAoACgAAAD/+AAgABAAEAAIAAgABAAIAAgAEAAQACAAAQP4CAAQABAAIAAgAEAAIAAgABAAEAAIAAABB/gAAAAAAAAABAAEAAQABAAEAAQABAAEAD0L+HgAQABAAEAAQABAAEAAQABAAAAAAAAAAQ/4AAAAAAAAAAwADAAMAAwADAAMADwAJAA9E/h4AEgAeABgAGAAYABgAGAAYAAAAAAAAAEX+AAAAAAgAEAAwAHAA4ADAA8AHAAMAAAAARv4AAAAACAAYACgAyAAQAyAEQASAAwAAAABH/gAOAAIAAgACAAIAAgACAAIAAgACAAIADkj+DgAIAAgACAAIAAgACAAIAAgACAAIAA4ASf4AAAAAAgACAAAAAgACAAAAAgACAAAAAABK/gAAAAACAAIAAAACAAAAAgACAAIAAAAAAEv+AgACAAIAAgACAAIAAgACAAIAAgACAAIATP4KAAoACgAKAAYACgAKAAoABgAKAAoACgBN/gAAAAAABAAEAAAABAAEAAAABAAEAAAAAE7+AAAAAAAEAAQAAAAEAAAABAAEAAQAAAAAT/4ABAAIAAgABAAEAAgACAAEAAQACAAIAARQ/gAAAAAAAAAAAAAACgAGAAAAAAAAAAAAAFH+AAAAAAAAAAAAAgAEAAgAAAAAAAAAAAAAUv4AAAAAAAAAAAAAAAAABAAAAAAAAAAAAABU/gAAAAAAAAAAAAAgCgAGAAAAAAAAAAAAAFX+AAAAAAAAAAAAAEAEAAAAAAAAAAAAAAAAVv4AAAAAAAAgABAAEA2QAGAAAAAAAAAAAABX/gAAAAAAAAAAAAAAAPANAAAAAAAAAAAAAFj+AAAAAAAAAAIAAgACAAIAAgACAAIAAAAAWf4AAAAAAAAAAAAAwAMwDAAAAAAAAAAAAABa/gAAAAAAAAAAEAAgDMADAAAAAAAAAAAAAFv+AAAAAAAAAAAAAOAHEAgAAAAAAAAAAAAAXP4AAAAAAAAAABAIYAeAAAAAAAAAAAAAAABd/gAAAAAAAAAAAADgBxAIAAAAAAAAAAAAAF7+AAAAAAAAAAAAABAI4AcAAAAAAAAAAAAAX/4AAAAAAAAAAEAF8APgB1ABAAAAAAAAAABg/gAAAAAAAAAGYAmQCWAGAAYACQAAAAAAAGH+AAAAAAAAAABgADAAYAAAAAAAAAAAAAAAYv4AAAAAAAAAAQABwAcAAQABAAAAAAAAAABj/gAAAAAAAAAAAAEAAQABAAEAAAAAAAAAAGT+AAAAAAAAAACAAIABgAFAAkACAAAAAAAAZf4AAAAAAABAAkACgAGAAQABAAAAAAAAAABm/gAAAAAAAAAAQAJAAkACQAIAAAAAAAAAAGj+AAAAAAAAAAAQAOAAAAcACAAAAAAAAAAAaf4AAAAAAAAAAGACkASYDJAEIAMAAAAAAABq/gAAAADgABAB4AwAA8AAMAeACAAHAAAAAGv+AAAAAMADIASQCVAKUAmQCSACwAEAAAAAAf8AAAAAAAAAAAAA/AYABAAAAAAAAAAAAAAC/wAAAAAAAAAADwAAAAAADwAAAAAAAAAAAAP/AAAAAJAAkAT8A5AAkAT8A5AAkAAAAAAABP8AAAAAAAAYAiQERARGDIQECAMAAAAAAAAF/wAAeACEAIQEeALAATAAyAMkBCAEwAMAAAb/AAAAAIADeAREBKQEGAMAA8AEAAQAAAAAB/8AAAAAAAAAAAAADwAAAAAAAAAAAAAAAAAI/wAAAAAAAAAAAAAAAAAAAADwAQwGAggAAAn/AAACCAwG8AEAAAAAAAAAAAAAAAAAAAAACv8AAAAAEAEQAaAAQAD8B0AAoAAQARABAAAL/wAAQABAAEAAQAD8B0AAQABAAEAAAAAAAAz/AAAAAAAAAAAAAWABwAAAAAAAAAAAAAAADf8AAEAAQABAAEAAQABAAEAAQABAAAAAAAAO/wAAAAAAAAAAAABgAEAAAAAAAAAAAAAAAA//AAgABAACAAGAAEAAIAAQAAgABAACAAAAEP8AAAAAAADwAQgCBAQEBAgC8AEAAAAAAAAR/wAAAAAAAAAEBAQEBPwHAAQABAAAAAAAABL/AAAAAAAACAQIBAQGBAXEBDgEAAAAAAAAE/8AAAAAAAAIAggERAREBKQEuAMAAAAAAAAU/wAAAAAAAIABYAEQAQgB/AcAAQAAAAAAABX/AAAAAAACfAIkBCQEJAREAoQBAAAAAAAAFv8AAAAAAADwAUgCJAQkBCQCyAMAAAAAAAAX/wAAAAAAAAQABACEB2QAHAAEAAAAAAAAABj/AAAAAAAAmANkBEQERAREBLgDAAAAAAAAGf8AAAAAAAB4AoQEhASEBEgC8AEAAAAAAAAa/wAAAAAAAAAAAAAYAxACAAAAAAAAAAAAABv/AAAAAAAAAAAACIwFCAMAAAAAAAAAAAAAHP8AAEAAQACgAKAAEAEQAQgCCAIEBAAAAAAd/wAAoACgAKAAoACgAKAAoACgAKAAAAAAAB7/AAAAAAQECAIIAhABEAGgAKAAQABAAAAAH/8AAAAAAAAIAAQAhAbEBCQAGAAAAAAAAAAg/wAA4AEYAgQE5AgSCZII4ggSBYQAeAAAACH/AAAAAAAEAAPwAIwAjADwAAADAAQAAAAAIv8AAAAAAAD8B0QERAREBEQEuASAAwAAAAAj/wAAAAAAAPABCAIEBAQEBAQEBAgCAAAAACT/AAAAAAAA/AcEBAQEBAQEBAgC8AEAAAAAJf8AAAAAAAD8B0QERAREBEQEBAQAAAAAAAAm/wAAAAAAAAAA/AdEAEQARABEAAQAAAAAACf/AAAAAPAACAMIAgQEBAREBEQEyAMAAAAAKP8AAAAA/AdAAEAAQABAAEAAQAD8BwAAAAAp/wAAAAAAAAQEBAT8BwQEBAQAAAAAAAAAACr/AAAAAAAAAAIABAAEAAT8AwAAAAAAAAAAK/8AAAAAAAD8B0AAIABQAIgBBAIEBAAAAAAs/wAAAAAAAAAA/AcABAAEAAQABAAAAAAAAC3/AAAAAPwHCABwAIADAAHwAAgA/AcAAAAALv8AAAAAAAD8BwgAMABAAIABAAL8BwAAAAAv/wAAAADwAQgCBAQEBAQEBAQIAvABAAAAADD/AAAAAAAA/AeEAIQAhACEAEgAOAAAAAAAMf8AAAAA+AAEAQICAgICBgIKBAn4CAAAAAAy/wAAAAAAAPwHRABEAEQAxABEAzgEAAAAADP/AAAAAAAAGAIkBEQERASEBAgDAAAAAAAANP8AAAAABAAEAAQA/AcEAAQABAAAAAAAAAA1/wAAAAD8AQACAAQABAAEAAQAAvwBAAAAADb/AAAAAAQAOADAAQAGAAbAATgABAAAAAAAN/8MAPABAAaAA3AADAB4AIADAAbwAQwAAAA4/wAAAAAAAAQEDAKwAUAAsAEMAgQEAAAAADn/AAAAAAQAGABgAIAHYAAYAAQAAAAAAAAAOv8AAAAAAAAEBAQHhAREBDQEDAQEBAAAAAA7/wAAAAAAAAAAAAAAAAAAAAAAAP4PAggCCDz/AgAEAAgAEAAgAEAAgAAAAQACAAQACAAAPf8CCAII/g8AAAAAAAAAAAAAAAAAAAAAAAA+/wAAAAAAAAAAAgABAAEAAgAAAAAAAAAAAD//AAgACAAIAAgACAAIAAgACAAIAAgACAAIQP8AAAAAAAAAAAEAAQACAAAAAAAAAAAAAABB/wAAAAAAACADkASQBJAEkALgBwAAAAAAAEL/AAAAAAAA/gcgBBAEEAQgAsABAAAAAAAAQ/8AAAAAAADAASACEAQQBBAEIAIAAAAAAABE/wAAAAAAAMABIAIQBBAEEAL+BwAAAAAAAEX/AAAAAAAAwAGgApAEkASgBOACAAAAAAAARv8AAAAAAAAQABAA/AcSABIAEgAAAAAAAABH/wAAAAAAALgGRAlECUQJPAkEBQAGAAAAAEj/AAAAAAAA/gcgABAAEAAQAOAHAAAAAAAASf8AAAAAAAAAAAAABgDwBwAAAAAAAAAAAABK/wAAAAAAAAAAAAAAAPsPAAAAAAAAAAAAAEv/AAAAAAAAAAD+B4AAwAAgARAGEAQAAAAATP8AAAAAAAAAAAAA/gMABAAEAAQAAAAAAABN/wAA8AcgABAAEAAQAOAHIAAQABAA4AcAAE7/AAAAAAAA8AcgABAAEAAQAOAHAAAAAAAAT/8AAAAAAADAASACEAQQBCACwAEAAAAAAABQ/wAAAAAAAPwPCAEEAQQBiABwAAAAAAAAAFH/AAAAAAAAcACIAAQBBAEEAfwPAAAAAAAAUv8AAAAAAAAAAPAHIAAQABAAEAAAAAAAAABT/wAAAAAAAGACUASQBJAEkAQgAwAAAAAAAFT/AAAAAAAAEAAQAPwDEAQQBBAEAAAAAAAAVf8AAAAAAADwAwAEAAQABAAC8AcAAAAAAABW/wAAAAAQAGAAgAMABIADYAAQAAAAAAAAAFf/AAAQAOABAAaAA2AAMADAAwAGwAEwAAAAWP8AAAAAAAAQBDACwAFAATACEAQAAAAAAABZ/wAAAAAECBgI4AQAA8AAOAAEAAAAAAAAAFr/AAAAAAAAAAQQBpAFUAQwBBAEAAAAAAAAW/8AAAAAAAAAAAAAAAAAAAAAQAC8BwIIAABc/wAAAAAAAAAAAAD/DwAAAAAAAAAAAAAAAF3/AAACCPwHAAAAAAAAAAAAAAAAAAAAAAAAXv9AAEAAIAAgACAAQACAAIAAgABAAEAAAABf/wAAAAAAAAAAAAAAAAAA/AMCDPgBBg4AAGD/AAACCPwHAAD+DwAAAAAAAAAAAAAAAAAAYf8ABgAJAAkABgAAAAAAAAAAAAAAAAAAAABi/wAAAAD+AQIAAgACAAAAAAAAAAAAAAAAAGP/AAgACAAI8A8AAAAAAAAAAAAAAAAAAAAAZP8AAAABAAIABAAAAAAAAAAAAAAAAAAAAABl/wAAAABgAEAAAAAAAAAAAAAAAAAAAAAAAGb/AABICEgMSAO4AAAAAAAAAAAAAAAAAAAAZ/8AABAE0AMQAGAAAAAAAAAAAAAAAAAAAABo/wAAAAGAAMAPMAAAAAAAAAAAAAAAAAAAAGn/AADgADAMIALgAQAAAAAAAAAAAAAAAAAAav8ABCAE4AcgBAAEAAAAAAAAAAAAAAAAAABr/wAAIAGgBPgHIAAAAAAAAAAAAAAAAAAAAGz/AACAAPAAQA/gAAAAAAAAAAAAAAAAAAAAbf8AAAAEIAQgB+AEAAAAAAAAAAAAAAAAAABu/wAAIASgBKAE4A8AAAAAAAAAAAAAAAAAAG//wAAACOAEAALgAQAAAAAAAAAAAAAAAAAAcP8AAEAAQABAAEAAQAAAAAAAAAAAAAAAAABx/wgICA7oAQgAeAAAAAAAAAAAAAAAAAAAAHL/QADAAEAA8A8MAAQAAAAAAAAAAAAAAAAAc/8AAHgADgaIAXgAAAAAAAAAAAAAAAAAAAB0/wgCCAL4AwgCCAIAAAAAAAAAAAAAAAAAAHX/EAKQAVAE/AcQAAAAAAAAAAAAAAAAAAAAdv8QBBAD/AAQBPADAAAAAAAAAAAAAAAAAAB3/yABEAH8AJAPiACAAAAAAAAAAAAAAAAAAHj/AABgABAEDgPIADgAAAAAAAAAAAAAAAAAef/AADwIEAbwARAAAAAAAAAAAAAAAAAAAAB6/wAACAIIAggC+AcAAAAAAAAAAAAAAAAAAHv/EAD8ABAEEAL8ARAAAAAAAAAAAAAAAAAAfP8AACAIRAwYAoABYAAAAAAAAAAAAAAAAAB9/wAAAAwIAogBeAMADAAAAAAAAAAAAAAAAH7/AAAgAPwDEATQBDgEAAAAAAAAAAAAAAAAf/8AAAwAMAQAA+AAHAAAAAAAAAAAAAAAAACA/2AAEAxOAsgBOAEAAAAAAAAAAAAAAAAAAIH/AABICEgM+ANEAEAAAAAAAAAAAAAAAAAAgv84AAAEHAPAADwAAAAAAAAAAAAAAAAAAACD/yAAJAQkBuQBJAAgAAAAAAAAAAAAAAAAAIT/AAAAAPwHQADAAAAAAAAAAAAAAAAAAAAAhf8AABAEEAP+ABAAEAAAAAAAAAAAAAAAAACG/wAAAAIIAggCCAIAAgAAAAAAAAAAAAAAAIf/AAAICEgGyAE4BgAAAAAAAAAAAAAAAAAAiP8AAAgBiADOBzgAiAEAAAAAAAAAAAAAAACJ/wAAAAQAA+AAHAAAAAAAAAAAAAAAAAAAAIr/AATAAzgAAAA4AMAHAAAAAAAAAAAAAAAAi/8AAPwDIAQgBBAEAAAAAAAAAAAAAAAAAACM/wAACAgIBIgDeAAAAAAAAAAAAAAAAAAAAI3/gAFgABAAYACAAQAGAAAAAAAAAAAAAAAAjv8AANABEAT8BxAA0AEAAAAAAAAAAAAAAACP/wAACADIAIgDaAQYAAAAAAAAAAAAAAAAAJD/AAAgASQCSAJIBAAAAAAAAAAAAAAAAAAAkf8AAvADDALAAgAFAAAAAAAAAAAAAAAAAACS/wAEEAPgALgABAEAAAAAAAAAAAAAAAAAAJP/QABIAPgDSARIBGAAAAAAAAAAAAAAAAAAlP8gAPwBEA7QADgAAAAAAAAAAAAAAAAAAACV/wACCAIIAsgDOAIAAAAAAAAAAAAAAAAAAJb/AABIAkgCSAL4BwAAAAAAAAAAAAAAAAAAl/8AACAAJAwkA+QAAAAAAAAAAAAAAAAAAACY/wAAfAAABAAC/AEAAAAAAAAAAAAAAAAAAJn/AAf8AAAA/AcAAoABAAAAAAAAAAAAAAAAmv8AAPwHAAIAAYAAQAAAAAAAAAAAAAAAAACb/wAA+AcIAggC+AcAAAAAAAAAAAAAAAAAAJz/AAB4AAgMCAP4AAAAAAAAAAAAAAAAAAAAnf8AAAQEGAIAAcAAMAAAAAAAAAAAAAAAAACe/wwAAAAGAAAAAAAAAAAAAAAAAAAAAAAAAJ//BAAKAAQAAAAAAAAAAAAAAAAAAAAAAAAAoP8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACh/wAAAAAQABAAEAAQABAAEADwAwAAAAAAAKL/AAAQABAAEADwAwAAEAAQABAA8AMAAAAAo/8AAAAAEAAQAPADAAAAA/AAAAEAAgAAAACk/wAAAAD4AQABAAEAAQABAAEAAQAAAAAAAKX/AAAAAPADAAIAAhACEAHwABABEAIAAAAApv8AAAAA8AEAAQAAoAFgAnACoAEAAAAAAACn/wAAAADwARABEAEQARABEAEQAQAAAAAAAKj/AAAAAPABEAEQAQAA8AEQARABAAAAAAAAqf8AAAAAyANIAkgCSAJIAkgCeAIAAAAAAACq/wAAAADQAVABcAEAARAAEADwAQAAAAAAAKv/AAAAANABUAFwAQAA8AEQARAB8AEAAAAArP8AAAAA0AFQAXABAADwASABIAHwAQAAAACt/wAAAADQAVABcAEAAYAAcACAAAABAAAAAK7/AAAAANABUAFwAQAA8AFQAVABEAEAAAAAr/8AAAAA0AFQAXAAAAHwARAB8AEQAQAAAACw/wAAAADQAVABcAEAAJABWAKQAQAAAAAAALH/AAAAAPABEAEQARABEAEQAfABAAAAAAAAsv8AAAAA+AEgASABIAEgASAB+AEAAAAAAACz/wAAAADwAUAB8AEAAPABQAHwAQAAAAAAALT/AAAAAPABQAHwAQABgABwAIAAAAEAAAAAtf8AAAAAAAGAAEAAOABAAIAAAAEAAAAAAAC2/wAAAAKAAXAAgAEAAoAB8AAAAQACAAAAALf/AAAAAOAAEAEIAggCCAIQAeAAAAAAAAAAuP8AAAAACAGIAEgAOABIAIgACAEAAAAAAAC5/wAAAAGIAHgAiAAAAYgAeACIAAABAAAAALr/AAAAABABEAGQAHwAkAAQARABAAAAAAAAu/8AAAAASABIAEgASABIAEgA+AEAAAAAAAC8/wAAAADwAVABUAFQAVABUAFQAQAAAAAAAL3/AAAAARAB8AEQARABEAHwARABAAEAAAAAvv8AAAAAEACQAVACWAJQApABEAAAAAAAAADC/wAAAAAAAAAAAAD8D0AAQAAAAAAAAAAAAMP/AAAAAAAAAAD+ByAA/g8AAAAAAAAAAAAAxP8AAAAAAAAAAP4PkACQAAAAAAAAAAAAAADF/wAAAAAAAAAA/g+QAP4PAAAAAAAAAAAAAMb/AAAAAAAAIAAgACAA/gcAAAAAAAAAAAAAx/8AAAAAAAAgACAA/gcAAP4PAAAAAAAAAADK/wAAAAAAAJAAkACQAP4PAAAAAAAAAAAAAMv/AAAAAAAAkACQAP4PAAD+DwAAAAAAAAAAzP8AAAABAAEAAQAB8AEAAQABAAEAAQAAAADN/wAAAAEAAQAB4AEAAQABAAD8D0AAQAAAAM7/AAAAAQAB4AEAAQABAAD8D0AA/A8AAAAAz/8AAAABAAEAAfABAAEAAQAA/g8AAAAAAADS/wABAAEAAfgBAAEAAQAB+AEAAQABAAAAANP/AAAgACAAIAAgAOAHIAAgACAAIAAAAAAA1P8AAEAAQABAAMAHQABAAEABAAH8DwAAAADV/wAAQABAAMAHQABAAQAB/A8AAP4PAAAAANb/AABAAEAAQADAB0AAQABAAAAA/g8AAAAA1/8gACAAIADgByAAIAAgAOAHIAAgACAAAADa/wAAQABAAEAAQABAAEAAQABAAEAAQAAAANv/AACAAIAAgACAAIAAgACAAAAA/g8AAAAA3P8AAAAAAAAAAAAA/g8AAAAAAAAAAAAAAADg/wAAAAAAAOAAEAEIAvwHCAIQAQABAAAAAOH/AAAAAAAEQAb4BUQERAREBAQECAAAAAAA4v8AACAAIAAgACAAIAAgACAAIADgAQAAAADj/wEAAQABAAEAAQABAAEAAQABAAEAAQABAOT/AAAAAAAAAAAAAL4PAAAAAAAAAAAAAAAA5f8AAAAABACYAeABgAfgAZgBBAAAAAAAAADm/wAARAB4AMAHwANwAHgAwANABvgBRAAAAOj/AAAAAP8PAAAAAAAAAAAAAAAAAAAAAAAA6f9AAOAAUAFAAEAAQAAAAAAAAAAAAAAAAADq/xAACAD+DwgAEAAAAAAAAAAAAAAAAAAAAOv/QABAAEAAUAHgAEAAAAAAAAAAAAAAAAAA7P8AAQAC/g8AAgABAAAAAAAAAAAAAAAAAADt/wAA8ADwAPAA8AAAAAAAAAAAAAAAAAAAAO7/AADgABABEAHgAAAAAAAAAAAAAAAAAAAA\"\n    }\n}\n","pxt.json":"{\n    \"name\": \"fonts\",\n    \"description\": \"Fonts for displays (V2 only).\",\n    \"dependencies\": {\n        \"core\": \"*\"\n    },\n    \"files\": [\n        \"font12.jres\"\n    ],\n    \"public\": true,\n    \"targetVersions\": {\n        \"target\": \"7.1.42\",\n        \"pxt\": \"11.4.28\"\n    },\n    \"hidden\": true,\n    \"disablesVariants\": [\n        \"mbdal\"\n    ],\n    \"searchOnly\": true\n}\n"},"color":{"README.md":"# Colors\n\nColor manipulation","colorbuffer.ts":"namespace color {\n    export enum ColorBufferLayout {\n        /**\n         * 24bit RGB color\n         */\n        RGB,\n        /**\n         * 32bit RGB color with alpha\n         */\n        ARGB\n    }\n\n    /**\n     * A buffer of colors\n     */\n    export class ColorBuffer {\n        layout: ColorBufferLayout;\n        buf: Buffer;\n\n        constructor(length: number, layout?: ColorBufferLayout) {\n            this.layout = layout || ColorBufferLayout.RGB;\n            this.buf = control.createBuffer((length | 0) * this.stride);\n        }\n\n        static fromBuffer(buffer: Buffer, layout: ColorBufferLayout) {\n            const b = new ColorBuffer(0, layout);\n            b.buf = buffer.slice();\n            return b;\n        }\n\n        get stride() {\n            return this.layout == ColorBufferLayout.RGB ? 3 : 4;\n        }\n\n        get length() {\n            return Math.idiv(this.buf.length, this.stride);\n        }\n\n        color(index: number): number {\n            index = index | 0;\n            if (index < 0 || index >= this.length)\n                return -1;\n\n            const s = this.stride;\n            const start = index * s;\n            let c = 0;\n            for (let i = 0; i < s; ++i)\n                c = (c << 8) | (this.buf[start + i] & 0xff);\n            return c;\n        }\n\n        setColor(index: number, color: number) {\n            index = index | 0;\n            if (index < 0 || index >= this.length) return;\n\n            const s = this.stride;\n            const start = index * s;\n            for (let i = s - 1; i >= 0; --i) {\n                this.buf[start + i] = color & 0xff;\n                color = color >> 8;\n            }\n        }\n\n        slice(start?: number, length?: number): ColorBuffer {\n            start = start | 0;\n            if (start < 0)\n                start = this.length - start;\n\n            if (length == undefined)\n                length = this.length;\n            length = Math.min(length, this.length - start);\n\n            const output = new ColorBuffer(length, this.layout);\n            for (let i = 0; i < length; ++i) {\n                output.setColor(i, this.color(start + i));\n            }\n\n            return output;\n        }\n\n        /**\n         * Writes the content of the src color buffer starting at the start dstOffset in the current buffer\n         * @param dstOffset\n         * @param src\n         */\n        write(dstOffset: number, src: ColorBuffer): void {\n            if (this.layout == src.layout) {\n                const d = (dstOffset | 0) * this.stride;\n                this.buf.write(d, src.buf);\n            } else {\n                // different color layout\n                const n = Math.min(src.length, this.length - dstOffset);\n                for (let i = 0; i < n; ++i)\n                    this.setColor(dstOffset + i, src.color(i));\n            }\n        }\n    }\n\n    /**\n     * Converts an array of colors into a color buffer\n     */\n    export function createBuffer(colors: number[], layout?: ColorBufferLayout): color.ColorBuffer {\n        const p = new ColorBuffer(colors.length, layout);\n        const n = colors.length;\n        for (let i = 0; i < n; i++) {\n            p.setColor(i, colors[i]);\n        }\n        return p;\n    }\n}","colors.ts":"/**\n * Well known colors\n */\nconst enum Colors {\n    //% block=red\n    //% blockIdentity=color.wellKnown\n    Red = 0xFF0000,\n    //% block=orange\n    //% blockIdentity=color.wellKnown\n    Orange = 0xFF7F00,\n    //% block=yellow\n    //% blockIdentity=color.wellKnown\n    Yellow = 0xFFFF00,\n    //% block=green\n    //% blockIdentity=color.wellKnown\n    Green = 0x00FF00,\n    //% block=blue\n    //% blockIdentity=color.wellKnown\n    Blue = 0x0000FF,\n    //% block=indigo\n    //% blockIdentity=color.wellKnown\n    Indigo = 0x4b0082,\n    //% block=violet\n    //% blockIdentity=color.wellKnown\n    Violet = 0x8a2be2,\n    //% block=purple\n    //% blockIdentity=color.wellKnown\n    Purple = 0xA033E5,\n    //% block=pink\n    //% blockIdentity=color.wellKnown\n    Pink = 0xFF007F,\n    //% block=white\n    //% blockIdentity=color.wellKnown\n    White = 0xFFFFFF,\n    //% block=black\n    //% blockIdentity=color.wellKnown\n    Black = 0x000000\n}\n\n/**\n * Well known color hues\n */\nconst enum ColorHues {\n    //% block=red\n    Red = 0,\n    //% block=orange\n    Orange = 29,\n    //% block=yellow\n    Yellow = 43,\n    //% block=green\n    Green = 86,\n    //% block=aqua\n    Aqua = 125,\n    //% block=blue\n    Blue = 170,\n    //% block=purple\n    Purple = 191,\n    //% block=magenta\n    Magenta = 213,\n    //% block=pink\n    Pink = 234\n}\n\n/**\n * Color manipulation\n */\n//% advanced=1\nnamespace color {\n    /**\n     * Converts red, green, blue channels into a RGB color\n     * @param red value of the red channel between 0 and 255. eg: 255\n     * @param green value of the green channel between 0 and 255. eg: 255\n     * @param blue value of the blue channel between 0 and 255. eg: 255\n     */\n    //% blockId=\"colorsrgb\" block=\"red %red|green %green|blue %blue\"\n    //% red.min=0 red.max=255 green.min=0 green.max=255 blue.min=0 blue.max=255\n    //% help=\"colors/rgb\"\n    //% weight=19 blockGap=8\n    //% blockHidden=true\n    export function rgb(red: number, green: number, blue: number): number {\n        return ((red & 0xFF) << 16) | ((green & 0xFF) << 8) | (blue & 0xFF);\n    }\n\n    export function argb(alpha: number, red: number, green: number, blue: number): number {\n        return ((alpha & 0xFF) << 24) | ((red & 0xFF) << 16) | ((green & 0xFF) << 8) | (blue & 0xFF);\n    }\n\n    /**\n    * Get the RGB value of a known color\n    */\n    //% blockId=colorscolors block=\"%color\"\n    //% help=\"colors/well-known\"\n    //% shim=TD_ID\n    //% weight=20 blockGap=8\n    //% blockHidden=true\n    export function wellKnown(color: Colors): number {\n        return color;\n    }\n\n    /**\n     * Convert an HSV (hue, saturation, value) color to RGB\n     * @param hue value of the hue channel between 0 and 255. eg: 255\n     * @param sat value of the saturation channel between 0 and 255. eg: 255\n     * @param val value of the value channel between 0 and 255. eg: 255\n     */\n\n    //% blockId=\"colorshsv\" block=\"hue %hue|sat %sat|val %val\"\n    //% hue.min=0 hue.max=255 sat.min=0 sat.max=255 val.min=0 val.max=255\n    //% help=\"colors/hsv\"\n    //% weight=17\n    //% blockHidden=true\n    export function hsv(hue: number, sat: number = 255, val: number = 255): number {\n        let h = (hue % 255) >> 0;\n        if (h < 0) h += 255;\n        // scale down to 0..192\n        h = (h * 192 / 255) >> 0;\n\n        //reference: based on FastLED's hsv2rgb rainbow algorithm [https://github.com/FastLED/FastLED](MIT)\n        const invsat = 255 - sat;\n        const brightness_floor = ((val * invsat) / 255) >> 0;\n        const color_amplitude = val - brightness_floor;\n        const section = (h / 0x40) >> 0; // [0..2]\n        const offset = (h % 0x40) >> 0; // [0..63]\n\n        const rampup = offset;\n        const rampdown = (0x40 - 1) - offset;\n\n        const rampup_amp_adj = ((rampup * color_amplitude) / (255 / 4)) >> 0;\n        const rampdown_amp_adj = ((rampdown * color_amplitude) / (255 / 4)) >> 0;\n\n        const rampup_adj_with_floor = (rampup_amp_adj + brightness_floor);\n        const rampdown_adj_with_floor = (rampdown_amp_adj + brightness_floor);\n\n        let r: number;\n        let g: number;\n        let b: number;\n        if (section) {\n            if (section == 1) {\n                // section 1: 0x40..0x7F\n                r = brightness_floor;\n                g = rampdown_adj_with_floor;\n                b = rampup_adj_with_floor;\n            } else {\n                // section 2; 0x80..0xBF\n                r = rampup_adj_with_floor;\n                g = brightness_floor;\n                b = rampdown_adj_with_floor;\n            }\n        } else {\n            // section 0: 0x00..0x3F\n            r = rampdown_adj_with_floor;\n            g = rampup_adj_with_floor;\n            b = brightness_floor;\n        }\n        return rgb(r, g, b);\n    }\n\n    /**\n     * Fade the color by the brightness\n     * @param color color to fade\n     * @param brightness the amount of brightness to apply to the color, eg: 128\n     */\n    //% blockId=\"colorsfade\" block=\"fade %color=neopixel_colors|by %brightness\"\n    //% brightness.min=0 brightness.max=255\n    //% help=\"light/fade\"\n    //% group=\"Color\" weight=18 blockGap=8\n    //% blockHidden=true\n    export function fade(color: number, brightness: number): number {\n        brightness = Math.max(0, Math.min(255, brightness >> 0));\n        if (brightness < 255) {\n            let red = unpackR(color);\n            let green = unpackG(color);\n            let blue = unpackB(color);\n\n            red = (red * brightness) >> 8;\n            green = (green * brightness) >> 8;\n            blue = (blue * brightness) >> 8;\n\n            color = rgb(red, green, blue);\n        }\n        return color;\n    }\n\n    export function blend(color: number, alpha: number, otherColor: number) {\n        alpha = Math.max(0, Math.min(0xff, alpha | 0));\n        const malpha = 0xff - alpha;\n        const r = (unpackR(color) * malpha + unpackR(otherColor) * alpha) >> 8;\n        const g = (unpackG(color) * malpha + unpackG(otherColor) * alpha) >> 8;\n        const b = (unpackB(color) * malpha + unpackB(otherColor) * alpha) >> 8;\n        return rgb(r, g, b);\n    }\n\n    export function gradient(startColor: number, endColor: number, steps: number): ColorBuffer {\n        steps = Math.max(2, steps | 0);\n        const b = new ColorBuffer(steps);\n        b.setColor(0, startColor);\n        b.setColor(b.length - 1, endColor);\n        for (let i = 1; i < steps - 1; ++i) {\n            const alpha = Math.idiv(0xff * i, steps);\n            const c = blend(startColor, alpha, endColor);\n            b.setColor(i, c);\n        }\n        return b;\n    }\n\n    export function unpackR(rgb: number): number {\n        return (rgb >> 16) & 0xFF;\n    }\n    export function unpackG(rgb: number): number {\n        return (rgb >> 8) & 0xFF;\n    }\n    export function unpackB(rgb: number): number {\n        return (rgb >> 0) & 0xFF;\n    }\n\n    export function parseColor(color: string): number {\n        switch (color) {\n            case \"RED\":\n            case \"red\":\n                return Colors.Red;\n            case \"GREEN\":\n            case \"green\":\n                return Colors.Green;\n            case \"BLUE\":\n            case \"blue\":\n                return Colors.Blue;\n            case \"WHITE\":\n            case \"white\":\n                return Colors.White;\n            case \"ORANGE\":\n            case \"orange\":\n                return Colors.Orange;\n            case \"PURPLE\":\n            case \"purple\":\n                return Colors.Purple;\n            case \"YELLOW\":\n            case \"yellow\":\n                return Colors.Yellow;\n            case \"PINK\":\n            case \"pink\":\n                return Colors.Pink;\n            default:\n                return parseInt(color) || 0;\n        }\n    }\n}","pxt.json":"{\n    \"name\": \"color\",\n    \"description\": \"Color manipulation\",\n    \"dependencies\": {\n        \"core\": \"*\"\n    },\n    \"files\": [\n        \"colors.ts\",\n        \"colorbuffer.ts\",\n        \"README.md\"\n    ],\n    \"public\": true,\n    \"targetVersions\": {\n        \"target\": \"7.1.42\",\n        \"pxt\": \"11.4.28\"\n    },\n    \"hidden\": true,\n    \"weight\": 1,\n    \"icon\": \"/static/libs/color.png\"\n}\n"},"audio-recording":{"pxt.json":"{\n    \"name\": \"audio-recording\",\n    \"description\": \"Record sound clips. micro:bit (V2) only\",\n    \"dependencies\": {\n        \"core\": \"*\"\n    },\n    \"files\": [\n        \"recording.ts\",\n        \"recording.cpp\",\n        \"shims.d.ts\"\n    ],\n    \"public\": true,\n    \"targetVersions\": {\n        \"target\": \"7.1.42\",\n        \"pxt\": \"11.4.28\"\n    },\n    \"weight\": 10,\n    \"icon\": \"/static/libs/audio-recording.png\"\n}\n","recording.cpp":"/*\n    The MIT License (MIT)\n\n    Copyright (c) 2022 Lancaster University\n\n    Permission is hereby granted, free of charge, to any person obtaining a\n    copy of this software and associated documentation files (the \"Software\"),\n    to deal in the Software without restriction, including without limitation\n    the rights to use, copy, modify, merge, publish, distribute, sublicense,\n    and/or sell copies of the Software, and to permit persons to whom the\n    Software is furnished to do so, subject to the following conditions:\n    The above copyright notice and this permission notice shall be included in\n    all copies or substantial portions of the Software.\n    THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n    IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n    FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL\n    THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n    LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\n    FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER\n    DEALINGS IN THE SOFTWARE.\n*/\n\n#include \"pxt.h\"\n#include \"MicroBit.h\"\n\n#if MICROBIT_CODAL\n#include \"StreamRecording.h\"\n#endif\n\nusing namespace pxt;\n\nnamespace record {\n\n#if MICROBIT_CODAL\nstatic StreamRecording *recording = NULL;\nstatic SplitterChannel *splitterChannel = NULL;\nstatic MixerChannel *channel = NULL;\n#endif\n\n\nvoid checkEnv() {\n#if MICROBIT_CODAL\n    if (recording == NULL) {\n        int defaultSampleRate = 11000;\n        MicroBitAudio::requestActivation();\n\n        splitterChannel = uBit.audio.splitter->createChannel();\n        uBit.audio.mic->setSampleRate( defaultSampleRate );\n\n        recording = new StreamRecording(*splitterChannel);\n\n        channel = uBit.audio.mixer.addChannel(*recording, defaultSampleRate);\n\n        channel->setVolume(75.0);\n        uBit.audio.mixer.setVolume(1000);\n        uBit.audio.setSpeakerEnabled(true);\n    }\n#endif\n}\n\n/**\n * Record an audio clip\n */\n//% promise\nvoid record() {\n#if MICROBIT_CODAL\n    checkEnv();\n    recording->recordAsync();\n#else\n    target_panic(PANIC_VARIANT_NOT_SUPPORTED);\n#endif\n}\n\n/**\n * Play the audio clip that is saved in the buffer\n */\n//%\nvoid play() {\n#if MICROBIT_CODAL\n    checkEnv();\n    recording->playAsync();\n#else\n    target_panic(PANIC_VARIANT_NOT_SUPPORTED);\n#endif\n}\n\n/**\n * Stop recording\n */\n//%\nvoid stop() {\n#if MICROBIT_CODAL\n    checkEnv();\n    recording->stop();\n#else\n    target_panic(PANIC_VARIANT_NOT_SUPPORTED);\n#endif\n}\n\n/**\n * Clear the buffer\n */\n//%\nvoid erase() {\n#if MICROBIT_CODAL\n    checkEnv();\n    recording->erase();\n#endif\n}\n\n/**\n * Set sensitity of the microphone input\n */\n//%\nvoid setMicrophoneGain(float gain) {\n#if MICROBIT_CODAL\n    uBit.audio.processor->setGain(gain);\n#endif\n}\n\n/**\n * Get how long the recorded audio clip is\n */\n//%\nint audioDuration(int sampleRate) {\n#if MICROBIT_CODAL\n    return recording->duration(sampleRate);\n#else\n    target_panic(PANIC_VARIANT_NOT_SUPPORTED);\n    return MICROBIT_NOT_SUPPORTED;\n#endif\n}\n\n/**\n * Get whether the playback is active\n */\n//%\nbool audioIsPlaying() {\n#if MICROBIT_CODAL\n    return recording->isPlaying();\n#else\n    return false;\n#endif\n}\n\n/**\n * Get whether the microphone is listening\n */\n//%\nbool audioIsRecording() {\n#if MICROBIT_CODAL\n    return recording->isRecording();\n#else\n    return false;\n#endif\n}\n\n/**\n * Get whether the board is recording or playing back\n */\n//%\nbool audioIsStopped() {\n#if MICROBIT_CODAL\n    return recording->isStopped();\n#else\n    return false;\n#endif\n}\n\n/**\n * Change the sample rate of the splitter channel (audio input)\n */\n//%\nvoid setInputSampleRate(int sampleRate) {\n#if MICROBIT_CODAL\n    checkEnv();\n    uBit.audio.mic->setSampleRate(sampleRate);\n#else\n    target_panic(PANIC_VARIANT_NOT_SUPPORTED);\n#endif\n}\n\n\n/**\n * Change the sample rate of the mixer channel (audio output)\n */\n//%\nvoid setOutputSampleRate(int sampleRate) {\n#if MICROBIT_CODAL\n    checkEnv();\n    channel->setSampleRate(sampleRate);\n#else\n    target_panic(PANIC_VARIANT_NOT_SUPPORTED);\n#endif\n}\n\n/**\n * Set the sample rate for both input and output\n*/\n//%\nvoid setBothSamples(int sampleRate) {\n#if MICROBIT_CODAL\n    setOutputSampleRate(sampleRate);\n    uBit.audio.mic->setSampleRate(sampleRate);\n#else\n    target_panic(PANIC_VARIANT_NOT_SUPPORTED);\n#endif\n}\n\n} // namespace record","recording.ts":"/*\n    The MIT License (MIT)\n\n    Copyright (c) 2022 Lancaster University\n\n    Permission is hereby granted, free of charge, to any person obtaining a\n    copy of this software and associated documentation files (the \"Software\"),\n    to deal in the Software without restriction, including without limitation\n    the rights to use, copy, modify, merge, publish, distribute, sublicense,\n    and/or sell copies of the Software, and to permit persons to whom the\n    Software is furnished to do so, subject to the following conditions:\n    The above copyright notice and this permission notice shall be included in\n    all copies or substantial portions of the Software.\n    THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n    IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n    FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL\n    THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n    LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\n    FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER\n    DEALINGS IN THE SOFTWARE.\n*/\n\n/**\n * Functions to operate the v2 on-board microphone and speaker.\n */\n//% weight=5 color=#015f85 icon=\"\\uf130\" block=\"Record\" advanced=false\nnamespace record {\n    // \n\n    export enum AudioEvent {\n        //% block=\"starts playing\"\n        StartedPlaying,\n        //% block=\"stops playing\"\n        StoppedPlaying,\n        //% block=\"starts recording\"\n        StartedRecording,\n        //% block=\"stops recording\"\n        StoppedRecording\n    }\n\n    export enum AudioLevels {\n        //% block=\"low\"\n        Low = 1,\n        //% block=\"medium\"\n        Medium,\n        //% block=\"high\"\n        High\n    }\n\n    export enum AudioSampleRateScope {\n        //% block=\"everything\"\n        Everything,\n        //% block=\"playback\"\n        Playback,\n        //% block=\"recording\"\n        Recording\n    }\n\n    export enum AudioRecordingMode {\n        //% block=\"stopped\"\n        Stopped,\n        //% block=\"recording\"\n        Recording,\n        //% block=\"playing\"\n        Playing\n    }\n\n    export enum AudioStatus {\n        //% block=\"playing\"\n        Playing,\n        //% block=\"recording\"\n        Recording,\n        //% block=\"stopped\"\n        Stopped,\n        //% block=\"empty\"\n        BufferEmpty,\n    }\n\n    export enum BlockingState {\n        //% block=\"until done\"\n        Blocking,\n        //% block=\"in background\"\n        Nonblocking\n    }\n\n    let _recordingPresent: boolean = false;\n\n    function audioNotRecording(): boolean {\n        return !audioIsRecording();\n    }\n\n    function audioNotPlaying(): boolean {\n        return !audioIsPlaying();\n    }\n\n    /**\n     * Record an audio clip for a maximum of 3 seconds\n     */\n    //% block=\"record audio clip $mode\"\n    //% blockId=\"record_startRecording\"\n    //% weight=70\n    //% parts=\"microphone\"\n    //% help=record/start-recording\n    export function startRecording(mode: BlockingState): void {\n        music._onStopSound(stopPlayback);\n        eraseRecording();\n        record();\n        if (mode === BlockingState.Blocking) pauseUntil(audioNotRecording);\n        _recordingPresent = true;\n    }\n\n    /**\n     * Play recorded audio\n     */\n    //% block=\"play audio clip $mode\"\n    //% blockId=\"record_playAudio\"\n    //% weight=60\n    //% parts=\"microphone\"\n    //% help=record/play-audio\n    export function playAudio(mode: BlockingState): void {\n        play();\n        if (mode === BlockingState.Blocking) pauseUntil(audioNotPlaying);\n    }\n\n    function stopPlayback(): void {\n        if (audioIsPlaying()) {\n            stop();\n        }\n    }\n\n    //% shim=record::stop\n    export function stopRecording(): void {\n    }\n\n    export function eraseRecording(): void {\n        _recordingPresent = false;\n        erase();\n        return\n    }\n\n    /**\n     * Test what the audio is doing\n     */\n    //% block=\"audio is $status\"\n    //% blockId=\"record_audioStatus\"\n    //% parts=\"microphone\"\n    //% help=record/audio-status\n    export function audioStatus(status: AudioStatus): boolean {\n        switch (status) {\n            case AudioStatus.Playing:\n                return audioIsPlaying();\n            case AudioStatus.Recording:\n                return audioIsRecording();\n            case AudioStatus.Stopped:\n                return audioIsStopped();\n            case AudioStatus.BufferEmpty:\n                return !_recordingPresent;\n        }\n    }\n\n    /**\n     * Change how sensitive the microphone is. This changes the recording quality!\n     */\n    //% block=\"set microphone sensitivity to $gain\"\n    //% blockId=\"record_setMicGain\"\n    //% parts=\"microphone\"\n    //% weight=30\n    //% help=record/set-mic-gain\n    export function setMicGain(gain: AudioLevels): void {\n        switch (gain) {\n            case AudioLevels.Low:\n                setMicrophoneGain(0.079);\n                break;\n            case AudioLevels.Medium:\n                setMicrophoneGain(0.2);\n                break;\n            case AudioLevels.High:\n                setMicrophoneGain(1.0);\n                break;\n        }\n    }\n\n    /**\n     * Set the sample frequency for recording, playback, or both (default)\n     * \n     * @param hz The sample frequency, in Hz\n     */\n    //% block=\"set sample rate to $hz || for $scope\"\n    //% blockId=\"record_setSampleRate\"\n    //% hz.min=1000 hz.max=22000 hz.defl=11000\n    //% expandableArgumentMode=\"enabled\"\n    //% parts=\"microphone\"\n    //% weight=40\n    //% help=record/set-sample-rate\n    export function setSampleRate(hz: number, scope?: AudioSampleRateScope): void {\n        switch (scope) {\n            case AudioSampleRateScope.Playback:\n                setOutputSampleRate(hz);\n                break;\n            case AudioSampleRateScope.Recording:\n                setInputSampleRate(hz);\n                break;\n            case AudioSampleRateScope.Everything:\n            default:\n                setBothSamples(hz);\n                break;\n        }\n    }\n}","shims.d.ts":"// Auto-generated. Do not edit.\ndeclare namespace record {\n\n    /**\n     * Record an audio clip\n     */\n    //% promise shim=record::record\n    function record(): void;\n\n    /**\n     * Play the audio clip that is saved in the buffer\n     */\n    //% shim=record::play\n    function play(): void;\n\n    /**\n     * Stop recording\n     */\n    //% shim=record::stop\n    function stop(): void;\n\n    /**\n     * Clear the buffer\n     */\n    //% shim=record::erase\n    function erase(): void;\n\n    /**\n     * Set sensitity of the microphone input\n     */\n    //% shim=record::setMicrophoneGain\n    function setMicrophoneGain(gain: number): void;\n\n    /**\n     * Get how long the recorded audio clip is\n     */\n    //% shim=record::audioDuration\n    function audioDuration(sampleRate: int32): int32;\n\n    /**\n     * Get whether the playback is active\n     */\n    //% shim=record::audioIsPlaying\n    function audioIsPlaying(): boolean;\n\n    /**\n     * Get whether the microphone is listening\n     */\n    //% shim=record::audioIsRecording\n    function audioIsRecording(): boolean;\n\n    /**\n     * Get whether the board is recording or playing back\n     */\n    //% shim=record::audioIsStopped\n    function audioIsStopped(): boolean;\n\n    /**\n     * Change the sample rate of the splitter channel (audio input)\n     */\n    //% shim=record::setInputSampleRate\n    function setInputSampleRate(sampleRate: int32): void;\n\n    /**\n     * Change the sample rate of the mixer channel (audio output)\n     */\n    //% shim=record::setOutputSampleRate\n    function setOutputSampleRate(sampleRate: int32): void;\n\n    /**\n     * Set the sample rate for both input and output\n     */\n    //% shim=record::setBothSamples\n    function setBothSamples(sampleRate: int32): void;\n}\n\n// Auto-generated. Do not edit. Really.\n"}},"apiInfo":{"libs/core":{"apis":{"byQName":{"Math":{"kind":5,"retType":"","attributes":{"jsDoc":"More complex operations with numbers."}},"Math.PI":{"kind":4,"retType":"number","attributes":{"blockIdentity":"Math._constant","block":"π","_def":{"parts":[{"kind":"label","text":"π","style":[]}],"parameters":[]}}},"Math.E":{"kind":4,"retType":"number","attributes":{"blockIdentity":"Math._constant","block":"e","_def":{"parts":[{"kind":"label","text":"e","style":[]}],"parameters":[]}}},"Math.LN2":{"kind":4,"retType":"number","attributes":{"blockIdentity":"Math._constant","block":"ln(2)","_def":{"parts":[{"kind":"label","text":"ln(2)","style":[]}],"parameters":[]}}},"Math.LN10":{"kind":4,"retType":"number","attributes":{"blockIdentity":"Math._constant","block":"ln(10)","_def":{"parts":[{"kind":"label","text":"ln(10)","style":[]}],"parameters":[]}}},"Math.LOG2E":{"kind":4,"retType":"number","attributes":{"blockIdentity":"Math._constant","block":"log₂(e)","_def":{"parts":[{"kind":"label","text":"log₂(e)","style":[]}],"parameters":[]}}},"Math.LOG10E":{"kind":4,"retType":"number","attributes":{"blockIdentity":"Math._constant","block":"log₁₀(e)","_def":{"parts":[{"kind":"label","text":"log₁₀(e)","style":[]}],"parameters":[]}}},"Math.SQRT1_2":{"kind":4,"retType":"number","attributes":{"blockIdentity":"Math._constant","block":"√½","_def":{"parts":[{"kind":"label","text":"√½","style":[]}],"parameters":[]}}},"Math.SQRT2":{"kind":4,"retType":"number","attributes":{"blockIdentity":"Math._constant","block":"√2","_def":{"parts":[{"kind":"label","text":"√2","style":[]}],"parameters":[]}}},"Math.map":{"kind":-3,"retType":"number","attributes":{"paramDefl":{"fromHigh":"1023","toHigh":"4"},"help":"math/map","weight":10,"blockGap":"8","blockId":"math_map","block":"map %value|from low %fromLow|high %fromHigh|to low %toLow|high %toHigh","inlineInputMode":"inline","paramHelp":{"value":"value to map in ranges","fromLow":"the lower bound of the value's current range","fromHigh":"the upper bound of the value's current range, eg: 1023","toLow":"the lower bound of the value's target range","toHigh":"the upper bound of the value's target range, eg: 4"},"jsDoc":"Re-maps a number from one range to another. That is, a value of ``from low`` would get mapped to ``to low``, a value of ``from high`` to ``to high``, values in-between to values in-between, etc.","_def":{"parts":[{"kind":"label","text":"map ","style":[]},{"kind":"param","name":"value","ref":false},{"kind":"break"},{"kind":"label","text":"from low ","style":[]},{"kind":"param","name":"fromLow","ref":false},{"kind":"break"},{"kind":"label","text":"high ","style":[]},{"kind":"param","name":"fromHigh","ref":false},{"kind":"break"},{"kind":"label","text":"to low ","style":[]},{"kind":"param","name":"toLow","ref":false},{"kind":"break"},{"kind":"label","text":"high ","style":[]},{"kind":"param","name":"toHigh","ref":false}],"parameters":[{"kind":"param","name":"value","ref":false},{"kind":"param","name":"fromLow","ref":false},{"kind":"param","name":"fromHigh","ref":false},{"kind":"param","name":"toLow","ref":false},{"kind":"param","name":"toHigh","ref":false}]}},"parameters":[{"name":"value","description":"value to map in ranges"},{"name":"fromLow","description":"the lower bound of the value's current range"},{"name":"fromHigh","description":"the upper bound of the value's current range, eg: 1023","default":"1023"},{"name":"toLow","description":"the lower bound of the value's target range"},{"name":"toHigh","description":"the upper bound of the value's target range, eg: 4","default":"4"}]},"Math.constrain":{"kind":-3,"retType":"number","attributes":{"help":"math/constrain","weight":11,"blockGap":"8","blockId":"math_constrain_value","block":"constrain %value|between %low|and %high","paramHelp":{"x":"the number to constrain, all data types","y":"the lower end of the range, all data types","z":"the upper end of the range, all data types"},"jsDoc":"Constrains a number to be within a range","_def":{"parts":[{"kind":"label","text":"constrain ","style":[]},{"kind":"param","name":"value","ref":false},{"kind":"break"},{"kind":"label","text":"between ","style":[]},{"kind":"param","name":"low","ref":false},{"kind":"break"},{"kind":"label","text":"and ","style":[]},{"kind":"param","name":"high","ref":false}],"parameters":[{"kind":"param","name":"value","ref":false},{"kind":"param","name":"low","ref":false},{"kind":"param","name":"high","ref":false}]}},"parameters":[{"name":"value"},{"name":"low"},{"name":"high"}]},"Math.isin":{"kind":-3,"retType":"number","attributes":{"help":"math/isin","weight":11,"advanced":true,"blockGap":"8","paramHelp":{"theta":"input angle from 0-255"},"jsDoc":"Returns the sine of an input angle. This is an 8-bit approximation."},"parameters":[{"name":"theta","description":"input angle from 0-255"}]},"Math.icos":{"kind":-3,"retType":"number","attributes":{"help":"math/icos","weight":10,"advanced":true,"blockGap":"8","paramHelp":{"theta":"input angle from 0-255"},"jsDoc":"Returns the cosine of an input angle. This is an 8-bit approximation."},"parameters":[{"name":"theta","description":"input angle from 0-255"}]},"Math._constant":{"kind":-3,"retType":"number","attributes":{"shim":"TD_ID","block":"$MEMBER","constantShim":true,"weight":0,"_def":{"parts":[{"kind":"param","name":"MEMBER","ref":true}],"parameters":[{"kind":"param","name":"MEMBER","ref":true}]}},"parameters":[{"name":"MEMBER"}]},"Number":{"kind":5,"retType":"","extendsTypes":["Number"]},"Number.EPSILON":{"kind":4,"retType":"number"},"DAL":{"kind":6,"retType":"DAL","extendsTypes":["DAL","Number"]},"NumberFormat":{"kind":6,"retType":"NumberFormat","extendsTypes":["NumberFormat","Number"]},"NumberFormat.Int8LE":{"retType":"NumberFormat.Int8LE","extendsTypes":["NumberFormat.Int8LE","Number"],"pyQName":"NumberFormat.INT8_LE"},"NumberFormat.UInt8LE":{"retType":"NumberFormat.UInt8LE","extendsTypes":["NumberFormat.UInt8LE","Number"],"pyQName":"NumberFormat.UINT8_LE"},"NumberFormat.Int16LE":{"retType":"NumberFormat.Int16LE","extendsTypes":["NumberFormat.Int16LE","Number"],"pyQName":"NumberFormat.INT16_LE"},"NumberFormat.UInt16LE":{"retType":"NumberFormat.UInt16LE","extendsTypes":["NumberFormat.UInt16LE","Number"],"pyQName":"NumberFormat.UINT16_LE"},"NumberFormat.Int32LE":{"retType":"NumberFormat.Int32LE","extendsTypes":["NumberFormat.Int32LE","Number"],"pyQName":"NumberFormat.INT32_LE"},"NumberFormat.Int8BE":{"retType":"NumberFormat.Int8BE","extendsTypes":["NumberFormat.Int8BE","Number"],"pyQName":"NumberFormat.INT8_BE"},"NumberFormat.UInt8BE":{"retType":"NumberFormat.UInt8BE","extendsTypes":["NumberFormat.UInt8BE","Number"],"pyQName":"NumberFormat.UINT8_BE"},"NumberFormat.Int16BE":{"retType":"NumberFormat.Int16BE","extendsTypes":["NumberFormat.Int16BE","Number"],"pyQName":"NumberFormat.INT16_BE"},"NumberFormat.UInt16BE":{"retType":"NumberFormat.UInt16BE","extendsTypes":["NumberFormat.UInt16BE","Number"],"pyQName":"NumberFormat.UINT16_BE"},"NumberFormat.Int32BE":{"retType":"NumberFormat.Int32BE","extendsTypes":["NumberFormat.Int32BE","Number"],"pyQName":"NumberFormat.INT32_BE"},"NumberFormat.UInt32LE":{"retType":"NumberFormat.UInt32LE","extendsTypes":["NumberFormat.UInt32LE","Number"],"pyQName":"NumberFormat.UINT32_LE"},"NumberFormat.UInt32BE":{"retType":"NumberFormat.UInt32BE","extendsTypes":["NumberFormat.UInt32BE","Number"],"pyQName":"NumberFormat.UINT32_BE"},"NumberFormat.Float32LE":{"retType":"NumberFormat.Float32LE","extendsTypes":["NumberFormat.Float32LE","Number"],"pyQName":"NumberFormat.FLOAT32_LE"},"NumberFormat.Float64LE":{"retType":"NumberFormat.Float64LE","extendsTypes":["NumberFormat.Float64LE","Number"],"pyQName":"NumberFormat.FLOAT64_LE"},"NumberFormat.Float32BE":{"retType":"NumberFormat.Float32BE","extendsTypes":["NumberFormat.Float32BE","Number"],"pyQName":"NumberFormat.FLOAT32_BE"},"NumberFormat.Float64BE":{"retType":"NumberFormat.Float64BE","extendsTypes":["NumberFormat.Float64BE","Number"],"pyQName":"NumberFormat.FLOAT64_BE"},"PerfCounters":{"kind":6,"retType":"PerfCounters","extendsTypes":["PerfCounters","Number"]},"PerfCounters.GC":{"retType":"PerfCounters","extendsTypes":["PerfCounters.GC","Number"]},"images":{"kind":5,"retType":"","attributes":{"color":"#7600A8","weight":31,"icon":"","advanced":true,"jsDoc":"Creation, manipulation and display of LED images."}},"basic":{"kind":5,"retType":"","attributes":{"color":"#1E90FF","weight":116,"icon":"","jsDoc":"Provides access to basic micro:bit functionality."}},"Button":{"kind":6,"retType":"Button","extendsTypes":["Button","Number"]},"Button.A":{"retType":"Button.A","extendsTypes":["Button.A","Number"]},"Button.B":{"retType":"Button.B","extendsTypes":["Button.B","Number"]},"Button.AB":{"retType":"Button.AB","attributes":{"block":"A+B","_def":{"parts":[{"kind":"label","text":"A+B","style":[]}],"parameters":[]}},"extendsTypes":["Button.AB","Number"]},"Dimension":{"kind":6,"retType":"Dimension","extendsTypes":["Dimension","Number"]},"Dimension.X":{"retType":"Dimension.X","attributes":{"block":"x","_def":{"parts":[{"kind":"label","text":"x","style":[]}],"parameters":[]}},"extendsTypes":["Dimension.X","Number"]},"Dimension.Y":{"retType":"Dimension.Y","attributes":{"block":"y","_def":{"parts":[{"kind":"label","text":"y","style":[]}],"parameters":[]}},"extendsTypes":["Dimension.Y","Number"]},"Dimension.Z":{"retType":"Dimension.Z","attributes":{"block":"z","_def":{"parts":[{"kind":"label","text":"z","style":[]}],"parameters":[]}},"extendsTypes":["Dimension.Z","Number"]},"Dimension.Strength":{"retType":"Dimension.Strength","attributes":{"block":"strength","_def":{"parts":[{"kind":"label","text":"strength","style":[]}],"parameters":[]}},"extendsTypes":["Dimension.Strength","Number"],"pyQName":"Dimension.STRENGTH"},"Rotation":{"kind":6,"retType":"Rotation","extendsTypes":["Rotation","Number"]},"Rotation.Pitch":{"retType":"Rotation.Pitch","attributes":{"block":"pitch","_def":{"parts":[{"kind":"label","text":"pitch","style":[]}],"parameters":[]}},"extendsTypes":["Rotation.Pitch","Number"],"pyQName":"Rotation.PITCH"},"Rotation.Roll":{"retType":"Rotation.Roll","attributes":{"block":"roll","_def":{"parts":[{"kind":"label","text":"roll","style":[]}],"parameters":[]}},"extendsTypes":["Rotation.Roll","Number"],"pyQName":"Rotation.ROLL"},"TouchPin":{"kind":6,"retType":"TouchPin","extendsTypes":["TouchPin","Number"]},"TouchPin.P0":{"retType":"TouchPin.P0","extendsTypes":["TouchPin.P0","Number"]},"TouchPin.P1":{"retType":"TouchPin.P1","extendsTypes":["TouchPin.P1","Number"]},"TouchPin.P2":{"retType":"TouchPin.P2","extendsTypes":["TouchPin.P2","Number"]},"AcceleratorRange":{"kind":6,"retType":"AcceleratorRange","extendsTypes":["AcceleratorRange","Number"]},"AcceleratorRange.OneG":{"retType":"AcceleratorRange.OneG","attributes":{"block":"1g","jsDoc":"The accelerator measures forces up to 1 gravity","_def":{"parts":[{"kind":"label","text":"1g","style":[]}],"parameters":[]}},"extendsTypes":["AcceleratorRange.OneG","Number"],"pyQName":"AcceleratorRange.ONE_G"},"AcceleratorRange.TwoG":{"retType":"AcceleratorRange.TwoG","attributes":{"block":"2g","jsDoc":"The accelerator measures forces up to 2 gravity","_def":{"parts":[{"kind":"label","text":"2g","style":[]}],"parameters":[]}},"extendsTypes":["AcceleratorRange.TwoG","Number"],"pyQName":"AcceleratorRange.TWO_G"},"AcceleratorRange.FourG":{"retType":"AcceleratorRange.FourG","attributes":{"block":"4g","jsDoc":"The accelerator measures forces up to 4 gravity","_def":{"parts":[{"kind":"label","text":"4g","style":[]}],"parameters":[]}},"extendsTypes":["AcceleratorRange.FourG","Number"],"pyQName":"AcceleratorRange.FOUR_G"},"AcceleratorRange.EightG":{"retType":"AcceleratorRange.EightG","attributes":{"block":"8g","jsDoc":"The accelerator measures forces up to 8 gravity","_def":{"parts":[{"kind":"label","text":"8g","style":[]}],"parameters":[]}},"extendsTypes":["AcceleratorRange.EightG","Number"],"pyQName":"AcceleratorRange.EIGHT_G"},"Gesture":{"kind":6,"retType":"Gesture","extendsTypes":["Gesture","Number"]},"Gesture.Shake":{"retType":"Gesture.Shake","attributes":{"block":"shake","jres":"gestures.shake","jsDoc":"Raised when shaken","whenUsed":true,"_def":{"parts":[{"kind":"label","text":"shake","style":[]}],"parameters":[]}},"extendsTypes":["Gesture.Shake","Number"],"pyQName":"Gesture.SHAKE"},"Gesture.LogoUp":{"retType":"Gesture.LogoUp","attributes":{"block":"logo up","jres":"gestures.tiltforward","jsDoc":"Raised when the logo is upward and the screen is vertical","whenUsed":true,"_def":{"parts":[{"kind":"label","text":"logo up","style":[]}],"parameters":[]}},"extendsTypes":["Gesture.LogoUp","Number"],"pyQName":"Gesture.LOGO_UP"},"Gesture.LogoDown":{"retType":"Gesture.LogoDown","attributes":{"block":"logo down","jres":"gestures.tiltbackwards","jsDoc":"Raised when the logo is downward and the screen is vertical","whenUsed":true,"_def":{"parts":[{"kind":"label","text":"logo down","style":[]}],"parameters":[]}},"extendsTypes":["Gesture.LogoDown","Number"],"pyQName":"Gesture.LOGO_DOWN"},"Gesture.ScreenUp":{"retType":"Gesture.ScreenUp","attributes":{"block":"screen up","jres":"gestures.frontsideup","jsDoc":"Raised when the screen is pointing up and the board is horizontal","whenUsed":true,"_def":{"parts":[{"kind":"label","text":"screen up","style":[]}],"parameters":[]}},"extendsTypes":["Gesture.ScreenUp","Number"],"pyQName":"Gesture.SCREEN_UP"},"Gesture.ScreenDown":{"retType":"Gesture.ScreenDown","attributes":{"block":"screen down","jres":"gestures.backsideup","jsDoc":"Raised when the screen is pointing down and the board is horizontal","whenUsed":true,"_def":{"parts":[{"kind":"label","text":"screen down","style":[]}],"parameters":[]}},"extendsTypes":["Gesture.ScreenDown","Number"],"pyQName":"Gesture.SCREEN_DOWN"},"Gesture.TiltLeft":{"retType":"Gesture.TiltLeft","attributes":{"block":"tilt left","jres":"gestures.tiltleft","jsDoc":"Raised when the screen is pointing left","whenUsed":true,"_def":{"parts":[{"kind":"label","text":"tilt left","style":[]}],"parameters":[]}},"extendsTypes":["Gesture.TiltLeft","Number"],"pyQName":"Gesture.TILT_LEFT"},"Gesture.TiltRight":{"retType":"Gesture.TiltRight","attributes":{"block":"tilt right","jres":"gestures.tiltright","jsDoc":"Raised when the screen is pointing right","whenUsed":true,"_def":{"parts":[{"kind":"label","text":"tilt right","style":[]}],"parameters":[]}},"extendsTypes":["Gesture.TiltRight","Number"],"pyQName":"Gesture.TILT_RIGHT"},"Gesture.FreeFall":{"retType":"Gesture.FreeFall","attributes":{"block":"free fall","jres":"gestures.freefall","jsDoc":"Raised when the board is falling!","whenUsed":true,"_def":{"parts":[{"kind":"label","text":"free fall","style":[]}],"parameters":[]}},"extendsTypes":["Gesture.FreeFall","Number"],"pyQName":"Gesture.FREE_FALL"},"Gesture.ThreeG":{"retType":"Gesture.ThreeG","attributes":{"block":"3g","jres":"gestures.impact3g","jsDoc":"Raised when a 3G shock is detected","whenUsed":true,"_def":{"parts":[{"kind":"label","text":"3g","style":[]}],"parameters":[]}},"extendsTypes":["Gesture.ThreeG","Number"],"pyQName":"Gesture.THREE_G"},"Gesture.SixG":{"retType":"Gesture.SixG","attributes":{"block":"6g","jres":"gestures.impact6g","jsDoc":"Raised when a 6G shock is detected","whenUsed":true,"_def":{"parts":[{"kind":"label","text":"6g","style":[]}],"parameters":[]}},"extendsTypes":["Gesture.SixG","Number"],"pyQName":"Gesture.SIX_G"},"Gesture.EightG":{"retType":"Gesture.EightG","attributes":{"block":"8g","jres":"gestures.impact8g","jsDoc":"Raised when a 8G shock is detected","whenUsed":true,"_def":{"parts":[{"kind":"label","text":"8g","style":[]}],"parameters":[]}},"extendsTypes":["Gesture.EightG","Number"],"pyQName":"Gesture.EIGHT_G"},"MesDpadButtonInfo":{"kind":6,"retType":"MesDpadButtonInfo","extendsTypes":["MesDpadButtonInfo","Number"]},"MesDpadButtonInfo.ADown":{"retType":"MesDpadButtonInfo.ADown","attributes":{"block":"A down","_def":{"parts":[{"kind":"label","text":"A down","style":[]}],"parameters":[]}},"extendsTypes":["MesDpadButtonInfo.ADown","Number"],"pyQName":"MesDpadButtonInfo.ADOWN"},"MesDpadButtonInfo.AUp":{"retType":"MesDpadButtonInfo.AUp","attributes":{"block":"A up","_def":{"parts":[{"kind":"label","text":"A up","style":[]}],"parameters":[]}},"extendsTypes":["MesDpadButtonInfo.AUp","Number"],"pyQName":"MesDpadButtonInfo.AUP"},"MesDpadButtonInfo.BDown":{"retType":"MesDpadButtonInfo.BDown","attributes":{"block":"B down","_def":{"parts":[{"kind":"label","text":"B down","style":[]}],"parameters":[]}},"extendsTypes":["MesDpadButtonInfo.BDown","Number"],"pyQName":"MesDpadButtonInfo.BDOWN"},"MesDpadButtonInfo.BUp":{"retType":"MesDpadButtonInfo.BUp","attributes":{"block":"B up","_def":{"parts":[{"kind":"label","text":"B up","style":[]}],"parameters":[]}},"extendsTypes":["MesDpadButtonInfo.BUp","Number"],"pyQName":"MesDpadButtonInfo.BUP"},"MesDpadButtonInfo.CDown":{"retType":"MesDpadButtonInfo.CDown","attributes":{"block":"C down","_def":{"parts":[{"kind":"label","text":"C down","style":[]}],"parameters":[]}},"extendsTypes":["MesDpadButtonInfo.CDown","Number"],"pyQName":"MesDpadButtonInfo.CDOWN"},"MesDpadButtonInfo.CUp":{"retType":"MesDpadButtonInfo.CUp","attributes":{"block":"C up","_def":{"parts":[{"kind":"label","text":"C up","style":[]}],"parameters":[]}},"extendsTypes":["MesDpadButtonInfo.CUp","Number"],"pyQName":"MesDpadButtonInfo.CUP"},"MesDpadButtonInfo.DDown":{"retType":"MesDpadButtonInfo.DDown","attributes":{"block":"D down","_def":{"parts":[{"kind":"label","text":"D down","style":[]}],"parameters":[]}},"extendsTypes":["MesDpadButtonInfo.DDown","Number"],"pyQName":"MesDpadButtonInfo.DDOWN"},"MesDpadButtonInfo.DUp":{"retType":"MesDpadButtonInfo.DUp","attributes":{"block":"D up","_def":{"parts":[{"kind":"label","text":"D up","style":[]}],"parameters":[]}},"extendsTypes":["MesDpadButtonInfo.DUp","Number"],"pyQName":"MesDpadButtonInfo.DUP"},"MesDpadButtonInfo._1Down":{"retType":"MesDpadButtonInfo._1Down","attributes":{"block":"1 down","_def":{"parts":[{"kind":"label","text":"1 down","style":[]}],"parameters":[]}},"extendsTypes":["MesDpadButtonInfo._1Down","Number"],"pyQName":"MesDpadButtonInfo._1_DOWN"},"MesDpadButtonInfo._1Up":{"retType":"MesDpadButtonInfo._1Up","attributes":{"block":"1 up","_def":{"parts":[{"kind":"label","text":"1 up","style":[]}],"parameters":[]}},"extendsTypes":["MesDpadButtonInfo._1Up","Number"],"pyQName":"MesDpadButtonInfo._1_UP"},"MesDpadButtonInfo._2Down":{"retType":"MesDpadButtonInfo._2Down","attributes":{"block":"2 down","_def":{"parts":[{"kind":"label","text":"2 down","style":[]}],"parameters":[]}},"extendsTypes":["MesDpadButtonInfo._2Down","Number"],"pyQName":"MesDpadButtonInfo._2_DOWN"},"MesDpadButtonInfo._2Up":{"retType":"MesDpadButtonInfo._2Up","attributes":{"block":"2 up","_def":{"parts":[{"kind":"label","text":"2 up","style":[]}],"parameters":[]}},"extendsTypes":["MesDpadButtonInfo._2Up","Number"],"pyQName":"MesDpadButtonInfo._2_UP"},"MesDpadButtonInfo._3Down":{"retType":"MesDpadButtonInfo._3Down","attributes":{"block":"3 down","_def":{"parts":[{"kind":"label","text":"3 down","style":[]}],"parameters":[]}},"extendsTypes":["MesDpadButtonInfo._3Down","Number"],"pyQName":"MesDpadButtonInfo._3_DOWN"},"MesDpadButtonInfo._3Up":{"retType":"MesDpadButtonInfo._3Up","attributes":{"block":"3 up","_def":{"parts":[{"kind":"label","text":"3 up","style":[]}],"parameters":[]}},"extendsTypes":["MesDpadButtonInfo._3Up","Number"],"pyQName":"MesDpadButtonInfo._3_UP"},"MesDpadButtonInfo._4Down":{"retType":"MesDpadButtonInfo._4Down","attributes":{"block":"4 down","_def":{"parts":[{"kind":"label","text":"4 down","style":[]}],"parameters":[]}},"extendsTypes":["MesDpadButtonInfo._4Down","Number"],"pyQName":"MesDpadButtonInfo._4_DOWN"},"MesDpadButtonInfo._4Up":{"retType":"MesDpadButtonInfo._4Up","attributes":{"block":"4 up","_def":{"parts":[{"kind":"label","text":"4 up","style":[]}],"parameters":[]}},"extendsTypes":["MesDpadButtonInfo._4Up","Number"],"pyQName":"MesDpadButtonInfo._4_UP"},"input":{"kind":5,"retType":"","attributes":{"color":"#D400D4","weight":111,"icon":"","jsDoc":"Events and data from sensors"}},"EventCreationMode":{"kind":6,"retType":"EventCreationMode","attributes":{"jsDoc":"How to create the event."},"extendsTypes":["EventCreationMode","Number"]},"EventCreationMode.CreateOnly":{"retType":"EventCreationMode.CreateOnly","attributes":{"jsDoc":"MicroBitEvent is initialised, and no further processing takes place."},"extendsTypes":["EventCreationMode.CreateOnly","Number"],"pyQName":"EventCreationMode.CREATE_ONLY"},"EventCreationMode.CreateAndFire":{"retType":"EventCreationMode.CreateAndFire","attributes":{"jsDoc":"MicroBitEvent is initialised, and its event handlers are immediately fired (not suitable for use in interrupts!)."},"extendsTypes":["EventCreationMode.CreateAndFire","Number"],"pyQName":"EventCreationMode.CREATE_AND_FIRE"},"EventBusSource":{"kind":6,"retType":"EventBusSource","extendsTypes":["EventBusSource","Number"]},"EventBusSource.MICROBIT_ID_BUTTON_A":{"retType":"EventBusSource.MICROBIT_ID_BUTTON_A","attributes":{"blockIdentity":"control.eventSourceId"},"extendsTypes":["EventBusSource.MICROBIT_ID_BUTTON_A","Number"]},"EventBusSource.MICROBIT_ID_BUTTON_B":{"retType":"EventBusSource.MICROBIT_ID_BUTTON_B","attributes":{"blockIdentity":"control.eventSourceId"},"extendsTypes":["EventBusSource.MICROBIT_ID_BUTTON_B","Number"]},"EventBusSource.MICROBIT_ID_BUTTON_AB":{"retType":"EventBusSource.MICROBIT_ID_BUTTON_AB","attributes":{"blockIdentity":"control.eventSourceId"},"extendsTypes":["EventBusSource.MICROBIT_ID_BUTTON_AB","Number"]},"EventBusSource.MICROBIT_ID_RADIO":{"retType":"EventBusSource.MICROBIT_ID_RADIO","attributes":{"blockIdentity":"control.eventSourceId"},"extendsTypes":["EventBusSource.MICROBIT_ID_RADIO","Number"]},"EventBusSource.MICROBIT_ID_GESTURE":{"retType":"EventBusSource.MICROBIT_ID_GESTURE","attributes":{"blockIdentity":"control.eventSourceId"},"extendsTypes":["EventBusSource.MICROBIT_ID_GESTURE","Number"]},"EventBusSource.MICROBIT_ID_ACCELEROMETER":{"retType":"EventBusSource.MICROBIT_ID_ACCELEROMETER","attributes":{"blockIdentity":"control.eventSourceId"},"extendsTypes":["EventBusSource.MICROBIT_ID_ACCELEROMETER","Number"]},"EventBusSource.MICROBIT_ID_IO_P0":{"retType":"EventBusSource.MICROBIT_ID_IO_P0","attributes":{"blockIdentity":"control.eventSourceId"},"extendsTypes":["EventBusSource.MICROBIT_ID_IO_P0","Number"]},"EventBusSource.MICROBIT_ID_IO_P1":{"retType":"EventBusSource.MICROBIT_ID_IO_P1","attributes":{"blockIdentity":"control.eventSourceId"},"extendsTypes":["EventBusSource.MICROBIT_ID_IO_P1","Number"]},"EventBusSource.MICROBIT_ID_IO_P2":{"retType":"EventBusSource.MICROBIT_ID_IO_P2","attributes":{"blockIdentity":"control.eventSourceId"},"extendsTypes":["EventBusSource.MICROBIT_ID_IO_P2","Number"]},"EventBusSource.MICROBIT_ID_IO_P3":{"retType":"EventBusSource.MICROBIT_ID_IO_P3","attributes":{"blockIdentity":"control.eventSourceId"},"extendsTypes":["EventBusSource.MICROBIT_ID_IO_P3","Number"]},"EventBusSource.MICROBIT_ID_IO_P4":{"retType":"EventBusSource.MICROBIT_ID_IO_P4","attributes":{"blockIdentity":"control.eventSourceId"},"extendsTypes":["EventBusSource.MICROBIT_ID_IO_P4","Number"]},"EventBusSource.MICROBIT_ID_IO_P5":{"retType":"EventBusSource.MICROBIT_ID_IO_P5","attributes":{"blockIdentity":"control.eventSourceId"},"extendsTypes":["EventBusSource.MICROBIT_ID_IO_P5","Number"]},"EventBusSource.MICROBIT_ID_IO_P6":{"retType":"EventBusSource.MICROBIT_ID_IO_P6","attributes":{"blockIdentity":"control.eventSourceId"},"extendsTypes":["EventBusSource.MICROBIT_ID_IO_P6","Number"]},"EventBusSource.MICROBIT_ID_IO_P7":{"retType":"EventBusSource.MICROBIT_ID_IO_P7","attributes":{"blockIdentity":"control.eventSourceId"},"extendsTypes":["EventBusSource.MICROBIT_ID_IO_P7","Number"]},"EventBusSource.MICROBIT_ID_IO_P8":{"retType":"EventBusSource.MICROBIT_ID_IO_P8","attributes":{"blockIdentity":"control.eventSourceId"},"extendsTypes":["EventBusSource.MICROBIT_ID_IO_P8","Number"]},"EventBusSource.MICROBIT_ID_IO_P9":{"retType":"EventBusSource.MICROBIT_ID_IO_P9","attributes":{"blockIdentity":"control.eventSourceId"},"extendsTypes":["EventBusSource.MICROBIT_ID_IO_P9","Number"]},"EventBusSource.MICROBIT_ID_IO_P10":{"retType":"EventBusSource.MICROBIT_ID_IO_P10","attributes":{"blockIdentity":"control.eventSourceId"},"extendsTypes":["EventBusSource.MICROBIT_ID_IO_P10","Number"]},"EventBusSource.MICROBIT_ID_IO_P11":{"retType":"EventBusSource.MICROBIT_ID_IO_P11","attributes":{"blockIdentity":"control.eventSourceId"},"extendsTypes":["EventBusSource.MICROBIT_ID_IO_P11","Number"]},"EventBusSource.MICROBIT_ID_IO_P12":{"retType":"EventBusSource.MICROBIT_ID_IO_P12","attributes":{"blockIdentity":"control.eventSourceId"},"extendsTypes":["EventBusSource.MICROBIT_ID_IO_P12","Number"]},"EventBusSource.MICROBIT_ID_IO_P13":{"retType":"EventBusSource.MICROBIT_ID_IO_P13","attributes":{"blockIdentity":"control.eventSourceId"},"extendsTypes":["EventBusSource.MICROBIT_ID_IO_P13","Number"]},"EventBusSource.MICROBIT_ID_IO_P14":{"retType":"EventBusSource.MICROBIT_ID_IO_P14","attributes":{"blockIdentity":"control.eventSourceId"},"extendsTypes":["EventBusSource.MICROBIT_ID_IO_P14","Number"]},"EventBusSource.MICROBIT_ID_IO_P15":{"retType":"EventBusSource.MICROBIT_ID_IO_P15","attributes":{"blockIdentity":"control.eventSourceId"},"extendsTypes":["EventBusSource.MICROBIT_ID_IO_P15","Number"]},"EventBusSource.MICROBIT_ID_IO_P16":{"retType":"EventBusSource.MICROBIT_ID_IO_P16","attributes":{"blockIdentity":"control.eventSourceId"},"extendsTypes":["EventBusSource.MICROBIT_ID_IO_P16","Number"]},"EventBusSource.MICROBIT_ID_IO_P19":{"retType":"EventBusSource.MICROBIT_ID_IO_P19","attributes":{"blockIdentity":"control.eventSourceId"},"extendsTypes":["EventBusSource.MICROBIT_ID_IO_P19","Number"]},"EventBusSource.MICROBIT_ID_IO_P20":{"retType":"EventBusSource.MICROBIT_ID_IO_P20","attributes":{"blockIdentity":"control.eventSourceId"},"extendsTypes":["EventBusSource.MICROBIT_ID_IO_P20","Number"]},"EventBusSource.MES_DEVICE_INFO_ID":{"retType":"EventBusSource.MES_DEVICE_INFO_ID","attributes":{"blockIdentity":"control.eventSourceId"},"extendsTypes":["EventBusSource.MES_DEVICE_INFO_ID","Number"]},"EventBusSource.MES_SIGNAL_STRENGTH_ID":{"retType":"EventBusSource.MES_SIGNAL_STRENGTH_ID","attributes":{"blockIdentity":"control.eventSourceId"},"extendsTypes":["EventBusSource.MES_SIGNAL_STRENGTH_ID","Number"]},"EventBusSource.MES_DPAD_CONTROLLER_ID":{"retType":"EventBusSource.MES_DPAD_CONTROLLER_ID","attributes":{"blockIdentity":"control.eventSourceId"},"extendsTypes":["EventBusSource.MES_DPAD_CONTROLLER_ID","Number"]},"EventBusSource.MES_BROADCAST_GENERAL_ID":{"retType":"EventBusSource.MES_BROADCAST_GENERAL_ID","attributes":{"blockIdentity":"control.eventSourceId"},"extendsTypes":["EventBusSource.MES_BROADCAST_GENERAL_ID","Number"]},"EventBusValue":{"kind":6,"retType":"EventBusValue","extendsTypes":["EventBusValue","Number"]},"EventBusValue.MICROBIT_EVT_ANY":{"retType":"EventBusValue.MICROBIT_EVT_ANY","attributes":{"blockIdentity":"control.eventValueId"},"extendsTypes":["EventBusValue.MICROBIT_EVT_ANY","Number"]},"EventBusValue.MICROBIT_BUTTON_EVT_DOWN":{"retType":"EventBusValue.MICROBIT_BUTTON_EVT_DOWN","attributes":{"blockIdentity":"control.eventValueId"},"extendsTypes":["EventBusValue.MICROBIT_BUTTON_EVT_DOWN","Number"]},"EventBusValue.MICROBIT_BUTTON_EVT_UP":{"retType":"EventBusValue.MICROBIT_BUTTON_EVT_UP","attributes":{"blockIdentity":"control.eventValueId"},"extendsTypes":["EventBusValue.MICROBIT_BUTTON_EVT_UP","Number"]},"EventBusValue.MICROBIT_BUTTON_EVT_CLICK":{"retType":"EventBusValue.MICROBIT_BUTTON_EVT_CLICK","attributes":{"blockIdentity":"control.eventValueId"},"extendsTypes":["EventBusValue.MICROBIT_BUTTON_EVT_CLICK","Number"]},"EventBusValue.MICROBIT_RADIO_EVT_DATAGRAM":{"retType":"EventBusValue.MICROBIT_BUTTON_EVT_DOWN","attributes":{"blockIdentity":"control.eventValueId"},"extendsTypes":["EventBusValue.MICROBIT_RADIO_EVT_DATAGRAM","Number"]},"EventBusValue.MICROBIT_ACCELEROMETER_EVT_DATA_UPDATE":{"retType":"EventBusValue.MICROBIT_BUTTON_EVT_DOWN","attributes":{"blockIdentity":"control.eventValueId"},"extendsTypes":["EventBusValue.MICROBIT_ACCELEROMETER_EVT_DATA_UPDATE","Number"]},"EventBusValue.MICROBIT_PIN_EVT_RISE":{"retType":"EventBusValue.MICROBIT_BUTTON_EVT_UP","attributes":{"blockIdentity":"control.eventValueId"},"extendsTypes":["EventBusValue.MICROBIT_PIN_EVT_RISE","Number"]},"EventBusValue.MICROBIT_PIN_EVT_FALL":{"retType":"EventBusValue.MICROBIT_BUTTON_EVT_CLICK","attributes":{"blockIdentity":"control.eventValueId"},"extendsTypes":["EventBusValue.MICROBIT_PIN_EVT_FALL","Number"]},"EventBusValue.MICROBIT_PIN_EVT_PULSE_HI":{"retType":"EventBusValue.MICROBIT_PIN_EVT_PULSE_HI","attributes":{"blockIdentity":"control.eventValueId"},"extendsTypes":["EventBusValue.MICROBIT_PIN_EVT_PULSE_HI","Number"]},"EventBusValue.MICROBIT_PIN_EVT_PULSE_LO":{"retType":"EventBusValue.MICROBIT_PIN_EVT_PULSE_LO","attributes":{"blockIdentity":"control.eventValueId"},"extendsTypes":["EventBusValue.MICROBIT_PIN_EVT_PULSE_LO","Number"]},"EventBusValue.MES_ALERT_EVT_ALARM1":{"retType":"EventBusValue.MES_ALERT_EVT_ALARM1","attributes":{"blockIdentity":"control.eventValueId"},"extendsTypes":["EventBusValue.MES_ALERT_EVT_ALARM1","Number"]},"EventBusValue.MES_ALERT_EVT_ALARM2":{"retType":"EventBusValue.MES_ALERT_EVT_ALARM2","attributes":{"blockIdentity":"control.eventValueId"},"extendsTypes":["EventBusValue.MES_ALERT_EVT_ALARM2","Number"]},"EventBusValue.MES_ALERT_EVT_ALARM3":{"retType":"EventBusValue.MES_ALERT_EVT_ALARM3","attributes":{"blockIdentity":"control.eventValueId"},"extendsTypes":["EventBusValue.MES_ALERT_EVT_ALARM3","Number"]},"EventBusValue.MES_ALERT_EVT_ALARM4":{"retType":"EventBusValue.MES_ALERT_EVT_ALARM4","attributes":{"blockIdentity":"control.eventValueId"},"extendsTypes":["EventBusValue.MES_ALERT_EVT_ALARM4","Number"]},"EventBusValue.MES_ALERT_EVT_ALARM5":{"retType":"EventBusValue.MES_ALERT_EVT_ALARM5","attributes":{"blockIdentity":"control.eventValueId"},"extendsTypes":["EventBusValue.MES_ALERT_EVT_ALARM5","Number"]},"EventBusValue.MES_ALERT_EVT_ALARM6":{"retType":"EventBusValue.MES_ALERT_EVT_ALARM6","attributes":{"blockIdentity":"control.eventValueId"},"extendsTypes":["EventBusValue.MES_ALERT_EVT_ALARM6","Number"]},"EventBusValue.MES_ALERT_EVT_DISPLAY_TOAST":{"retType":"EventBusValue.MICROBIT_BUTTON_EVT_DOWN","attributes":{"blockIdentity":"control.eventValueId"},"extendsTypes":["EventBusValue.MES_ALERT_EVT_DISPLAY_TOAST","Number"]},"EventBusValue.MES_ALERT_EVT_FIND_MY_PHONE":{"retType":"EventBusValue.MICROBIT_PIN_EVT_PULSE_LO","attributes":{"blockIdentity":"control.eventValueId"},"extendsTypes":["EventBusValue.MES_ALERT_EVT_FIND_MY_PHONE","Number"]},"EventBusValue.MES_ALERT_EVT_PLAY_RINGTONE":{"retType":"EventBusValue.MICROBIT_PIN_EVT_PULSE_HI","attributes":{"blockIdentity":"control.eventValueId"},"extendsTypes":["EventBusValue.MES_ALERT_EVT_PLAY_RINGTONE","Number"]},"EventBusValue.MES_ALERT_EVT_PLAY_SOUND":{"retType":"EventBusValue.MICROBIT_BUTTON_EVT_CLICK","attributes":{"blockIdentity":"control.eventValueId"},"extendsTypes":["EventBusValue.MES_ALERT_EVT_PLAY_SOUND","Number"]},"EventBusValue.MES_ALERT_EVT_VIBRATE":{"retType":"EventBusValue.MICROBIT_BUTTON_EVT_UP","attributes":{"blockIdentity":"control.eventValueId"},"extendsTypes":["EventBusValue.MES_ALERT_EVT_VIBRATE","Number"]},"EventBusValue.MES_CAMERA_EVT_LAUNCH_PHOTO_MODE":{"retType":"EventBusValue.MICROBIT_BUTTON_EVT_DOWN","attributes":{"blockIdentity":"control.eventValueId"},"extendsTypes":["EventBusValue.MES_CAMERA_EVT_LAUNCH_PHOTO_MODE","Number"]},"EventBusValue.MES_CAMERA_EVT_LAUNCH_VIDEO_MODE":{"retType":"EventBusValue.MICROBIT_BUTTON_EVT_UP","attributes":{"blockIdentity":"control.eventValueId"},"extendsTypes":["EventBusValue.MES_CAMERA_EVT_LAUNCH_VIDEO_MODE","Number"]},"EventBusValue.MES_CAMERA_EVT_START_VIDEO_CAPTURE":{"retType":"EventBusValue.MICROBIT_PIN_EVT_PULSE_HI","attributes":{"blockIdentity":"control.eventValueId"},"extendsTypes":["EventBusValue.MES_CAMERA_EVT_START_VIDEO_CAPTURE","Number"]},"EventBusValue.MES_CAMERA_EVT_STOP_PHOTO_MODE":{"retType":"EventBusValue.MES_ALERT_EVT_ALARM1","attributes":{"blockIdentity":"control.eventValueId"},"extendsTypes":["EventBusValue.MES_CAMERA_EVT_STOP_PHOTO_MODE","Number"]},"EventBusValue.MES_CAMERA_EVT_STOP_VIDEO_CAPTURE":{"retType":"EventBusValue.MICROBIT_PIN_EVT_PULSE_LO","attributes":{"blockIdentity":"control.eventValueId"},"extendsTypes":["EventBusValue.MES_CAMERA_EVT_STOP_VIDEO_CAPTURE","Number"]},"EventBusValue.MES_CAMERA_EVT_STOP_VIDEO_MODE":{"retType":"EventBusValue.MES_ALERT_EVT_ALARM2","attributes":{"blockIdentity":"control.eventValueId"},"extendsTypes":["EventBusValue.MES_CAMERA_EVT_STOP_VIDEO_MODE","Number"]},"EventBusValue.MES_CAMERA_EVT_TAKE_PHOTO":{"retType":"EventBusValue.MICROBIT_BUTTON_EVT_CLICK","attributes":{"blockIdentity":"control.eventValueId"},"extendsTypes":["EventBusValue.MES_CAMERA_EVT_TAKE_PHOTO","Number"]},"EventBusValue.MES_CAMERA_EVT_TOGGLE_FRONT_REAR":{"retType":"EventBusValue.MES_ALERT_EVT_ALARM3","attributes":{"blockIdentity":"control.eventValueId"},"extendsTypes":["EventBusValue.MES_CAMERA_EVT_TOGGLE_FRONT_REAR","Number"]},"EventBusValue.MES_DEVICE_DISPLAY_OFF":{"retType":"EventBusValue.MICROBIT_PIN_EVT_PULSE_LO","attributes":{"blockIdentity":"control.eventValueId"},"extendsTypes":["EventBusValue.MES_DEVICE_DISPLAY_OFF","Number"]},"EventBusValue.MES_DEVICE_DISPLAY_ON":{"retType":"EventBusValue.MES_ALERT_EVT_ALARM1","attributes":{"blockIdentity":"control.eventValueId"},"extendsTypes":["EventBusValue.MES_DEVICE_DISPLAY_ON","Number"]},"EventBusValue.MES_DEVICE_GESTURE_DEVICE_SHAKEN":{"retType":"EventBusValue.MICROBIT_PIN_EVT_PULSE_HI","attributes":{"blockIdentity":"control.eventValueId"},"extendsTypes":["EventBusValue.MES_DEVICE_GESTURE_DEVICE_SHAKEN","Number"]},"EventBusValue.MES_DEVICE_INCOMING_CALL":{"retType":"EventBusValue.MES_ALERT_EVT_ALARM2","attributes":{"blockIdentity":"control.eventValueId"},"extendsTypes":["EventBusValue.MES_DEVICE_INCOMING_CALL","Number"]},"EventBusValue.MES_DEVICE_INCOMING_MESSAGE":{"retType":"EventBusValue.MES_ALERT_EVT_ALARM3","attributes":{"blockIdentity":"control.eventValueId"},"extendsTypes":["EventBusValue.MES_DEVICE_INCOMING_MESSAGE","Number"]},"EventBusValue.MES_DEVICE_ORIENTATION_LANDSCAPE":{"retType":"EventBusValue.MICROBIT_BUTTON_EVT_DOWN","attributes":{"blockIdentity":"control.eventValueId"},"extendsTypes":["EventBusValue.MES_DEVICE_ORIENTATION_LANDSCAPE","Number"]},"EventBusValue.MES_DEVICE_ORIENTATION_PORTRAIT":{"retType":"EventBusValue.MICROBIT_BUTTON_EVT_UP","attributes":{"blockIdentity":"control.eventValueId"},"extendsTypes":["EventBusValue.MES_DEVICE_ORIENTATION_PORTRAIT","Number"]},"EventBusValue.MES_DPAD_BUTTON_1_DOWN":{"retType":"EventBusValue.MES_ALERT_EVT_ALARM4","attributes":{"blockIdentity":"control.eventValueId"},"extendsTypes":["EventBusValue.MES_DPAD_BUTTON_1_DOWN","Number"]},"EventBusValue.MES_DPAD_BUTTON_1_UP":{"retType":"EventBusValue.MES_ALERT_EVT_ALARM5","attributes":{"blockIdentity":"control.eventValueId"},"extendsTypes":["EventBusValue.MES_DPAD_BUTTON_1_UP","Number"]},"EventBusValue.MES_DPAD_BUTTON_2_DOWN":{"retType":"EventBusValue.MES_ALERT_EVT_ALARM6","attributes":{"blockIdentity":"control.eventValueId"},"extendsTypes":["EventBusValue.MES_DPAD_BUTTON_2_DOWN","Number"]},"EventBusValue.MES_DPAD_BUTTON_2_UP":{"retType":"EventBusValue.MES_DPAD_BUTTON_2_UP","attributes":{"blockIdentity":"control.eventValueId"},"extendsTypes":["EventBusValue.MES_DPAD_BUTTON_2_UP","Number"]},"EventBusValue.MES_DPAD_BUTTON_3_DOWN":{"retType":"EventBusValue.MES_DPAD_BUTTON_3_DOWN","attributes":{"blockIdentity":"control.eventValueId"},"extendsTypes":["EventBusValue.MES_DPAD_BUTTON_3_DOWN","Number"]},"EventBusValue.MES_DPAD_BUTTON_3_UP":{"retType":"EventBusValue.MES_DPAD_BUTTON_3_UP","attributes":{"blockIdentity":"control.eventValueId"},"extendsTypes":["EventBusValue.MES_DPAD_BUTTON_3_UP","Number"]},"EventBusValue.MES_DPAD_BUTTON_4_DOWN":{"retType":"EventBusValue.MES_DPAD_BUTTON_4_DOWN","attributes":{"blockIdentity":"control.eventValueId"},"extendsTypes":["EventBusValue.MES_DPAD_BUTTON_4_DOWN","Number"]},"EventBusValue.MES_DPAD_BUTTON_4_UP":{"retType":"EventBusValue.MES_DPAD_BUTTON_4_UP","attributes":{"blockIdentity":"control.eventValueId"},"extendsTypes":["EventBusValue.MES_DPAD_BUTTON_4_UP","Number"]},"EventBusValue.MES_DPAD_BUTTON_A_DOWN":{"retType":"EventBusValue.MICROBIT_BUTTON_EVT_DOWN","attributes":{"blockIdentity":"control.eventValueId"},"extendsTypes":["EventBusValue.MES_DPAD_BUTTON_A_DOWN","Number"]},"EventBusValue.MES_DPAD_BUTTON_A_UP":{"retType":"EventBusValue.MICROBIT_BUTTON_EVT_UP","attributes":{"blockIdentity":"control.eventValueId"},"extendsTypes":["EventBusValue.MES_DPAD_BUTTON_A_UP","Number"]},"EventBusValue.MES_DPAD_BUTTON_B_DOWN":{"retType":"EventBusValue.MICROBIT_BUTTON_EVT_CLICK","attributes":{"blockIdentity":"control.eventValueId"},"extendsTypes":["EventBusValue.MES_DPAD_BUTTON_B_DOWN","Number"]},"EventBusValue.MES_DPAD_BUTTON_B_UP":{"retType":"EventBusValue.MICROBIT_PIN_EVT_PULSE_HI","attributes":{"blockIdentity":"control.eventValueId"},"extendsTypes":["EventBusValue.MES_DPAD_BUTTON_B_UP","Number"]},"EventBusValue.MES_DPAD_BUTTON_C_DOWN":{"retType":"EventBusValue.MICROBIT_PIN_EVT_PULSE_LO","attributes":{"blockIdentity":"control.eventValueId"},"extendsTypes":["EventBusValue.MES_DPAD_BUTTON_C_DOWN","Number"]},"EventBusValue.MES_DPAD_BUTTON_C_UP":{"retType":"EventBusValue.MES_ALERT_EVT_ALARM1","attributes":{"blockIdentity":"control.eventValueId"},"extendsTypes":["EventBusValue.MES_DPAD_BUTTON_C_UP","Number"]},"EventBusValue.MES_DPAD_BUTTON_D_DOWN":{"retType":"EventBusValue.MES_ALERT_EVT_ALARM2","attributes":{"blockIdentity":"control.eventValueId"},"extendsTypes":["EventBusValue.MES_DPAD_BUTTON_D_DOWN","Number"]},"EventBusValue.MES_DPAD_BUTTON_D_UP":{"retType":"EventBusValue.MES_ALERT_EVT_ALARM3","attributes":{"blockIdentity":"control.eventValueId"},"extendsTypes":["EventBusValue.MES_DPAD_BUTTON_D_UP","Number"]},"EventBusValue.MES_REMOTE_CONTROL_EVT_FORWARD":{"retType":"EventBusValue.MES_ALERT_EVT_ALARM1","attributes":{"blockIdentity":"control.eventValueId"},"extendsTypes":["EventBusValue.MES_REMOTE_CONTROL_EVT_FORWARD","Number"]},"EventBusValue.MES_REMOTE_CONTROL_EVT_NEXTTRACK":{"retType":"EventBusValue.MICROBIT_PIN_EVT_PULSE_HI","attributes":{"blockIdentity":"control.eventValueId"},"extendsTypes":["EventBusValue.MES_REMOTE_CONTROL_EVT_NEXTTRACK","Number"]},"EventBusValue.MES_REMOTE_CONTROL_EVT_PAUSE":{"retType":"EventBusValue.MICROBIT_BUTTON_EVT_UP","attributes":{"blockIdentity":"control.eventValueId"},"extendsTypes":["EventBusValue.MES_REMOTE_CONTROL_EVT_PAUSE","Number"]},"EventBusValue.MES_REMOTE_CONTROL_EVT_PLAY":{"retType":"EventBusValue.MICROBIT_BUTTON_EVT_DOWN","attributes":{"blockIdentity":"control.eventValueId"},"extendsTypes":["EventBusValue.MES_REMOTE_CONTROL_EVT_PLAY","Number"]},"EventBusValue.MES_REMOTE_CONTROL_EVT_PREVTRACK":{"retType":"EventBusValue.MICROBIT_PIN_EVT_PULSE_LO","attributes":{"blockIdentity":"control.eventValueId"},"extendsTypes":["EventBusValue.MES_REMOTE_CONTROL_EVT_PREVTRACK","Number"]},"EventBusValue.MES_REMOTE_CONTROL_EVT_REWIND":{"retType":"EventBusValue.MES_ALERT_EVT_ALARM2","attributes":{"blockIdentity":"control.eventValueId"},"extendsTypes":["EventBusValue.MES_REMOTE_CONTROL_EVT_REWIND","Number"]},"EventBusValue.MES_REMOTE_CONTROL_EVT_STOP":{"retType":"EventBusValue.MICROBIT_BUTTON_EVT_CLICK","attributes":{"blockIdentity":"control.eventValueId"},"extendsTypes":["EventBusValue.MES_REMOTE_CONTROL_EVT_STOP","Number"]},"EventBusValue.MES_REMOTE_CONTROL_EVT_VOLUMEDOWN":{"retType":"EventBusValue.MES_ALERT_EVT_ALARM4","attributes":{"blockIdentity":"control.eventValueId"},"extendsTypes":["EventBusValue.MES_REMOTE_CONTROL_EVT_VOLUMEDOWN","Number"]},"EventBusValue.MES_REMOTE_CONTROL_EVT_VOLUMEUP":{"retType":"EventBusValue.MES_ALERT_EVT_ALARM3","attributes":{"blockIdentity":"control.eventValueId"},"extendsTypes":["EventBusValue.MES_REMOTE_CONTROL_EVT_VOLUMEUP","Number"]},"EventFlags":{"kind":6,"retType":"EventFlags","extendsTypes":["EventFlags","Number"]},"EventFlags.QueueIfBusy":{"retType":"EventFlags.QueueIfBusy","extendsTypes":["EventFlags.QueueIfBusy","Number"],"pyQName":"EventFlags.QUEUE_IF_BUSY"},"EventFlags.DropIfBusy":{"retType":"EventFlags.DropIfBusy","extendsTypes":["EventFlags.DropIfBusy","Number"],"pyQName":"EventFlags.DROP_IF_BUSY"},"EventFlags.Reentrant":{"retType":"EventFlags.Reentrant","extendsTypes":["EventFlags.Reentrant","Number"],"pyQName":"EventFlags.REENTRANT"},"control":{"kind":5,"retType":"","attributes":{"weight":1,"color":"#333333","advanced":true,"icon":"","jsDoc":"Runtime and event utilities."}},"DisplayMode":{"kind":6,"retType":"DisplayMode","extendsTypes":["DisplayMode","Number"]},"DisplayMode.BlackAndWhite":{"retType":"DisplayMode.BlackAndWhite","attributes":{"block":"black and white","_def":{"parts":[{"kind":"label","text":"black and white","style":[]}],"parameters":[]}},"extendsTypes":["DisplayMode.BlackAndWhite","Number"],"pyQName":"DisplayMode.BLACK_AND_WHITE"},"DisplayMode.BackAndWhite":{"retType":"DisplayMode.BlackAndWhite","attributes":{"blockHidden":true},"extendsTypes":["DisplayMode.BackAndWhite","Number"],"pyQName":"DisplayMode.BACK_AND_WHITE"},"DisplayMode.Greyscale":{"retType":"DisplayMode.Greyscale","attributes":{"block":"greyscale","_def":{"parts":[{"kind":"label","text":"greyscale","style":[]}],"parameters":[]}},"extendsTypes":["DisplayMode.Greyscale","Number"],"pyQName":"DisplayMode.GREYSCALE"},"led":{"kind":5,"retType":"","attributes":{"color":"#5C2D91","weight":101,"icon":"","jsDoc":"Control of the LED screen."}},"DigitalPin":{"kind":6,"retType":"DigitalPin","extendsTypes":["DigitalPin","Number"]},"DigitalPin.P0":{"retType":"DigitalPin.P0","attributes":{"blockIdentity":"pins._digitalPin"},"extendsTypes":["DigitalPin.P0","Number"]},"DigitalPin.P1":{"retType":"DigitalPin.P1","attributes":{"blockIdentity":"pins._digitalPin"},"extendsTypes":["DigitalPin.P1","Number"]},"DigitalPin.P2":{"retType":"DigitalPin.P2","attributes":{"blockIdentity":"pins._digitalPin"},"extendsTypes":["DigitalPin.P2","Number"]},"DigitalPin.P3":{"retType":"DigitalPin.P3","attributes":{"blockIdentity":"pins._digitalPin"},"extendsTypes":["DigitalPin.P3","Number"]},"DigitalPin.P4":{"retType":"DigitalPin.P4","attributes":{"blockIdentity":"pins._digitalPin"},"extendsTypes":["DigitalPin.P4","Number"]},"DigitalPin.P5":{"retType":"DigitalPin.P5","attributes":{"blockIdentity":"pins._digitalPin"},"extendsTypes":["DigitalPin.P5","Number"]},"DigitalPin.P6":{"retType":"DigitalPin.P6","attributes":{"blockIdentity":"pins._digitalPin"},"extendsTypes":["DigitalPin.P6","Number"]},"DigitalPin.P7":{"retType":"DigitalPin.P7","attributes":{"blockIdentity":"pins._digitalPin"},"extendsTypes":["DigitalPin.P7","Number"]},"DigitalPin.P8":{"retType":"DigitalPin.P8","attributes":{"blockIdentity":"pins._digitalPin"},"extendsTypes":["DigitalPin.P8","Number"]},"DigitalPin.P9":{"retType":"DigitalPin.P9","attributes":{"blockIdentity":"pins._digitalPin"},"extendsTypes":["DigitalPin.P9","Number"]},"DigitalPin.P10":{"retType":"DigitalPin.P10","attributes":{"blockIdentity":"pins._digitalPin"},"extendsTypes":["DigitalPin.P10","Number"]},"DigitalPin.P11":{"retType":"DigitalPin.P11","attributes":{"blockIdentity":"pins._digitalPin"},"extendsTypes":["DigitalPin.P11","Number"]},"DigitalPin.P12":{"retType":"DigitalPin.P12","attributes":{"blockIdentity":"pins._digitalPin"},"extendsTypes":["DigitalPin.P12","Number"]},"DigitalPin.P13":{"retType":"DigitalPin.P13","attributes":{"blockIdentity":"pins._digitalPin"},"extendsTypes":["DigitalPin.P13","Number"]},"DigitalPin.P14":{"retType":"DigitalPin.P14","attributes":{"blockIdentity":"pins._digitalPin"},"extendsTypes":["DigitalPin.P14","Number"]},"DigitalPin.P15":{"retType":"DigitalPin.P15","attributes":{"blockIdentity":"pins._digitalPin"},"extendsTypes":["DigitalPin.P15","Number"]},"DigitalPin.P16":{"retType":"DigitalPin.P16","attributes":{"blockIdentity":"pins._digitalPin"},"extendsTypes":["DigitalPin.P16","Number"]},"DigitalPin.P19":{"retType":"DigitalPin.P19","attributes":{"blockIdentity":"pins._digitalPin","blockHidden":true},"extendsTypes":["DigitalPin.P19","Number"]},"DigitalPin.P20":{"retType":"DigitalPin.P20","attributes":{"blockIdentity":"pins._digitalPin","blockHidden":true},"extendsTypes":["DigitalPin.P20","Number"]},"AnalogPin":{"kind":6,"retType":"AnalogPin","extendsTypes":["AnalogPin","Number"]},"AnalogPin.P0":{"retType":"AnalogPin.P0","attributes":{"blockIdentity":"pins._analogPin"},"extendsTypes":["AnalogPin.P0","Number"]},"AnalogPin.P1":{"retType":"AnalogPin.P1","attributes":{"blockIdentity":"pins._analogPin"},"extendsTypes":["AnalogPin.P1","Number"]},"AnalogPin.P2":{"retType":"AnalogPin.P2","attributes":{"blockIdentity":"pins._analogPin"},"extendsTypes":["AnalogPin.P2","Number"]},"AnalogPin.P3":{"retType":"AnalogPin.P3","attributes":{"blockIdentity":"pins._analogPin"},"extendsTypes":["AnalogPin.P3","Number"]},"AnalogPin.P4":{"retType":"AnalogPin.P4","attributes":{"blockIdentity":"pins._analogPin"},"extendsTypes":["AnalogPin.P4","Number"]},"AnalogPin.P5":{"retType":"AnalogPin.P5","attributes":{"blockIdentity":"pins._analogPin"},"extendsTypes":["AnalogPin.P5","Number"]},"AnalogPin.P6":{"retType":"AnalogPin.P6","attributes":{"blockIdentity":"pins._analogPin"},"extendsTypes":["AnalogPin.P6","Number"]},"AnalogPin.P7":{"retType":"AnalogPin.P7","attributes":{"blockIdentity":"pins._analogPin"},"extendsTypes":["AnalogPin.P7","Number"]},"AnalogPin.P8":{"retType":"AnalogPin.P8","attributes":{"blockIdentity":"pins._analogPin"},"extendsTypes":["AnalogPin.P8","Number"]},"AnalogPin.P9":{"retType":"AnalogPin.P9","attributes":{"blockIdentity":"pins._analogPin"},"extendsTypes":["AnalogPin.P9","Number"]},"AnalogPin.P10":{"retType":"AnalogPin.P10","attributes":{"blockIdentity":"pins._analogPin"},"extendsTypes":["AnalogPin.P10","Number"]},"AnalogPin.P11":{"retType":"AnalogPin.P11","attributes":{"blockIdentity":"pins._analogPin"},"extendsTypes":["AnalogPin.P11","Number"]},"AnalogPin.P12":{"retType":"AnalogPin.P12","attributes":{"blockIdentity":"pins._analogPin"},"extendsTypes":["AnalogPin.P12","Number"]},"AnalogPin.P13":{"retType":"AnalogPin.P13","attributes":{"blockIdentity":"pins._analogPin"},"extendsTypes":["AnalogPin.P13","Number"]},"AnalogPin.P14":{"retType":"AnalogPin.P14","attributes":{"blockIdentity":"pins._analogPin"},"extendsTypes":["AnalogPin.P14","Number"]},"AnalogPin.P15":{"retType":"AnalogPin.P15","attributes":{"blockIdentity":"pins._analogPin"},"extendsTypes":["AnalogPin.P15","Number"]},"AnalogPin.P16":{"retType":"AnalogPin.P16","attributes":{"blockIdentity":"pins._analogPin"},"extendsTypes":["AnalogPin.P16","Number"]},"AnalogPin.P19":{"retType":"AnalogPin.P19","attributes":{"blockIdentity":"pins._analogPin","blockHidden":true},"extendsTypes":["AnalogPin.P19","Number"]},"AnalogPin.P20":{"retType":"AnalogPin.P20","attributes":{"blockIdentity":"pins._analogPin","blockHidden":true},"extendsTypes":["AnalogPin.P20","Number"]},"PulseValue":{"kind":6,"retType":"PulseValue","extendsTypes":["PulseValue","Number"]},"PulseValue.High":{"retType":"PulseValue.High","attributes":{"block":"high","_def":{"parts":[{"kind":"label","text":"high","style":[]}],"parameters":[]}},"extendsTypes":["PulseValue.High","Number"],"pyQName":"PulseValue.HIGH"},"PulseValue.Low":{"retType":"PulseValue.Low","attributes":{"block":"low","_def":{"parts":[{"kind":"label","text":"low","style":[]}],"parameters":[]}},"extendsTypes":["PulseValue.Low","Number"],"pyQName":"PulseValue.LOW"},"PinPullMode":{"kind":6,"retType":"PinPullMode","extendsTypes":["PinPullMode","Number"]},"PinPullMode.PullDown":{"retType":"PinPullMode.PullDown","attributes":{"block":"down","_def":{"parts":[{"kind":"label","text":"down","style":[]}],"parameters":[]}},"extendsTypes":["PinPullMode.PullDown","Number"],"pyQName":"PinPullMode.PULL_DOWN"},"PinPullMode.PullUp":{"retType":"PinPullMode.PullUp","attributes":{"block":"up","_def":{"parts":[{"kind":"label","text":"up","style":[]}],"parameters":[]}},"extendsTypes":["PinPullMode.PullUp","Number"],"pyQName":"PinPullMode.PULL_UP"},"PinPullMode.PullNone":{"retType":"PinPullMode.PullNone","attributes":{"block":"none","_def":{"parts":[{"kind":"label","text":"none","style":[]}],"parameters":[]}},"extendsTypes":["PinPullMode.PullNone","Number"],"pyQName":"PinPullMode.PULL_NONE"},"PinEventType":{"kind":6,"retType":"PinEventType","extendsTypes":["PinEventType","Number"]},"PinEventType.Edge":{"retType":"PinEventType.Edge","attributes":{"block":"edge","_def":{"parts":[{"kind":"label","text":"edge","style":[]}],"parameters":[]}},"extendsTypes":["PinEventType.Edge","Number"],"pyQName":"PinEventType.EDGE"},"PinEventType.Pulse":{"retType":"PinEventType.Pulse","attributes":{"block":"pulse","_def":{"parts":[{"kind":"label","text":"pulse","style":[]}],"parameters":[]}},"extendsTypes":["PinEventType.Pulse","Number"],"pyQName":"PinEventType.PULSE"},"PinEventType.Touch":{"retType":"PinEventType.Touch","attributes":{"block":"touch","_def":{"parts":[{"kind":"label","text":"touch","style":[]}],"parameters":[]}},"extendsTypes":["PinEventType.Touch","Number"],"pyQName":"PinEventType.TOUCH"},"PinEventType.None":{"retType":"PinEventType.None","attributes":{"block":"none","_def":{"parts":[{"kind":"label","text":"none","style":[]}],"parameters":[]}},"extendsTypes":["PinEventType.None","Number"],"pyQName":"PinEventType.NONE"},"SerialPin":{"kind":6,"retType":"SerialPin","extendsTypes":["SerialPin","Number"]},"SerialPin.P0":{"retType":"SerialPin.P0","extendsTypes":["SerialPin.P0","Number"]},"SerialPin.P1":{"retType":"SerialPin.P1","extendsTypes":["SerialPin.P1","Number"]},"SerialPin.P2":{"retType":"SerialPin.P2","extendsTypes":["SerialPin.P2","Number"]},"SerialPin.P8":{"retType":"SerialPin.P8","extendsTypes":["SerialPin.P8","Number"]},"SerialPin.P12":{"retType":"SerialPin.P12","extendsTypes":["SerialPin.P12","Number"]},"SerialPin.P13":{"retType":"SerialPin.P13","extendsTypes":["SerialPin.P13","Number"]},"SerialPin.P14":{"retType":"SerialPin.P14","extendsTypes":["SerialPin.P14","Number"]},"SerialPin.P15":{"retType":"SerialPin.P15","extendsTypes":["SerialPin.P15","Number"]},"SerialPin.P16":{"retType":"SerialPin.P16","extendsTypes":["SerialPin.P16","Number"]},"SerialPin.USB_TX":{"retType":"SerialPin.USB_TX","extendsTypes":["SerialPin.USB_TX","Number"]},"SerialPin.USB_RX":{"retType":"SerialPin.USB_RX","extendsTypes":["SerialPin.USB_RX","Number"]},"BaudRate":{"kind":6,"retType":"BaudRate","extendsTypes":["BaudRate","Number"]},"BaudRate.BaudRate115200":{"retType":"BaudRate.BaudRate115200","attributes":{"block":"115200","_def":{"parts":[{"kind":"label","text":"115200","style":[]}],"parameters":[]}},"extendsTypes":["BaudRate.BaudRate115200","Number"],"pyQName":"BaudRate.BAUD_RATE115200"},"BaudRate.BaudRate57600":{"retType":"BaudRate.BaudRate57600","attributes":{"block":"57600","_def":{"parts":[{"kind":"label","text":"57600","style":[]}],"parameters":[]}},"extendsTypes":["BaudRate.BaudRate57600","Number"],"pyQName":"BaudRate.BAUD_RATE57600"},"BaudRate.BaudRate38400":{"retType":"BaudRate.BaudRate38400","attributes":{"block":"38400","_def":{"parts":[{"kind":"label","text":"38400","style":[]}],"parameters":[]}},"extendsTypes":["BaudRate.BaudRate38400","Number"],"pyQName":"BaudRate.BAUD_RATE38400"},"BaudRate.BaudRate31250":{"retType":"BaudRate.BaudRate31250","attributes":{"block":"31250","_def":{"parts":[{"kind":"label","text":"31250","style":[]}],"parameters":[]}},"extendsTypes":["BaudRate.BaudRate31250","Number"],"pyQName":"BaudRate.BAUD_RATE31250"},"BaudRate.BaudRate28800":{"retType":"BaudRate.BaudRate28800","attributes":{"block":"28800","_def":{"parts":[{"kind":"label","text":"28800","style":[]}],"parameters":[]}},"extendsTypes":["BaudRate.BaudRate28800","Number"],"pyQName":"BaudRate.BAUD_RATE28800"},"BaudRate.BaudRate19200":{"retType":"BaudRate.BaudRate19200","attributes":{"block":"19200","_def":{"parts":[{"kind":"label","text":"19200","style":[]}],"parameters":[]}},"extendsTypes":["BaudRate.BaudRate19200","Number"],"pyQName":"BaudRate.BAUD_RATE19200"},"BaudRate.BaudRate14400":{"retType":"BaudRate.BaudRate14400","attributes":{"block":"14400","_def":{"parts":[{"kind":"label","text":"14400","style":[]}],"parameters":[]}},"extendsTypes":["BaudRate.BaudRate14400","Number"],"pyQName":"BaudRate.BAUD_RATE14400"},"BaudRate.BaudRate9600":{"retType":"BaudRate.BaudRate9600","attributes":{"block":"9600","_def":{"parts":[{"kind":"label","text":"9600","style":[]}],"parameters":[]}},"extendsTypes":["BaudRate.BaudRate9600","Number"],"pyQName":"BaudRate.BAUD_RATE9600"},"BaudRate.BaudRate4800":{"retType":"BaudRate.BaudRate4800","attributes":{"block":"4800","_def":{"parts":[{"kind":"label","text":"4800","style":[]}],"parameters":[]}},"extendsTypes":["BaudRate.BaudRate4800","Number"],"pyQName":"BaudRate.BAUD_RATE4800"},"BaudRate.BaudRate2400":{"retType":"BaudRate.BaudRate2400","attributes":{"block":"2400","_def":{"parts":[{"kind":"label","text":"2400","style":[]}],"parameters":[]}},"extendsTypes":["BaudRate.BaudRate2400","Number"],"pyQName":"BaudRate.BAUD_RATE2400"},"BaudRate.BaudRate1200":{"retType":"BaudRate.BaudRate1200","attributes":{"block":"1200","_def":{"parts":[{"kind":"label","text":"1200","style":[]}],"parameters":[]}},"extendsTypes":["BaudRate.BaudRate1200","Number"],"pyQName":"BaudRate.BAUD_RATE1200"},"serial":{"kind":5,"retType":"","attributes":{"weight":2,"color":"#002050","icon":"","advanced":true,"jsDoc":"Reading and writing data over a serial connection."}},"TouchButtonEvent":{"kind":6,"retType":"TouchButtonEvent","attributes":{"jsDoc":"An action on a touch button"},"extendsTypes":["TouchButtonEvent","Number"]},"TouchButtonEvent.Pressed":{"retType":"TouchButtonEvent.Pressed","attributes":{"block":"pressed","_def":{"parts":[{"kind":"label","text":"pressed","style":[]}],"parameters":[]}},"extendsTypes":["TouchButtonEvent.Pressed","Number"],"pyQName":"TouchButtonEvent.PRESSED"},"TouchButtonEvent.Touched":{"retType":"TouchButtonEvent.Touched","attributes":{"block":"touched","_def":{"parts":[{"kind":"label","text":"touched","style":[]}],"parameters":[]}},"extendsTypes":["TouchButtonEvent.Touched","Number"],"pyQName":"TouchButtonEvent.TOUCHED"},"TouchButtonEvent.Released":{"retType":"TouchButtonEvent.Released","attributes":{"block":"released","_def":{"parts":[{"kind":"label","text":"released","style":[]}],"parameters":[]}},"extendsTypes":["TouchButtonEvent.Released","Number"],"pyQName":"TouchButtonEvent.RELEASED"},"TouchButtonEvent.LongPressed":{"retType":"TouchButtonEvent.LongPressed","attributes":{"block":"long pressed","_def":{"parts":[{"kind":"label","text":"long pressed","style":[]}],"parameters":[]}},"extendsTypes":["TouchButtonEvent.LongPressed","Number"],"pyQName":"TouchButtonEvent.LONG_PRESSED"},"TouchTargetMode":{"kind":6,"retType":"TouchTargetMode","extendsTypes":["TouchTargetMode","Number"]},"TouchTargetMode.Capacitive":{"retType":"TouchTargetMode.Capacitive","attributes":{"block":"capacitive","_def":{"parts":[{"kind":"label","text":"capacitive","style":[]}],"parameters":[]}},"extendsTypes":["TouchTargetMode.Capacitive","Number"],"pyQName":"TouchTargetMode.CAPACITIVE"},"TouchTargetMode.Resistive":{"retType":"TouchTargetMode.Resistive","attributes":{"block":"resistive","_def":{"parts":[{"kind":"label","text":"resistive","style":[]}],"parameters":[]}},"extendsTypes":["TouchTargetMode.Resistive","Number"],"pyQName":"TouchTargetMode.RESISTIVE"},"TouchTarget":{"kind":6,"retType":"TouchTarget","extendsTypes":["TouchTarget","Number"]},"TouchTarget.P0":{"retType":"TouchTarget.P0","attributes":{"block":"P0","_def":{"parts":[{"kind":"label","text":"P0","style":[]}],"parameters":[]}},"extendsTypes":["TouchTarget.P0","Number"]},"TouchTarget.P1":{"retType":"TouchTarget.P1","attributes":{"block":"P1","_def":{"parts":[{"kind":"label","text":"P1","style":[]}],"parameters":[]}},"extendsTypes":["TouchTarget.P1","Number"]},"TouchTarget.P2":{"retType":"TouchTarget.P2","attributes":{"block":"P2","_def":{"parts":[{"kind":"label","text":"P2","style":[]}],"parameters":[]}},"extendsTypes":["TouchTarget.P2","Number"]},"TouchTarget.LOGO":{"retType":"TouchTarget.LOGO","attributes":{"block":"logo","_def":{"parts":[{"kind":"label","text":"logo","style":[]}],"parameters":[]}},"extendsTypes":["TouchTarget.LOGO","Number"]},"images.createImage":{"kind":-3,"retType":"Image","attributes":{"weight":75,"help":"images/create-image","blockId":"device_build_image","block":"create image","parts":"ledmatrix","imageLiteral":1,"jsDoc":"Creates an image that fits on the LED screen.","_def":{"parts":[{"kind":"label","text":"create image","style":[]}],"parameters":[]}},"parameters":[{"name":"leds","type":"string"}],"pyQName":"images.create_image"},"images.createBigImage":{"kind":-3,"retType":"Image","attributes":{"weight":74,"help":"images/create-big-image","blockId":"device_build_big_image","block":"create big image","imageLiteral":2,"parts":"ledmatrix","jsDoc":"Creates an image with 2 frames.","_def":{"parts":[{"kind":"label","text":"create big image","style":[]}],"parameters":[]}},"parameters":[{"name":"leds","type":"string"}],"pyQName":"images.create_big_image"},"Image":{"kind":9,"retType":"Image","extendsTypes":[]},"Image.plotImage":{"kind":-1,"attributes":{"paramDefl":{"xOffset":"0"},"help":"images/plot-image","parts":"ledmatrix","explicitDefaults":["xOffset"],"jsDoc":"Plots the image at a given column to the screen"},"parameters":[{"name":"xOffset","initializer":"0","default":"0"}],"isInstance":true,"pyQName":"Image.plot_image"},"Image.showImage":{"kind":-1,"attributes":{"paramDefl":{"interval":"400"},"callingConvention":1,"help":"images/show-image","weight":80,"blockNamespace":"images","blockId":"device_show_image_offset","block":"show image %sprite(myImage)|at offset %offset ||and interval (ms) %interval","blockGap":"8","parts":"ledmatrix","async":"true","explicitDefaults":["interval"],"paramHelp":{"xOffset":"column index to start displaying the image","interval":"time in milliseconds to pause after drawing"},"jsDoc":"Shows an frame from the image at offset ``x offset``.","_def":{"parts":[{"kind":"label","text":"show image ","style":[]},{"kind":"param","name":"sprite","ref":false,"varName":"myImage"},{"kind":"break"},{"kind":"label","text":"at offset ","style":[]},{"kind":"param","name":"offset","ref":false},{"kind":"label","text":" ","style":[]}],"parameters":[{"kind":"param","name":"sprite","ref":false,"varName":"myImage"},{"kind":"param","name":"offset","ref":false}]},"_expandedDef":{"parts":[{"kind":"label","text":"and interval (ms) ","style":[]},{"kind":"param","name":"interval","ref":false}],"parameters":[{"kind":"param","name":"interval","ref":false}]}},"parameters":[{"name":"xOffset","description":"column index to start displaying the image"},{"name":"interval","description":"time in milliseconds to pause after drawing","initializer":"400","default":"400"}],"isInstance":true,"pyQName":"Image.show_image"},"Image.plotFrame":{"kind":-1,"attributes":{"help":"images/plot-frame","weight":80,"parts":"ledmatrix","paramHelp":{"xOffset":"column index to start displaying the image"},"jsDoc":"Draws the ``index``-th frame of the image on the screen."},"parameters":[{"name":"xOffset","description":"column index to start displaying the image"}],"isInstance":true,"pyQName":"Image.plot_frame"},"Image.scrollImage":{"kind":-1,"attributes":{"paramDefl":{"frameOffset":"1","interval":"200"},"callingConvention":1,"help":"images/scroll-image","weight":79,"async":"true","blockNamespace":"images","blockId":"device_scroll_image","block":"scroll image %sprite(myImage)|with offset %frameoffset|and interval (ms) %delay","blockGap":"8","parts":"ledmatrix","paramHelp":{"frameOffset":"x offset moved on each animation step, eg: 1, 2, 5","interval":"time between each animation step in milli seconds, eg: 200"},"jsDoc":"Scrolls an image .","_def":{"parts":[{"kind":"label","text":"scroll image ","style":[]},{"kind":"param","name":"sprite","ref":false,"varName":"myImage"},{"kind":"break"},{"kind":"label","text":"with offset ","style":[]},{"kind":"param","name":"frameoffset","ref":false},{"kind":"break"},{"kind":"label","text":"and interval (ms) ","style":[]},{"kind":"param","name":"delay","ref":false}],"parameters":[{"kind":"param","name":"sprite","ref":false,"varName":"myImage"},{"kind":"param","name":"frameoffset","ref":false},{"kind":"param","name":"delay","ref":false}]}},"parameters":[{"name":"frameOffset","description":"x offset moved on each animation step, eg: 1, 2, 5","default":"1"},{"name":"interval","description":"time between each animation step in milli seconds, eg: 200","default":"200"}],"isInstance":true,"pyQName":"Image.scroll_image"},"Image.clear":{"kind":-1,"attributes":{"help":"images/clear","parts":"ledmatrix","jsDoc":"Sets all pixels off."},"parameters":[],"isInstance":true},"Image.setPixelBrightness":{"kind":-1,"attributes":{"parts":"ledmatrix","jsDoc":"Sets a specific pixel brightness at a given position"},"parameters":[{"name":"x"},{"name":"y"},{"name":"value"}],"isInstance":true,"pyQName":"Image.set_pixel_brightness"},"Image.pixelBrightness":{"kind":-1,"retType":"number","attributes":{"parts":"ledmatrix","jsDoc":"Gets the pixel brightness ([0..255]) at a given position"},"parameters":[{"name":"x"},{"name":"y"}],"isInstance":true,"pyQName":"Image.pixel_brightness"},"Image.width":{"kind":-1,"retType":"number","attributes":{"help":"functions/width","jsDoc":"Gets the width in columns"},"parameters":[],"isInstance":true},"Image.height":{"kind":-1,"retType":"number","attributes":{"jsDoc":"Gets the height in rows (always 5)"},"parameters":[],"isInstance":true},"Image.setPixel":{"kind":-1,"attributes":{"help":"images/set-pixel","parts":"ledmatrix","paramHelp":{"x":"pixel column","y":"pixel row","value":"pixel state"},"jsDoc":"Set a pixel state at position ``(x,y)``"},"parameters":[{"name":"x","description":"pixel column"},{"name":"y","description":"pixel row"},{"name":"value","description":"pixel state","type":"boolean"}],"isInstance":true,"pyQName":"Image.set_pixel"},"Image.pixel":{"kind":-1,"retType":"boolean","attributes":{"help":"images/pixel","parts":"ledmatrix","paramHelp":{"x":"pixel column","y":"pixel row"},"jsDoc":"Get the pixel state at position ``(x,y)``"},"parameters":[{"name":"x","description":"pixel column"},{"name":"y","description":"pixel row"}],"isInstance":true},"Image.showFrame":{"kind":-1,"attributes":{"paramDefl":{"interval":"400"},"weight":70,"help":"images/show-frame","parts":"ledmatrix","explicitDefaults":["interval"],"paramHelp":{"frame":"image frame to show"},"jsDoc":"Show a particular frame of the image strip."},"parameters":[{"name":"frame","description":"image frame to show"},{"name":"interval","initializer":"400","default":"400"}],"isInstance":true,"pyQName":"Image.show_frame"},"basic.showLeds":{"kind":-3,"attributes":{"paramDefl":{"interval":"400"},"callingConvention":1,"help":"basic/show-leds","weight":95,"blockGap":"8","imageLiteral":1,"async":"true","blockId":"device_show_leds","block":"show leds","icon":"","parts":"ledmatrix","explicitDefaults":["interval"],"paramHelp":{"leds":"the pattern of LED to turn on/off.","interval":"time in milliseconds to pause after drawing."},"jsDoc":"Draws an image on the LED screen.","_def":{"parts":[{"kind":"label","text":"show leds","style":[]}],"parameters":[]}},"parameters":[{"name":"leds","description":"the pattern of LED to turn on/off.","type":"string"},{"name":"interval","description":"time in milliseconds to pause after drawing.","initializer":"400","default":"400"}],"pyQName":"basic.show_leds"},"basic.showString":{"kind":-3,"attributes":{"paramDefl":{"interval":"150","text":"Hello!"},"callingConvention":1,"help":"basic/show-string","weight":87,"blockGap":"16","block":"show|string %text","async":"true","blockId":"device_print_message","parts":"ledmatrix","paramShadowOptions":{"text":{"toString":"true"}},"explicitDefaults":["interval"],"paramHelp":{"text":"the text to scroll on the screen, eg: \"Hello!\"","interval":"how fast to shift characters; eg: 150, 100, 200, -100"},"jsDoc":"Display text on the display, one character at a time. If the string fits on the screen (i.e. is one letter), does not scroll.","_def":{"parts":[{"kind":"label","text":"show","style":[]},{"kind":"break"},{"kind":"label","text":"string ","style":[]},{"kind":"param","name":"text","ref":false}],"parameters":[{"kind":"param","name":"text","ref":false}]}},"parameters":[{"name":"text","description":"the text to scroll on the screen, eg: \"Hello!\"","type":"string","default":"Hello!","options":{"fieldEditorOptions":{"value":{"toString":"true"}}}},{"name":"interval","description":"how fast to shift characters; eg: 150, 100, 200, -100","initializer":"150","default":"150"}],"pyQName":"basic.show_string"},"basic.clearScreen":{"kind":-3,"attributes":{"help":"basic/clear-screen","weight":79,"blockId":"device_clear_display","block":"clear screen","parts":"ledmatrix","jsDoc":"Turn off all LEDs","_def":{"parts":[{"kind":"label","text":"clear screen","style":[]}],"parameters":[]}},"parameters":[],"pyQName":"basic.clear_screen"},"basic.showAnimation":{"kind":-3,"attributes":{"paramDefl":{"interval":"400"},"callingConvention":1,"help":"basic/show-animation","imageLiteral":1,"async":"true","parts":"ledmatrix","explicitDefaults":["interval"],"paramHelp":{"leds":"pattern of LEDs to turn on/off","interval":"time in milliseconds between each redraw."},"jsDoc":"Shows a sequence of LED screens as an animation."},"parameters":[{"name":"leds","description":"pattern of LEDs to turn on/off","type":"string"},{"name":"interval","description":"time in milliseconds between each redraw.","initializer":"400","default":"400"}],"pyQName":"basic.show_animation"},"basic.plotLeds":{"kind":-3,"attributes":{"help":"basic/plot-leds","weight":80,"parts":"ledmatrix","imageLiteral":1,"paramHelp":{"leds":"pattern of LEDs to turn on/off"},"jsDoc":"Draws an image on the LED screen."},"parameters":[{"name":"leds","description":"pattern of LEDs to turn on/off","type":"string"}],"pyQName":"basic.plot_leds"},"basic.forever":{"kind":-3,"attributes":{"help":"basic/forever","weight":55,"blockGap":"16","blockAllowMultiple":"1","afterOnStart":true,"blockId":"device_forever","block":"forever","icon":"","paramHelp":{"body":"code to execute"},"jsDoc":"Repeats the code forever in the background. On each iteration, allows other codes to run.","_def":{"parts":[{"kind":"label","text":"forever","style":[]}],"parameters":[]}},"parameters":[{"name":"a","type":"() => void","handlerParameters":[]}]},"basic.pause":{"kind":-3,"attributes":{"paramDefl":{"ms":"100"},"callingConvention":1,"help":"basic/pause","weight":54,"async":"true","block":"pause (ms) %pause","blockGap":"16","blockId":"device_pause","icon":"","_shadowOverrides":{"pause":"timePicker"},"paramHelp":{"ms":"how long to pause for, eg: 100, 200, 500, 1000, 2000"},"jsDoc":"Pause for the specified time in milliseconds","_def":{"parts":[{"kind":"label","text":"pause (ms) ","style":[]},{"kind":"param","name":"pause","shadowBlockId":"timePicker","ref":false}],"parameters":[{"kind":"param","name":"pause","shadowBlockId":"timePicker","ref":false}]}},"parameters":[{"name":"ms","description":"how long to pause for, eg: 100, 200, 500, 1000, 2000","default":"100"}]},"input.onButtonPressed":{"kind":-3,"attributes":{"help":"input/on-button-pressed","weight":85,"blockGap":"16","blockId":"device_button_event","block":"on button|%NAME|pressed","parts":"buttonpair","paramHelp":{"button":"the button that needs to be pressed","body":"code to run when event is raised"},"jsDoc":"Do something when a button (A, B or both A+B) is pushed down and released again.","_def":{"parts":[{"kind":"label","text":"on button","style":[]},{"kind":"break"},{"kind":"param","name":"NAME","ref":false},{"kind":"break"},{"kind":"label","text":"pressed","style":[]}],"parameters":[{"kind":"param","name":"NAME","ref":false}]}},"parameters":[{"name":"button","description":"the button that needs to be pressed","type":"Button","isEnum":true},{"name":"body","description":"code to run when event is raised","type":"() => void","handlerParameters":[]}],"pyQName":"input.on_button_pressed"},"input.onGesture":{"kind":-3,"attributes":{"paramDefl":{"gesture":"Gesture.Shake"},"help":"input/on-gesture","weight":84,"blockGap":"16","blockId":"device_gesture_event","block":"on |%NAME","parts":"accelerometer","paramFieldEditor":{"NAME":"gestures"},"paramFieldEditorOptions":{"NAME":{"columns":"4"}},"paramHelp":{"gesture":"the type of gesture to track, eg: Gesture.Shake","body":"code to run when gesture is raised"},"jsDoc":"Do something when when a gesture is done (like shaking the micro:bit).","_def":{"parts":[{"kind":"label","text":"on ","style":[]},{"kind":"break"},{"kind":"param","name":"NAME","ref":false}],"parameters":[{"kind":"param","name":"NAME","ref":false}]}},"parameters":[{"name":"gesture","description":"the type of gesture to track, eg: Gesture.Shake","type":"Gesture","default":"Gesture.Shake","isEnum":true},{"name":"body","description":"code to run when gesture is raised","type":"() => void","handlerParameters":[]}],"pyQName":"input.on_gesture"},"input.isGesture":{"kind":-3,"retType":"boolean","attributes":{"paramDefl":{"gesture":"Gesture.Shake"},"help":"input/is-gesture","weight":10,"blockGap":"8","blockId":"deviceisgesture","block":"is %gesture gesture","parts":"accelerometer","paramFieldEditor":{"gesture":"gestures"},"paramFieldEditorOptions":{"gesture":{"columns":"4"}},"paramHelp":{"gesture":"the type of gesture to detect, eg: Gesture.Shake"},"jsDoc":"Tests if a gesture is currently detected.","_def":{"parts":[{"kind":"label","text":"is ","style":[]},{"kind":"param","name":"gesture","ref":false},{"kind":"label","text":" gesture","style":[]}],"parameters":[{"kind":"param","name":"gesture","ref":false}]}},"parameters":[{"name":"gesture","description":"the type of gesture to detect, eg: Gesture.Shake","type":"Gesture","default":"Gesture.Shake","isEnum":true}],"pyQName":"input.is_gesture"},"input.onPinPressed":{"kind":-3,"attributes":{"paramDefl":{"name":"TouchPin.P0"},"help":"input/on-pin-pressed","weight":83,"blockGap":"32","blockId":"device_pin_event","block":"on pin %name|pressed","paramHelp":{"name":"the pin that needs to be pressed, eg: TouchPin.P0","body":"the code to run when the pin is pressed"},"jsDoc":"Do something when a pin is touched and released again (while also touching the GND pin).","_def":{"parts":[{"kind":"label","text":"on pin ","style":[]},{"kind":"param","name":"name","ref":false},{"kind":"break"},{"kind":"label","text":"pressed","style":[]}],"parameters":[{"kind":"param","name":"name","ref":false}]}},"parameters":[{"name":"name","description":"the pin that needs to be pressed, eg: TouchPin.P0","type":"TouchPin","default":"TouchPin.P0","isEnum":true},{"name":"body","description":"the code to run when the pin is pressed","type":"() => void","handlerParameters":[]}],"pyQName":"input.on_pin_pressed"},"input.onPinReleased":{"kind":-3,"attributes":{"paramDefl":{"name":"TouchPin.P0"},"help":"input/on-pin-released","weight":6,"blockGap":"16","blockId":"device_pin_released","block":"on pin %NAME|released","advanced":true,"paramHelp":{"name":"the pin that needs to be released, eg: TouchPin.P0","body":"the code to run when the pin is released"},"jsDoc":"Do something when a pin is released.","_def":{"parts":[{"kind":"label","text":"on pin ","style":[]},{"kind":"param","name":"NAME","ref":false},{"kind":"break"},{"kind":"label","text":"released","style":[]}],"parameters":[{"kind":"param","name":"NAME","ref":false}]}},"parameters":[{"name":"name","description":"the pin that needs to be released, eg: TouchPin.P0","type":"TouchPin","default":"TouchPin.P0","isEnum":true},{"name":"body","description":"the code to run when the pin is released","type":"() => void","handlerParameters":[]}],"pyQName":"input.on_pin_released"},"input.buttonIsPressed":{"kind":-3,"retType":"boolean","attributes":{"paramDefl":{"button":"Button.A"},"help":"input/button-is-pressed","weight":60,"block":"button|%NAME|is pressed","blockId":"device_get_button2","icon":"","blockGap":"8","parts":"buttonpair","paramHelp":{"button":"the button to query the request, eg: Button.A"},"jsDoc":"Get the button state (pressed or not) for ``A`` and ``B``.","_def":{"parts":[{"kind":"label","text":"button","style":[]},{"kind":"break"},{"kind":"param","name":"NAME","ref":false},{"kind":"break"},{"kind":"label","text":"is pressed","style":[]}],"parameters":[{"kind":"param","name":"NAME","ref":false}]}},"parameters":[{"name":"button","description":"the button to query the request, eg: Button.A","type":"Button","default":"Button.A","isEnum":true}],"pyQName":"input.button_is_pressed"},"input.pinIsPressed":{"kind":-3,"retType":"boolean","attributes":{"paramDefl":{"name":"TouchPin.P0"},"help":"input/pin-is-pressed","weight":58,"blockId":"device_pin_is_pressed","block":"pin %NAME|is pressed","blockGap":"8","paramHelp":{"name":"pin used to detect the touch, eg: TouchPin.P0"},"jsDoc":"Get the pin state (pressed or not). Requires to hold the ground to close the circuit.","_def":{"parts":[{"kind":"label","text":"pin ","style":[]},{"kind":"param","name":"NAME","ref":false},{"kind":"break"},{"kind":"label","text":"is pressed","style":[]}],"parameters":[{"kind":"param","name":"NAME","ref":false}]}},"parameters":[{"name":"name","description":"pin used to detect the touch, eg: TouchPin.P0","type":"TouchPin","default":"TouchPin.P0","isEnum":true}],"pyQName":"input.pin_is_pressed"},"input.acceleration":{"kind":-3,"retType":"number","attributes":{"paramDefl":{"dimension":"Dimension.X"},"help":"input/acceleration","weight":58,"blockId":"device_acceleration","block":"acceleration (mg)|%NAME","blockGap":"8","parts":"accelerometer","paramHelp":{"dimension":"x, y, or z dimension, eg: Dimension.X"},"jsDoc":"Get the acceleration value in milli-gravitys (when the board is laying flat with the screen up, x=0, y=0 and z=-1024)","_def":{"parts":[{"kind":"label","text":"acceleration (mg)","style":[]},{"kind":"break"},{"kind":"param","name":"NAME","ref":false}],"parameters":[{"kind":"param","name":"NAME","ref":false}]}},"parameters":[{"name":"dimension","description":"x, y, or z dimension, eg: Dimension.X","type":"Dimension","default":"Dimension.X","isEnum":true}]},"input.lightLevel":{"kind":-3,"retType":"number","attributes":{"help":"input/light-level","weight":57,"blockId":"device_get_light_level","block":"light level","blockGap":"8","parts":"ledmatrix","jsDoc":"Reads the light level applied to the LED screen in a range from ``0`` (dark) to ``255`` bright.","_def":{"parts":[{"kind":"label","text":"light level","style":[]}],"parameters":[]}},"parameters":[],"pyQName":"input.light_level"},"input.compassHeading":{"kind":-3,"retType":"number","attributes":{"help":"input/compass-heading","weight":56,"blockId":"device_heading","block":"compass heading (°)","blockGap":"8","parts":"compass","jsDoc":"Get the current compass heading in degrees.","_def":{"parts":[{"kind":"label","text":"compass heading (°)","style":[]}],"parameters":[]}},"parameters":[],"pyQName":"input.compass_heading"},"input.temperature":{"kind":-3,"retType":"number","attributes":{"weight":55,"help":"input/temperature","blockId":"device_temperature","block":"temperature (°C)","blockGap":"8","parts":"thermometer","jsDoc":"Gets the temperature in Celsius degrees (°C).","_def":{"parts":[{"kind":"label","text":"temperature (°C)","style":[]}],"parameters":[]}},"parameters":[]},"input.rotation":{"kind":-3,"retType":"number","attributes":{"help":"input/rotation","weight":52,"blockId":"device_get_rotation","block":"rotation (°)|%NAME","blockGap":"8","parts":"accelerometer","advanced":true,"paramHelp":{"kind":"pitch or roll"},"jsDoc":"The pitch or roll of the device, rotation along the ``x-axis`` or ``y-axis``, in degrees.","_def":{"parts":[{"kind":"label","text":"rotation (°)","style":[]},{"kind":"break"},{"kind":"param","name":"NAME","ref":false}],"parameters":[{"kind":"param","name":"NAME","ref":false}]}},"parameters":[{"name":"kind","description":"pitch or roll","type":"Rotation","isEnum":true}]},"input.magneticForce":{"kind":-3,"retType":"number","attributes":{"paramDefl":{"dimension":"Dimension.X"},"help":"input/magnetic-force","weight":54,"blockId":"device_get_magnetic_force","block":"magnetic force (µT)|%NAME","blockGap":"8","parts":"compass","advanced":true,"paramHelp":{"dimension":"the x, y, or z dimension, eg: Dimension.X"},"jsDoc":"Get the magnetic force value in ``micro-Teslas`` (``µT``). This function is not supported in the simulator.","_def":{"parts":[{"kind":"label","text":"magnetic force (µT)","style":[]},{"kind":"break"},{"kind":"param","name":"NAME","ref":false}],"parameters":[{"kind":"param","name":"NAME","ref":false}]}},"parameters":[{"name":"dimension","description":"the x, y, or z dimension, eg: Dimension.X","type":"Dimension","default":"Dimension.X","isEnum":true}],"pyQName":"input.magnetic_force"},"input.calibrateCompass":{"kind":-3,"attributes":{"help":"input/calibrate-compass","advanced":true,"blockId":"input_compass_calibrate","block":"calibrate compass","weight":55,"jsDoc":"Obsolete, compass calibration is automatic.","_def":{"parts":[{"kind":"label","text":"calibrate compass","style":[]}],"parameters":[]}},"parameters":[],"pyQName":"input.calibrate_compass"},"input.setAccelerometerRange":{"kind":-3,"attributes":{"help":"input/set-accelerometer-range","blockId":"device_set_accelerometer_range","block":"set accelerometer|range %range","weight":5,"parts":"accelerometer","advanced":true,"paramHelp":{"range":"a value describe the maximum strengh of acceleration measured"},"jsDoc":"Sets the accelerometer sample range in gravities.","_def":{"parts":[{"kind":"label","text":"set accelerometer","style":[]},{"kind":"break"},{"kind":"label","text":"range ","style":[]},{"kind":"param","name":"range","ref":false}],"parameters":[{"kind":"param","name":"range","ref":false}]}},"parameters":[{"name":"range","description":"a value describe the maximum strengh of acceleration measured","type":"AcceleratorRange","isEnum":true}],"pyQName":"input.set_accelerometer_range"},"control.millis":{"kind":-3,"retType":"number","attributes":{"help":"control/millis","weight":50,"blockId":"control_running_time","block":"millis (ms)","jsDoc":"Gets the number of milliseconds elapsed since power on.","_def":{"parts":[{"kind":"label","text":"millis (ms)","style":[]}],"parameters":[]}},"parameters":[]},"control.micros":{"kind":-3,"retType":"number","attributes":{"jsDoc":"Gets current time in microseconds. Overflows every ~18 minutes."},"parameters":[]},"control.inBackground":{"kind":-3,"attributes":{"help":"control/in-background","blockAllowMultiple":"1","afterOnStart":true,"blockId":"control_in_background","block":"run in background","blockGap":"8","jsDoc":"Schedules code that run in the background.","_def":{"parts":[{"kind":"label","text":"run in background","style":[]}],"parameters":[]}},"parameters":[{"name":"a","type":"() => void","handlerParameters":[]}],"pyQName":"control.in_background"},"control.waitForEvent":{"kind":-3,"attributes":{"callingConvention":1,"help":"control/wait-for-event","async":"true","blockId":"control_wait_for_event","block":"wait for event|from %src|with value %value","jsDoc":"Blocks the calling thread until the specified event is raised.","_def":{"parts":[{"kind":"label","text":"wait for event","style":[]},{"kind":"break"},{"kind":"label","text":"from ","style":[]},{"kind":"param","name":"src","ref":false},{"kind":"break"},{"kind":"label","text":"with value ","style":[]},{"kind":"param","name":"value","ref":false}],"parameters":[{"kind":"param","name":"src","ref":false},{"kind":"param","name":"value","ref":false}]}},"parameters":[{"name":"src"},{"name":"value"}],"pyQName":"control.wait_for_event"},"control.reset":{"kind":-3,"attributes":{"callingConvention":1,"weight":30,"async":"true","help":"control/reset","blockGap":"8","blockId":"control_reset","block":"reset","jsDoc":"Resets the BBC micro:bit.","_def":{"parts":[{"kind":"label","text":"reset","style":[]}],"parameters":[]}},"parameters":[]},"control.waitMicros":{"kind":-3,"attributes":{"paramDefl":{"micros":"4"},"callingConvention":1,"help":"control/wait-micros","weight":29,"async":"true","blockId":"control_wait_us","block":"wait (µs)%micros","paramMin":{"micros":"0"},"paramMax":{"micros":"6000"},"paramHelp":{"micros":"number of micro-seconds to wait. eg: 4"},"jsDoc":"Blocks the current fiber for the given microseconds","_def":{"parts":[{"kind":"label","text":"wait (µs)","style":[]},{"kind":"param","name":"micros","ref":false}],"parameters":[{"kind":"param","name":"micros","ref":false}]}},"parameters":[{"name":"micros","description":"number of micro-seconds to wait. eg: 4","default":"4","options":{"min":{"value":"0"},"max":{"value":"6000"}}}],"pyQName":"control.wait_micros"},"control.raiseEvent":{"kind":-3,"attributes":{"paramDefl":{"mode":"1"},"weight":21,"blockGap":"12","blockId":"control_raise_event","block":"raise event|from source %src=control_event_source_id|with value %value=control_event_value_id","blockExternalInputs":"1","help":"control/raise-event","explicitDefaults":["mode"],"inlineInputMode":"external","paramHelp":{"src":"ID of the MicroBit Component that generated the event e.g. MICROBIT_ID_BUTTON_A.","value":"Component specific code indicating the cause of the event.","mode":"optional definition of how the event should be processed after construction (default is CREATE_AND_FIRE)."},"jsDoc":"Raises an event in the event bus.","_def":{"parts":[{"kind":"label","text":"raise event","style":[]},{"kind":"break"},{"kind":"label","text":"from source ","style":[]},{"kind":"param","name":"src","shadowBlockId":"control_event_source_id","ref":false},{"kind":"break"},{"kind":"label","text":"with value ","style":[]},{"kind":"param","name":"value","shadowBlockId":"control_event_value_id","ref":false}],"parameters":[{"kind":"param","name":"src","shadowBlockId":"control_event_source_id","ref":false},{"kind":"param","name":"value","shadowBlockId":"control_event_value_id","ref":false}]}},"parameters":[{"name":"src","description":"ID of the MicroBit Component that generated the event e.g. MICROBIT_ID_BUTTON_A."},{"name":"value","description":"Component specific code indicating the cause of the event."},{"name":"mode","description":"optional definition of how the event should be processed after construction (default is CREATE_AND_FIRE).","type":"EventCreationMode","initializer":"1","default":"1","isEnum":true}],"pyQName":"control.raise_event"},"control.onEvent":{"kind":-3,"attributes":{"paramDefl":{"flags":"0"},"weight":20,"blockGap":"8","blockId":"control_on_event","block":"on event|from %src=control_event_source_id|with value %value=control_event_value_id","help":"control/on-event","blockExternalInputs":"1","explicitDefaults":["flags"],"inlineInputMode":"external","jsDoc":"Registers an event handler.","_def":{"parts":[{"kind":"label","text":"on event","style":[]},{"kind":"break"},{"kind":"label","text":"from ","style":[]},{"kind":"param","name":"src","shadowBlockId":"control_event_source_id","ref":false},{"kind":"break"},{"kind":"label","text":"with value ","style":[]},{"kind":"param","name":"value","shadowBlockId":"control_event_value_id","ref":false}],"parameters":[{"kind":"param","name":"src","shadowBlockId":"control_event_source_id","ref":false},{"kind":"param","name":"value","shadowBlockId":"control_event_value_id","ref":false}]}},"parameters":[{"name":"src"},{"name":"value"},{"name":"handler","type":"() => void","handlerParameters":[]},{"name":"flags","initializer":"0","default":"0"}],"pyQName":"control.on_event"},"control.eventValue":{"kind":-3,"retType":"number","attributes":{"blockId":"control_event_value\"","block":"event value","help":"control/event-value","weight":18,"jsDoc":"Gets the value of the last event executed on the bus","_def":{"parts":[{"kind":"label","text":"event value","style":[]}],"parameters":[]}},"parameters":[],"pyQName":"control.event_value"},"control.eventTimestamp":{"kind":-3,"retType":"number","attributes":{"blockId":"control_event_timestamp\"","block":"event timestamp","help":"control/event-timestamp","weight":19,"blockGap":"8","jsDoc":"Gets the timestamp of the last event executed on the bus","_def":{"parts":[{"kind":"label","text":"event timestamp","style":[]}],"parameters":[]}},"parameters":[],"pyQName":"control.event_timestamp"},"control.deviceName":{"kind":-3,"retType":"string","attributes":{"blockId":"control_device_name","block":"device name","weight":10,"blockGap":"8","help":"control/device-name","advanced":true,"jsDoc":"Make a friendly name for the device based on its serial number","_def":{"parts":[{"kind":"label","text":"device name","style":[]}],"parameters":[]}},"parameters":[],"pyQName":"control.device_name"},"control._hardwareVersion":{"kind":-3,"retType":"string","attributes":{"help":"control/hardware-version","jsDoc":"Returns the major version of the microbit"},"parameters":[],"pyQName":"control._hardware_version"},"control.deviceSerialNumber":{"kind":-3,"retType":"number","attributes":{"blockId":"control_device_serial_number","block":"device serial number","weight":9,"help":"control/device-serial-number","advanced":true,"jsDoc":"Derive a unique, consistent serial number of this device from internal data.","_def":{"parts":[{"kind":"label","text":"device serial number","style":[]}],"parameters":[]}},"parameters":[],"pyQName":"control.device_serial_number"},"control.deviceLongSerialNumber":{"kind":-3,"retType":"Buffer","attributes":{"help":"control/device-long-serial-number","advanced":true,"jsDoc":"Derive a unique, consistent 64-bit serial number of this device from internal data."},"parameters":[],"pyQName":"control.device_long_serial_number"},"control.__midiSend":{"kind":-3,"attributes":{"part":"midioutput","blockHidden":true,"jsDoc":"Informs simulator/runtime of a MIDI message\nInternal function to support the simulator."},"parameters":[{"name":"buffer","type":"Buffer"}]},"control.__log":{"kind":-3,"parameters":[{"name":"priority"},{"name":"text","type":"string"}]},"control.allocateNotifyEvent":{"kind":-3,"retType":"number","attributes":{"help":"control/allocate-notify-event","jsDoc":"Allocates the next user notification event"},"parameters":[],"pyQName":"control.allocate_notify_event"},"control.dmesg":{"kind":-3,"attributes":{"jsDoc":"Write a message to DMESG debugging buffer."},"parameters":[{"name":"s","type":"string"}]},"control.dmesgPtr":{"kind":-3,"attributes":{"jsDoc":"Write a message and value (pointer) to DMESG debugging buffer."},"parameters":[{"name":"str","type":"string"},{"name":"ptr","type":"Object"}],"pyQName":"control.dmesg_ptr"},"control.gc":{"kind":-3,"attributes":{"jsDoc":"Force GC and dump basic information about heap."},"parameters":[]},"control.heapDump":{"kind":-3,"attributes":{"jsDoc":"Force GC and halt waiting for debugger to do a full heap dump."},"parameters":[],"pyQName":"control.heap_dump"},"control.setDebugFlags":{"kind":-3,"attributes":{"jsDoc":"Set flags used when connecting an external debugger."},"parameters":[{"name":"flags"}],"pyQName":"control.set_debug_flags"},"control.heapSnapshot":{"kind":-3,"attributes":{"jsDoc":"Record a heap snapshot to debug memory leaks."},"parameters":[],"pyQName":"control.heap_snapshot"},"control.profilingEnabled":{"kind":-3,"retType":"boolean","attributes":{"jsDoc":"Return true if profiling is enabled in the current build."},"parameters":[],"pyQName":"control.profiling_enabled"},"led.plot":{"kind":-3,"attributes":{"help":"led/plot","weight":78,"blockId":"device_plot","block":"plot|x %x|y %y","blockGap":"8","parts":"ledmatrix","paramMin":{"x":"0","y":"0"},"paramMax":{"x":"4","y":"4"},"paramFieldEditorOptions":{"x":{"precision":"1"},"y":{"precision":"1"}},"paramHelp":{"x":"the horizontal coordinate of the LED starting at 0","y":"the vertical coordinate of the LED starting at 0"},"jsDoc":"Turn on the specified LED using x, y coordinates (x is horizontal, y is vertical). (0,0) is upper left.","_def":{"parts":[{"kind":"label","text":"plot","style":[]},{"kind":"break"},{"kind":"label","text":"x ","style":[]},{"kind":"param","name":"x","ref":false},{"kind":"break"},{"kind":"label","text":"y ","style":[]},{"kind":"param","name":"y","ref":false}],"parameters":[{"kind":"param","name":"x","ref":false},{"kind":"param","name":"y","ref":false}]}},"parameters":[{"name":"x","description":"the horizontal coordinate of the LED starting at 0","options":{"min":{"value":"0"},"max":{"value":"4"}}},{"name":"y","description":"the vertical coordinate of the LED starting at 0","options":{"min":{"value":"0"},"max":{"value":"4"}}}]},"led.plotBrightness":{"kind":-3,"attributes":{"paramDefl":{"brightness":"255"},"help":"led/plot-brightness","weight":78,"blockId":"device_plot_brightness","block":"plot|x %x|y %y|brightness %brightness","blockGap":"8","parts":"ledmatrix","paramMin":{"x":"0","y":"0","brightness":"0"},"paramMax":{"x":"4","y":"4","brightness":"255"},"paramFieldEditorOptions":{"x":{"precision":"1"},"y":{"precision":"1"}},"advanced":true,"paramHelp":{"x":"the horizontal coordinate of the LED starting at 0","y":"the vertical coordinate of the LED starting at 0","brightness":"the brightness from 0 (off) to 255 (bright), eg:255"},"jsDoc":"Turn on the specified LED with specific brightness using x, y coordinates (x is horizontal, y is vertical). (0,0) is upper left.","_def":{"parts":[{"kind":"label","text":"plot","style":[]},{"kind":"break"},{"kind":"label","text":"x ","style":[]},{"kind":"param","name":"x","ref":false},{"kind":"break"},{"kind":"label","text":"y ","style":[]},{"kind":"param","name":"y","ref":false},{"kind":"break"},{"kind":"label","text":"brightness ","style":[]},{"kind":"param","name":"brightness","ref":false}],"parameters":[{"kind":"param","name":"x","ref":false},{"kind":"param","name":"y","ref":false},{"kind":"param","name":"brightness","ref":false}]}},"parameters":[{"name":"x","description":"the horizontal coordinate of the LED starting at 0","options":{"min":{"value":"0"},"max":{"value":"4"}}},{"name":"y","description":"the vertical coordinate of the LED starting at 0","options":{"min":{"value":"0"},"max":{"value":"4"}}},{"name":"brightness","description":"the brightness from 0 (off) to 255 (bright), eg:255","default":"255","options":{"min":{"value":"0"},"max":{"value":"255"}}}],"pyQName":"led.plot_brightness"},"led.unplot":{"kind":-3,"attributes":{"help":"led/unplot","weight":77,"blockId":"device_unplot","block":"unplot|x %x|y %y","blockGap":"8","parts":"ledmatrix","paramMin":{"x":"0","y":"0"},"paramMax":{"x":"4","y":"4"},"paramFieldEditorOptions":{"x":{"precision":"1"},"y":{"precision":"1"}},"paramHelp":{"x":"the horizontal coordinate of the LED","y":"the vertical coordinate of the LED"},"jsDoc":"Turn off the specified LED using x, y coordinates (x is horizontal, y is vertical). (0,0) is upper left.","_def":{"parts":[{"kind":"label","text":"unplot","style":[]},{"kind":"break"},{"kind":"label","text":"x ","style":[]},{"kind":"param","name":"x","ref":false},{"kind":"break"},{"kind":"label","text":"y ","style":[]},{"kind":"param","name":"y","ref":false}],"parameters":[{"kind":"param","name":"x","ref":false},{"kind":"param","name":"y","ref":false}]}},"parameters":[{"name":"x","description":"the horizontal coordinate of the LED","options":{"min":{"value":"0"},"max":{"value":"4"}}},{"name":"y","description":"the vertical coordinate of the LED","options":{"min":{"value":"0"},"max":{"value":"4"}}}]},"led.pointBrightness":{"kind":-3,"retType":"number","attributes":{"help":"led/point-brightness","weight":76,"blockId":"device_point_brightness","block":"point|x %x|y %y brightness","parts":"ledmatrix","paramMin":{"x":"0","y":"0"},"paramMax":{"x":"4","y":"4"},"paramFieldEditorOptions":{"x":{"precision":"1"},"y":{"precision":"1"}},"advanced":true,"paramHelp":{"x":"the horizontal coordinate of the LED","y":"the vertical coordinate of the LED"},"jsDoc":"Get the brightness state of the specified LED using x, y coordinates. (0,0) is upper left.","_def":{"parts":[{"kind":"label","text":"point","style":[]},{"kind":"break"},{"kind":"label","text":"x ","style":[]},{"kind":"param","name":"x","ref":false},{"kind":"break"},{"kind":"label","text":"y ","style":[]},{"kind":"param","name":"y","ref":false},{"kind":"label","text":" brightness","style":[]}],"parameters":[{"kind":"param","name":"x","ref":false},{"kind":"param","name":"y","ref":false}]}},"parameters":[{"name":"x","description":"the horizontal coordinate of the LED","options":{"min":{"value":"0"},"max":{"value":"4"}}},{"name":"y","description":"the vertical coordinate of the LED","options":{"min":{"value":"0"},"max":{"value":"4"}}}],"pyQName":"led.point_brightness"},"led.brightness":{"kind":-3,"retType":"number","attributes":{"help":"led/brightness","weight":60,"blockId":"device_get_brightness","block":"brightness","blockGap":"8","parts":"ledmatrix","advanced":true,"jsDoc":"Get the screen brightness from 0 (off) to 255 (full bright).","_def":{"parts":[{"kind":"label","text":"brightness","style":[]}],"parameters":[]}},"parameters":[]},"led.setBrightness":{"kind":-3,"attributes":{"paramDefl":{"value":"255"},"help":"led/set-brightness","weight":59,"blockId":"device_set_brightness","block":"set brightness %value","parts":"ledmatrix","advanced":true,"paramMin":{"value":"0"},"paramMax":{"value":"255"},"paramHelp":{"value":"the brightness value, eg:255, 127, 0"},"jsDoc":"Set the screen brightness from 0 (off) to 255 (full bright).","_def":{"parts":[{"kind":"label","text":"set brightness ","style":[]},{"kind":"param","name":"value","ref":false}],"parameters":[{"kind":"param","name":"value","ref":false}]}},"parameters":[{"name":"value","description":"the brightness value, eg:255, 127, 0","default":"255","options":{"min":{"value":"0"},"max":{"value":"255"}}}],"pyQName":"led.set_brightness"},"led.stopAnimation":{"kind":-3,"attributes":{"weight":50,"help":"led/stop-animation","blockId":"device_stop_animation","block":"stop animation","parts":"ledmatrix","advanced":true,"jsDoc":"Cancels the current animation and clears other pending animations.","_def":{"parts":[{"kind":"label","text":"stop animation","style":[]}],"parameters":[]}},"parameters":[],"pyQName":"led.stop_animation"},"led.setDisplayMode":{"kind":-3,"attributes":{"weight":1,"help":"led/set-display-mode","parts":"ledmatrix","advanced":true,"blockId":"led_set_display_mode","block":"set display mode $mode","paramHelp":{"mode":"mode the display mode in which the screen operates"},"jsDoc":"Sets the display mode between black and white and greyscale for rendering LEDs.","_def":{"parts":[{"kind":"label","text":"set display mode ","style":[]},{"kind":"param","name":"mode","ref":true}],"parameters":[{"kind":"param","name":"mode","ref":true}]}},"parameters":[{"name":"mode","description":"mode the display mode in which the screen operates","type":"DisplayMode","isEnum":true}],"pyQName":"led.set_display_mode"},"led.displayMode":{"kind":-3,"retType":"DisplayMode","attributes":{"weight":1,"parts":"ledmatrix","advanced":true,"jsDoc":"Gets the current display mode"},"parameters":[],"pyQName":"led.display_mode"},"led.enable":{"kind":-3,"attributes":{"help":"led/enable","blockId":"device_led_enable","block":"led enable %on","advanced":true,"parts":"ledmatrix","jsDoc":"Turns on or off the display","_def":{"parts":[{"kind":"label","text":"led enable ","style":[]},{"kind":"param","name":"on","ref":false}],"parameters":[{"kind":"param","name":"on","ref":false}]}},"parameters":[{"name":"on","type":"boolean"}]},"led.screenshot":{"kind":-3,"retType":"Image","attributes":{"help":"led/screenshot","parts":"ledmatrix","jsDoc":"Takes a screenshot of the LED screen and returns an image."},"parameters":[]},"music":{"kind":5,"retType":"","attributes":{"color":"#E63022","weight":106,"icon":"","groups":["Melody","Tone","Volume","Tempo","Melody Advanced"],"jsDoc":"Generation of music tones."}},"music.setVolume":{"kind":-3,"attributes":{"paramDefl":{"volume":"127"},"blockId":"synth_set_volume","block":"set volume %volume","paramMin":{"volume":"0"},"paramMax":{"volume":"255"},"help":"music/set-volume","weight":70,"group":"Volume","blockGap":"8","explicitDefaults":["volume"],"paramHelp":{"volume":"the volume 0...255"},"jsDoc":"Set the default output volume of the sound synthesizer.","_def":{"parts":[{"kind":"label","text":"set volume ","style":[]},{"kind":"param","name":"volume","ref":false}],"parameters":[{"kind":"param","name":"volume","ref":false}]}},"parameters":[{"name":"volume","description":"the volume 0...255","initializer":"127","default":"127","options":{"min":{"value":"0"},"max":{"value":"255"}}}],"pyQName":"music.set_volume"},"music.volume":{"kind":-3,"retType":"number","attributes":{"blockId":"synth_get_volume","block":"volume","help":"music/volume","weight":69,"group":"Volume","blockGap":"8","jsDoc":"Returns the current output volume of the sound synthesizer.","_def":{"parts":[{"kind":"label","text":"volume","style":[]}],"parameters":[]}},"parameters":[]},"music.setBuiltInSpeakerEnabled":{"kind":-3,"attributes":{"blockId":"music_set_built_in_speaker_enable","block":"set built-in speaker $enabled","group":"micro:bit (V2)","parts":"builtinspeaker","help":"music/set-built-in-speaker-enabled","_shadowOverrides":{"enabled":"toggleOnOff"},"weight":0,"paramHelp":{"enabled":"whether the built-in speaker is enabled in addition to the sound pin"},"jsDoc":"Turn the built-in speaker on or off.\nDisabling the speaker resets the sound pin to the default of P0.","_def":{"parts":[{"kind":"label","text":"set built-in speaker ","style":[]},{"kind":"param","name":"enabled","shadowBlockId":"toggleOnOff","ref":true}],"parameters":[{"kind":"param","name":"enabled","shadowBlockId":"toggleOnOff","ref":true}]}},"parameters":[{"name":"enabled","description":"whether the built-in speaker is enabled in addition to the sound pin","type":"boolean"}],"pyQName":"music.set_built_in_speaker_enabled"},"music.isSoundPlaying":{"kind":-3,"retType":"boolean","attributes":{"blockId":"music_sound_is_playing","block":"sound is playing","group":"micro:bit (V2)","help":"music/is-sound-playing","weight":0,"jsDoc":"Check whether any sound is being played, no matter the source","_def":{"parts":[{"kind":"label","text":"sound is playing","style":[]}],"parameters":[]}},"parameters":[],"pyQName":"music.is_sound_playing"},"music.setSilenceLevel":{"kind":-3,"attributes":{"paramDefl":{"level":"0"},"group":"micro:bit (V2)","help":"music/set-silence-level","paramMin":{"level":"0"},"paramMax":{"level":"1024"},"weight":1,"explicitDefaults":["level"],"jsDoc":"Defines an optional sample level to generate during periods of silence."},"parameters":[{"name":"level","initializer":"0","default":"0","options":{"min":{"value":"0"},"max":{"value":"1024"}}}],"pyQName":"music.set_silence_level"},"pins":{"kind":5,"retType":"","attributes":{"color":"#B22222","weight":30,"icon":"","advanced":true,"groups":["Pins","Pulse","I2C","SPI","micro:bit (V2)"],"jsDoc":"Control currents in Pins for analog/digital signals, servos, i2c, ..."}},"pins.digitalReadPin":{"kind":-3,"retType":"number","attributes":{"paramDefl":{"name":"DigitalPin.P0"},"help":"pins/digital-read-pin","weight":30,"blockId":"device_get_digital_pin","block":"digital read|pin %name","blockGap":"8","_shadowOverrides":{"name":"digital_pin_shadow"},"paramHelp":{"name":"pin to read from, eg: DigitalPin.P0"},"jsDoc":"Read the specified pin or connector as either 0 or 1","_def":{"parts":[{"kind":"label","text":"digital read","style":[]},{"kind":"break"},{"kind":"label","text":"pin ","style":[]},{"kind":"param","name":"name","shadowBlockId":"digital_pin_shadow","ref":false}],"parameters":[{"kind":"param","name":"name","shadowBlockId":"digital_pin_shadow","ref":false}]}},"parameters":[{"name":"name","description":"pin to read from, eg: DigitalPin.P0","default":"DigitalPin.P0"}],"pyQName":"pins.digital_read_pin"},"pins.digitalWritePin":{"kind":-3,"attributes":{"paramDefl":{"name":"DigitalPin.P0"},"help":"pins/digital-write-pin","weight":29,"blockId":"device_set_digital_pin","block":"digital write|pin %name|to %value","paramMin":{"value":"0"},"paramMax":{"value":"1"},"_shadowOverrides":{"name":"digital_pin_shadow"},"paramHelp":{"name":"pin to write to, eg: DigitalPin.P0","value":"value to set on the pin, 1 eg,0"},"jsDoc":"Set a pin or connector value to either 0 or 1.","_def":{"parts":[{"kind":"label","text":"digital write","style":[]},{"kind":"break"},{"kind":"label","text":"pin ","style":[]},{"kind":"param","name":"name","shadowBlockId":"digital_pin_shadow","ref":false},{"kind":"break"},{"kind":"label","text":"to ","style":[]},{"kind":"param","name":"value","ref":false}],"parameters":[{"kind":"param","name":"name","shadowBlockId":"digital_pin_shadow","ref":false},{"kind":"param","name":"value","ref":false}]}},"parameters":[{"name":"name","description":"pin to write to, eg: DigitalPin.P0","default":"DigitalPin.P0"},{"name":"value","description":"value to set on the pin, 1 eg,0","options":{"min":{"value":"0"},"max":{"value":"1"}}}],"pyQName":"pins.digital_write_pin"},"pins.analogReadPin":{"kind":-3,"retType":"number","attributes":{"paramDefl":{"name":"AnalogPin.P0"},"help":"pins/analog-read-pin","weight":25,"blockId":"device_get_analog_pin","block":"analog read|pin %name","blockGap":"8","_shadowOverrides":{"name":"analog_read_write_pin_shadow"},"paramHelp":{"name":"pin to write to, eg: AnalogPin.P0"},"jsDoc":"Read the connector value as analog, that is, as a value comprised between 0 and 1023.","_def":{"parts":[{"kind":"label","text":"analog read","style":[]},{"kind":"break"},{"kind":"label","text":"pin ","style":[]},{"kind":"param","name":"name","shadowBlockId":"analog_read_write_pin_shadow","ref":false}],"parameters":[{"kind":"param","name":"name","shadowBlockId":"analog_read_write_pin_shadow","ref":false}]}},"parameters":[{"name":"name","description":"pin to write to, eg: AnalogPin.P0","default":"AnalogPin.P0"}],"pyQName":"pins.analog_read_pin"},"pins.analogWritePin":{"kind":-3,"attributes":{"paramDefl":{"name":"AnalogPin.P0","value":"1023"},"help":"pins/analog-write-pin","weight":24,"blockId":"device_set_analog_pin","block":"analog write|pin %name|to %value","blockGap":"8","paramMin":{"value":"0"},"paramMax":{"value":"1023"},"_shadowOverrides":{"name":"analog_pin_shadow"},"paramHelp":{"name":"pin name to write to, eg: AnalogPin.P0","value":"value to write to the pin between ``0`` and ``1023``. eg:1023,0"},"jsDoc":"Set the connector value as analog. Value must be comprised between 0 and 1023.","_def":{"parts":[{"kind":"label","text":"analog write","style":[]},{"kind":"break"},{"kind":"label","text":"pin ","style":[]},{"kind":"param","name":"name","shadowBlockId":"analog_pin_shadow","ref":false},{"kind":"break"},{"kind":"label","text":"to ","style":[]},{"kind":"param","name":"value","ref":false}],"parameters":[{"kind":"param","name":"name","shadowBlockId":"analog_pin_shadow","ref":false},{"kind":"param","name":"value","ref":false}]}},"parameters":[{"name":"name","description":"pin name to write to, eg: AnalogPin.P0","default":"AnalogPin.P0"},{"name":"value","description":"value to write to the pin between ``0`` and ``1023``. eg:1023,0","default":"1023","options":{"min":{"value":"0"},"max":{"value":"1023"}}}],"pyQName":"pins.analog_write_pin"},"pins.analogSetPeriod":{"kind":-3,"attributes":{"paramDefl":{"name":"AnalogPin.P0","micros":"20000"},"help":"pins/analog-set-period","weight":23,"blockGap":"8","blockId":"device_set_analog_period","block":"analog set period|pin %pin|to (µs)%micros","_shadowOverrides":{"pin":"analog_pin_shadow"},"paramHelp":{"name":"analog pin to set period to, eg: AnalogPin.P0","micros":"period in microseconds. eg:20000"},"jsDoc":"Configure the pulse-width modulation (PWM) period of the analog output in microseconds.\nIf this pin is not configured as an analog output (using `analog write pin`), the operation has no effect.","_def":{"parts":[{"kind":"label","text":"analog set period","style":[]},{"kind":"break"},{"kind":"label","text":"pin ","style":[]},{"kind":"param","name":"pin","shadowBlockId":"analog_pin_shadow","ref":false},{"kind":"break"},{"kind":"label","text":"to (µs)","style":[]},{"kind":"param","name":"micros","ref":false}],"parameters":[{"kind":"param","name":"pin","shadowBlockId":"analog_pin_shadow","ref":false},{"kind":"param","name":"micros","ref":false}]}},"parameters":[{"name":"name","description":"analog pin to set period to, eg: AnalogPin.P0","default":"AnalogPin.P0"},{"name":"micros","description":"period in microseconds. eg:20000","default":"20000"}],"pyQName":"pins.analog_set_period"},"pins.onPulsed":{"kind":-3,"attributes":{"paramDefl":{"name":"DigitalPin.P0","pulse":"PulseValue.High"},"help":"pins/on-pulsed","advanced":true,"blockId":"pins_on_pulsed","block":"on|pin %pin|pulsed %pulse","paramFieldEditor":{"pin":"gridpicker"},"paramFieldEditorOptions":{"pin":{"columns":"4","tooltips":"false","width":"250"}},"group":"Pulse","weight":25,"blockGap":"8","paramHelp":{"name":"digital pin to register to, eg: DigitalPin.P0","pulse":"the value of the pulse, eg: PulseValue.High"},"jsDoc":"Configure the pin as a digital input and generate an event when the pin is pulsed either high or low.","_def":{"parts":[{"kind":"label","text":"on","style":[]},{"kind":"break"},{"kind":"label","text":"pin ","style":[]},{"kind":"param","name":"pin","ref":false},{"kind":"break"},{"kind":"label","text":"pulsed ","style":[]},{"kind":"param","name":"pulse","ref":false}],"parameters":[{"kind":"param","name":"pin","ref":false},{"kind":"param","name":"pulse","ref":false}]}},"parameters":[{"name":"name","description":"digital pin to register to, eg: DigitalPin.P0","type":"DigitalPin","default":"DigitalPin.P0","isEnum":true},{"name":"pulse","description":"the value of the pulse, eg: PulseValue.High","type":"PulseValue","default":"PulseValue.High","isEnum":true},{"name":"body","type":"() => void","handlerParameters":[]}],"pyQName":"pins.on_pulsed"},"pins.pulseDuration":{"kind":-3,"retType":"number","attributes":{"help":"pins/pulse-duration","advanced":true,"blockId":"pins_pulse_duration","block":"pulse duration (µs)","group":"Pulse","weight":24,"blockGap":"8","jsDoc":"Get the duration of the last pulse in microseconds. This function should be called from a ``onPulsed`` handler.","_def":{"parts":[{"kind":"label","text":"pulse duration (µs)","style":[]}],"parameters":[]}},"parameters":[],"pyQName":"pins.pulse_duration"},"pins.pulseIn":{"kind":-3,"retType":"number","attributes":{"paramDefl":{"maxDuration":"2000000","name":"DigitalPin.P0","value":"PulseValue.High"},"blockId":"pins_pulse_in","block":"pulse in (µs)|pin %name|pulsed %value","advanced":true,"help":"pins/pulse-in","_shadowOverrides":{"name":"digital_pin_shadow"},"group":"Pulse","weight":23,"blockGap":"8","explicitDefaults":["maxDuration"],"paramHelp":{"name":"the pin which measures the pulse, eg: DigitalPin.P0","value":"the value of the pulse, eg: PulseValue.High","maximum":"duration in microseconds"},"jsDoc":"Return the duration of a pulse at a pin in microseconds.","_def":{"parts":[{"kind":"label","text":"pulse in (µs)","style":[]},{"kind":"break"},{"kind":"label","text":"pin ","style":[]},{"kind":"param","name":"name","shadowBlockId":"digital_pin_shadow","ref":false},{"kind":"break"},{"kind":"label","text":"pulsed ","style":[]},{"kind":"param","name":"value","ref":false}],"parameters":[{"kind":"param","name":"name","shadowBlockId":"digital_pin_shadow","ref":false},{"kind":"param","name":"value","ref":false}]}},"parameters":[{"name":"name","description":"the pin which measures the pulse, eg: DigitalPin.P0","default":"DigitalPin.P0"},{"name":"value","description":"the value of the pulse, eg: PulseValue.High","type":"PulseValue","default":"PulseValue.High","isEnum":true},{"name":"maxDuration","initializer":"2000000","default":"2000000"}],"pyQName":"pins.pulse_in"},"pins.servoWritePin":{"kind":-3,"attributes":{"paramDefl":{"name":"AnalogPin.P0","value":"180"},"help":"pins/servo-write-pin","weight":20,"blockId":"device_set_servo_pin","block":"servo write|pin %name|to %value","blockGap":"8","parts":"microservo","trackArgs":[0],"paramMin":{"value":"0"},"paramMax":{"value":"180"},"_shadowOverrides":{"name":"analog_pin_shadow"},"group":"Servo","paramHelp":{"name":"pin to write to, eg: AnalogPin.P0","value":"angle or rotation speed, eg:180,90,0"},"jsDoc":"Write a value to the servo, controlling the shaft accordingly. On a standard servo, this will set the angle of the shaft (in degrees), moving the shaft to that orientation. On a continuous rotation servo, this will set the speed of the servo (with ``0`` being full-speed in one direction, ``180`` being full speed in the other, and a value near ``90`` being no movement).","_def":{"parts":[{"kind":"label","text":"servo write","style":[]},{"kind":"break"},{"kind":"label","text":"pin ","style":[]},{"kind":"param","name":"name","shadowBlockId":"analog_pin_shadow","ref":false},{"kind":"break"},{"kind":"label","text":"to ","style":[]},{"kind":"param","name":"value","ref":false}],"parameters":[{"kind":"param","name":"name","shadowBlockId":"analog_pin_shadow","ref":false},{"kind":"param","name":"value","ref":false}]}},"parameters":[{"name":"name","description":"pin to write to, eg: AnalogPin.P0","default":"AnalogPin.P0"},{"name":"value","description":"angle or rotation speed, eg:180,90,0","default":"180","options":{"min":{"value":"0"},"max":{"value":"180"}}}],"pyQName":"pins.servo_write_pin"},"pins.servoSetContinuous":{"kind":-3,"attributes":{"jsDoc":"Specifies that a continuous servo is connected."},"parameters":[{"name":"name"},{"name":"value","type":"boolean"}],"pyQName":"pins.servo_set_continuous"},"pins.servoSetPulse":{"kind":-3,"attributes":{"paramDefl":{"micros":"1500"},"help":"pins/servo-set-pulse","weight":19,"blockId":"device_set_servo_pulse","block":"servo set pulse|pin %value|to (µs) %micros","_shadowOverrides":{"value":"analog_pin_shadow"},"group":"Servo","paramHelp":{"name":"pin name","micros":"pulse duration in microseconds, eg:1500"},"jsDoc":"Configure the IO pin as an analog/pwm output and set a pulse width. The period is 20 ms period and the pulse width is set based on the value given in **microseconds** or `1/1000` milliseconds.","_def":{"parts":[{"kind":"label","text":"servo set pulse","style":[]},{"kind":"break"},{"kind":"label","text":"pin ","style":[]},{"kind":"param","name":"value","shadowBlockId":"analog_pin_shadow","ref":false},{"kind":"break"},{"kind":"label","text":"to (µs) ","style":[]},{"kind":"param","name":"micros","ref":false}],"parameters":[{"kind":"param","name":"value","shadowBlockId":"analog_pin_shadow","ref":false},{"kind":"param","name":"micros","ref":false}]}},"parameters":[{"name":"name","description":"pin name"},{"name":"micros","description":"pulse duration in microseconds, eg:1500","default":"1500"}],"pyQName":"pins.servo_set_pulse"},"pins.analogSetPitchPin":{"kind":-3,"attributes":{"blockId":"device_analog_set_pitch_pin","block":"analog set pitch pin %name","help":"pins/analog-set-pitch-pin","advanced":true,"_shadowOverrides":{"name":"analog_pin_shadow"},"group":"Pins","weight":12,"blockGap":"8","paramHelp":{"name":"pin to modulate pitch from"},"jsDoc":"Set the pin used when using analog pitch or music.","_def":{"parts":[{"kind":"label","text":"analog set pitch pin ","style":[]},{"kind":"param","name":"name","shadowBlockId":"analog_pin_shadow","ref":false}],"parameters":[{"kind":"param","name":"name","shadowBlockId":"analog_pin_shadow","ref":false}]}},"parameters":[{"name":"name","description":"pin to modulate pitch from"}],"pyQName":"pins.analog_set_pitch_pin"},"pins.analogSetPitchVolume":{"kind":-3,"attributes":{"blockId":"device_analog_set_pitch_volume","block":"analog set pitch volume $volume","help":"pins/analog-set-pitch-volume","weight":3,"advanced":true,"paramMin":{"volume":"0"},"paramMax":{"volume":"255"},"deprecated":"true","paramHelp":{"volume":"the intensity of the sound from 0..255"},"jsDoc":"Sets the volume on the pitch pin","_def":{"parts":[{"kind":"label","text":"analog set pitch volume ","style":[]},{"kind":"param","name":"volume","ref":true}],"parameters":[{"kind":"param","name":"volume","ref":true}]}},"parameters":[{"name":"volume","description":"the intensity of the sound from 0..255","options":{"min":{"value":"0"},"max":{"value":"255"}}}],"pyQName":"pins.analog_set_pitch_volume"},"pins.analogPitchVolume":{"kind":-3,"retType":"number","attributes":{"blockId":"device_analog_pitch_volume","block":"analog pitch volume","help":"pins/analog-pitch-volume","weight":3,"advanced":true,"deprecated":"true","jsDoc":"Gets the volume the pitch pin from 0..255","_def":{"parts":[{"kind":"label","text":"analog pitch volume","style":[]}],"parameters":[]}},"parameters":[],"pyQName":"pins.analog_pitch_volume"},"pins.analogPitch":{"kind":-3,"attributes":{"callingConvention":1,"blockId":"device_analog_pitch","block":"analog pitch %frequency|for (ms) %ms","help":"pins/analog-pitch","async":"true","advanced":true,"group":"Pins","weight":14,"blockGap":"8","paramHelp":{"frequency":"frequency to modulate in Hz.","ms":"duration of the pitch in milliseconds."},"jsDoc":"Send a pulse-width modulation (PWM) signal to the current pitch pin. Use `analog set pitch pin` to define the pitch pin.","_def":{"parts":[{"kind":"label","text":"analog pitch ","style":[]},{"kind":"param","name":"frequency","ref":false},{"kind":"break"},{"kind":"label","text":"for (ms) ","style":[]},{"kind":"param","name":"ms","ref":false}],"parameters":[{"kind":"param","name":"frequency","ref":false},{"kind":"param","name":"ms","ref":false}]}},"parameters":[{"name":"frequency","description":"frequency to modulate in Hz."},{"name":"ms","description":"duration of the pitch in milliseconds."}],"pyQName":"pins.analog_pitch"},"pins.setPull":{"kind":-3,"attributes":{"paramDefl":{"name":"DigitalPin.P0","pull":"PinPullMode.PullUp"},"help":"pins/set-pull","advanced":true,"blockId":"device_set_pull","block":"set pull|pin %pin|to %pull","_shadowOverrides":{"pin":"digital_pin_shadow"},"group":"Pins","weight":15,"blockGap":"8","paramHelp":{"name":"pin to set the pull mode on, eg: DigitalPin.P0","pull":"one of the mbed pull configurations, eg: PinPullMode.PullUp"},"jsDoc":"Configure the pull direction of of a pin.","_def":{"parts":[{"kind":"label","text":"set pull","style":[]},{"kind":"break"},{"kind":"label","text":"pin ","style":[]},{"kind":"param","name":"pin","shadowBlockId":"digital_pin_shadow","ref":false},{"kind":"break"},{"kind":"label","text":"to ","style":[]},{"kind":"param","name":"pull","ref":false}],"parameters":[{"kind":"param","name":"pin","shadowBlockId":"digital_pin_shadow","ref":false},{"kind":"param","name":"pull","ref":false}]}},"parameters":[{"name":"name","description":"pin to set the pull mode on, eg: DigitalPin.P0","default":"DigitalPin.P0"},{"name":"pull","description":"one of the mbed pull configurations, eg: PinPullMode.PullUp","type":"PinPullMode","default":"PinPullMode.PullUp","isEnum":true}],"pyQName":"pins.set_pull"},"pins.setEvents":{"kind":-3,"attributes":{"paramDefl":{"name":"DigitalPin.P0","type":"PinEventType.Edge"},"help":"pins/set-events","advanced":true,"blockId":"device_set_pin_events","block":"set pin %pin|to emit %type|events","_shadowOverrides":{"pin":"digital_pin_shadow"},"group":"Pins","weight":13,"blockGap":"8","paramHelp":{"name":"pin to set the event mode on, eg: DigitalPin.P0","type":"the type of events for this pin to emit, eg: PinEventType.Edge"},"jsDoc":"Configure the events emitted by this pin. Events can be subscribed to\nusing ``control.onEvent()``.","_def":{"parts":[{"kind":"label","text":"set pin ","style":[]},{"kind":"param","name":"pin","shadowBlockId":"digital_pin_shadow","ref":false},{"kind":"break"},{"kind":"label","text":"to emit ","style":[]},{"kind":"param","name":"type","ref":false},{"kind":"break"},{"kind":"label","text":"events","style":[]}],"parameters":[{"kind":"param","name":"pin","shadowBlockId":"digital_pin_shadow","ref":false},{"kind":"param","name":"type","ref":false}]}},"parameters":[{"name":"name","description":"pin to set the event mode on, eg: DigitalPin.P0","default":"DigitalPin.P0"},{"name":"type","description":"the type of events for this pin to emit, eg: PinEventType.Edge","type":"PinEventType","default":"PinEventType.Edge","isEnum":true}],"pyQName":"pins.set_events"},"pins.createBuffer":{"kind":-3,"retType":"Buffer","attributes":{"paramHelp":{"size":"number of bytes in the buffer"},"jsDoc":"Create a new zero-initialized buffer."},"parameters":[{"name":"size","description":"number of bytes in the buffer"}],"pyQName":"bytearray"},"pins.setMatrixWidth":{"kind":-3,"attributes":{"paramDefl":{"width":"5","name":"DigitalPin.P1"},"help":"pins/neopixel-matrix-width","advanced":true,"blockId":"pin_neopixel_matrix_width","block":"neopixel matrix width|pin %pin %width","_shadowOverrides":{"pin":"digital_pin_shadow"},"paramMin":{"width":"2"},"group":"Pins","weight":11,"blockGap":"8","explicitDefaults":["width"],"paramHelp":{"name":"pin of Neopixel strip, eg: DigitalPin.P1","value":"width of matrix (at least ``2``)"},"jsDoc":"Set the matrix width for Neopixel strip (already assigned to a pin).\nShould be used in conjunction with `set matrix width` from Neopixel package.","_def":{"parts":[{"kind":"label","text":"neopixel matrix width","style":[]},{"kind":"break"},{"kind":"label","text":"pin ","style":[]},{"kind":"param","name":"pin","shadowBlockId":"digital_pin_shadow","ref":false},{"kind":"label","text":" ","style":[]},{"kind":"param","name":"width","ref":false}],"parameters":[{"kind":"param","name":"pin","shadowBlockId":"digital_pin_shadow","ref":false},{"kind":"param","name":"width","ref":false}]}},"parameters":[{"name":"pin"},{"name":"width","initializer":"5","default":"5","options":{"min":{"value":"2"}}}],"pyQName":"pins.set_matrix_width"},"pins.i2cReadBuffer":{"kind":-3,"retType":"Buffer","attributes":{"paramDefl":{"repeat":"0"},"explicitDefaults":["repeat"],"jsDoc":"Read `size` bytes from a 7-bit I2C `address`."},"parameters":[{"name":"address"},{"name":"size"},{"name":"repeat","type":"boolean","initializer":"0","default":"0"}],"pyQName":"pins.i2c_read_buffer"},"pins.i2cWriteBuffer":{"kind":-3,"retType":"number","attributes":{"paramDefl":{"repeat":"0"},"explicitDefaults":["repeat"],"jsDoc":"Write bytes to a 7-bit I2C `address`."},"parameters":[{"name":"address"},{"name":"buf","type":"Buffer"},{"name":"repeat","type":"boolean","initializer":"0","default":"0"}],"pyQName":"pins.i2c_write_buffer"},"pins.spiWrite":{"kind":-3,"retType":"number","attributes":{"help":"pins/spi-write","advanced":true,"blockId":"spi_write","block":"spi write %value","group":"SPI","blockGap":"8","weight":53,"paramHelp":{"value":"Data to be sent to the SPI slave"},"jsDoc":"Write to the SPI slave and return the response","_def":{"parts":[{"kind":"label","text":"spi write ","style":[]},{"kind":"param","name":"value","ref":false}],"parameters":[{"kind":"param","name":"value","ref":false}]}},"parameters":[{"name":"value","description":"Data to be sent to the SPI slave"}],"pyQName":"pins.spi_write"},"pins.spiTransfer":{"kind":-3,"attributes":{"help":"pins/spi-transfer","argsNullable":true,"paramHelp":{"command":"Data to be sent to the SPI slave (can be null)","response":"Data received from the SPI slave (can be null)"},"jsDoc":"Write to and read from the SPI slave at the same time"},"parameters":[{"name":"command","description":"Data to be sent to the SPI slave (can be null)","type":"Buffer"},{"name":"response","description":"Data received from the SPI slave (can be null)","type":"Buffer"}],"pyQName":"pins.spi_transfer"},"pins.spiFrequency":{"kind":-3,"attributes":{"paramDefl":{"frequency":"1000000"},"help":"pins/spi-frequency","advanced":true,"blockId":"spi_frequency","block":"spi frequency %frequency","group":"SPI","blockGap":"8","weight":55,"paramHelp":{"frequency":"the clock frequency, eg: 1000000"},"jsDoc":"Set the SPI frequency","_def":{"parts":[{"kind":"label","text":"spi frequency ","style":[]},{"kind":"param","name":"frequency","ref":false}],"parameters":[{"kind":"param","name":"frequency","ref":false}]}},"parameters":[{"name":"frequency","description":"the clock frequency, eg: 1000000","default":"1000000"}],"pyQName":"pins.spi_frequency"},"pins.spiFormat":{"kind":-3,"attributes":{"paramDefl":{"bits":"8","mode":"3"},"help":"pins/spi-format","advanced":true,"blockId":"spi_format","block":"spi format|bits %bits|mode %mode","group":"SPI","blockGap":"8","weight":54,"paramHelp":{"bits":"the number of bits, eg: 8","mode":"the mode, eg: 3"},"jsDoc":"Set the SPI bits and mode","_def":{"parts":[{"kind":"label","text":"spi format","style":[]},{"kind":"break"},{"kind":"label","text":"bits ","style":[]},{"kind":"param","name":"bits","ref":false},{"kind":"break"},{"kind":"label","text":"mode ","style":[]},{"kind":"param","name":"mode","ref":false}],"parameters":[{"kind":"param","name":"bits","ref":false},{"kind":"param","name":"mode","ref":false}]}},"parameters":[{"name":"bits","description":"the number of bits, eg: 8","default":"8"},{"name":"mode","description":"the mode, eg: 3","default":"3"}],"pyQName":"pins.spi_format"},"pins.spiPins":{"kind":-3,"attributes":{"help":"pins/spi-pins","advanced":true,"blockId":"spi_pins","block":"spi set pins|MOSI %mosi|MISO %miso|SCK %sck","_shadowOverrides":{"mosi":"digital_pin_shadow","miso":"digital_pin_shadow","sck":"digital_pin_shadow"},"group":"SPI","blockGap":"8","weight":51,"jsDoc":"Set the MOSI, MISO, SCK pins used by the SPI connection","_def":{"parts":[{"kind":"label","text":"spi set pins","style":[]},{"kind":"break"},{"kind":"label","text":"MOSI ","style":[]},{"kind":"param","name":"mosi","shadowBlockId":"digital_pin_shadow","ref":false},{"kind":"break"},{"kind":"label","text":"MISO ","style":[]},{"kind":"param","name":"miso","shadowBlockId":"digital_pin_shadow","ref":false},{"kind":"break"},{"kind":"label","text":"SCK ","style":[]},{"kind":"param","name":"sck","shadowBlockId":"digital_pin_shadow","ref":false}],"parameters":[{"kind":"param","name":"mosi","shadowBlockId":"digital_pin_shadow","ref":false},{"kind":"param","name":"miso","shadowBlockId":"digital_pin_shadow","ref":false},{"kind":"param","name":"sck","shadowBlockId":"digital_pin_shadow","ref":false}]}},"parameters":[{"name":"mosi"},{"name":"miso"},{"name":"sck"}],"pyQName":"pins.spi_pins"},"pins.pushButton":{"kind":-3,"attributes":{"help":"pins/push-button","advanced":true,"jsDoc":"Mounts a push button on the given pin"},"parameters":[{"name":"pin"}],"pyQName":"pins.push_button"},"pins.setAudioPin":{"kind":-3,"attributes":{"blockId":"pin_set_audio_pin","block":"set audio pin $name","help":"pins/set-audio-pin","_shadowOverrides":{"name":"digital_pin_shadow"},"weight":1,"blockGap":"8","paramHelp":{"name":"pin to modulate pitch from"},"jsDoc":"Set the pin used when producing sounds and melodies. Default is P0.","_def":{"parts":[{"kind":"label","text":"set audio pin ","style":[]},{"kind":"param","name":"name","shadowBlockId":"digital_pin_shadow","ref":true}],"parameters":[{"kind":"param","name":"name","shadowBlockId":"digital_pin_shadow","ref":true}]}},"parameters":[{"name":"name","description":"pin to modulate pitch from"}],"pyQName":"pins.set_audio_pin"},"pins.setAudioPinEnabled":{"kind":-3,"attributes":{"blockId":"pin_set_audio_pin_enabled","block":"set audio pin enabled $enabled","weight":0,"help":"pins/set-audio-pin-enabled","jsDoc":"Sets whether or not audio will be output using a pin on the edge\nconnector.","_def":{"parts":[{"kind":"label","text":"set audio pin enabled ","style":[]},{"kind":"param","name":"enabled","ref":true}],"parameters":[{"kind":"param","name":"enabled","ref":true}]}},"parameters":[{"name":"enabled","type":"boolean"}],"pyQName":"pins.set_audio_pin_enabled"},"serial.readUntil":{"kind":-3,"retType":"string","attributes":{"help":"serial/read-until","blockId":"serial_read_until","block":"serial|read until %delimiter=serial_delimiter_conv","weight":19,"paramHelp":{"delimiter":"text delimiter that separates each text chunk"},"jsDoc":"Read a line of text from the serial port and return the buffer when the delimiter is met.","_def":{"parts":[{"kind":"label","text":"serial","style":[]},{"kind":"break"},{"kind":"label","text":"read until ","style":[]},{"kind":"param","name":"delimiter","shadowBlockId":"serial_delimiter_conv","ref":false}],"parameters":[{"kind":"param","name":"delimiter","shadowBlockId":"serial_delimiter_conv","ref":false}]}},"parameters":[{"name":"delimiter","description":"text delimiter that separates each text chunk","type":"string"}],"pyQName":"serial.read_until"},"serial.readString":{"kind":-3,"retType":"string","attributes":{"help":"serial/read-string","blockId":"serial_read_buffer","block":"serial|read string","weight":18,"jsDoc":"Read the buffered received data as a string","_def":{"parts":[{"kind":"label","text":"serial","style":[]},{"kind":"break"},{"kind":"label","text":"read string","style":[]}],"parameters":[]}},"parameters":[],"pyQName":"serial.read_string"},"serial.onDataReceived":{"kind":-3,"attributes":{"help":"serial/on-data-received","weight":18,"blockId":"serial_on_data_received","block":"serial|on data received %delimiters=serial_delimiter_conv","paramHelp":{"delimiters":"the characters to match received characters against."},"jsDoc":"Register an event to be fired when one of the delimiter is matched.","_def":{"parts":[{"kind":"label","text":"serial","style":[]},{"kind":"break"},{"kind":"label","text":"on data received ","style":[]},{"kind":"param","name":"delimiters","shadowBlockId":"serial_delimiter_conv","ref":false}],"parameters":[{"kind":"param","name":"delimiters","shadowBlockId":"serial_delimiter_conv","ref":false}]}},"parameters":[{"name":"delimiters","description":"the characters to match received characters against.","type":"string"},{"name":"body","type":"() => void","handlerParameters":[]}],"pyQName":"serial.on_data_received"},"serial.writeString":{"kind":-3,"attributes":{"help":"serial/write-string","weight":87,"blockGap":"8","blockId":"serial_writestring","block":"serial|write string %text","paramShadowOptions":{"text":{"toString":"true"}},"jsDoc":"Send a piece of text through the serial connection.","_def":{"parts":[{"kind":"label","text":"serial","style":[]},{"kind":"break"},{"kind":"label","text":"write string ","style":[]},{"kind":"param","name":"text","ref":false}],"parameters":[{"kind":"param","name":"text","ref":false}]}},"parameters":[{"name":"text","type":"string","options":{"fieldEditorOptions":{"value":{"toString":"true"}}}}],"pyQName":"serial.write_string"},"serial.writeBuffer":{"kind":-3,"attributes":{"blockId":"serial_writebuffer","block":"serial|write buffer %buffer=serial_readbuffer","help":"serial/write-buffer","advanced":true,"weight":6,"jsDoc":"Send a buffer through serial connection","_def":{"parts":[{"kind":"label","text":"serial","style":[]},{"kind":"break"},{"kind":"label","text":"write buffer ","style":[]},{"kind":"param","name":"buffer","shadowBlockId":"serial_readbuffer","ref":false}],"parameters":[{"kind":"param","name":"buffer","shadowBlockId":"serial_readbuffer","ref":false}]}},"parameters":[{"name":"buffer","type":"Buffer"}],"pyQName":"serial.write_buffer"},"serial.readBuffer":{"kind":-3,"retType":"Buffer","attributes":{"blockId":"serial_readbuffer","block":"serial|read buffer %length","help":"serial/read-buffer","advanced":true,"weight":5,"paramHelp":{"length":"default buffer length"},"jsDoc":"Read multiple characters from the receive buffer. \nIf length is positive, pauses until enough characters are present.","_def":{"parts":[{"kind":"label","text":"serial","style":[]},{"kind":"break"},{"kind":"label","text":"read buffer ","style":[]},{"kind":"param","name":"length","ref":false}],"parameters":[{"kind":"param","name":"length","ref":false}]}},"parameters":[{"name":"length","description":"default buffer length"}],"pyQName":"serial.read_buffer"},"serial.redirect":{"kind":-3,"attributes":{"paramDefl":{"tx":"SerialPin.P0","rx":"SerialPin.P1","rate":"115200"},"weight":10,"help":"serial/redirect","blockId":"serial_redirect","block":"serial|redirect to|TX %tx|RX %rx|at baud rate %rate","blockExternalInputs":"1","paramFieldEditor":{"tx":"gridpicker","rx":"gridpicker"},"paramFieldEditorOptions":{"tx":{"columns":"3","tooltips":"false"},"rx":{"columns":"3","tooltips":"false"}},"blockGap":"8","inlineInputMode":"external","paramHelp":{"tx":"the new transmission pin, eg: SerialPin.P0","rx":"the new reception pin, eg: SerialPin.P1","rate":"the new baud rate. eg: 115200"},"jsDoc":"Set the serial input and output to use pins instead of the USB connection.","_def":{"parts":[{"kind":"label","text":"serial","style":[]},{"kind":"break"},{"kind":"label","text":"redirect to","style":[]},{"kind":"break"},{"kind":"label","text":"TX ","style":[]},{"kind":"param","name":"tx","ref":false},{"kind":"break"},{"kind":"label","text":"RX ","style":[]},{"kind":"param","name":"rx","ref":false},{"kind":"break"},{"kind":"label","text":"at baud rate ","style":[]},{"kind":"param","name":"rate","ref":false}],"parameters":[{"kind":"param","name":"tx","ref":false},{"kind":"param","name":"rx","ref":false},{"kind":"param","name":"rate","ref":false}]}},"parameters":[{"name":"tx","description":"the new transmission pin, eg: SerialPin.P0","type":"SerialPin","default":"SerialPin.P0","isEnum":true},{"name":"rx","description":"the new reception pin, eg: SerialPin.P1","type":"SerialPin","default":"SerialPin.P1","isEnum":true},{"name":"rate","description":"the new baud rate. eg: 115200","type":"BaudRate","default":"115200","isEnum":true}]},"serial.setBaudRate":{"kind":-3,"attributes":{"weight":10,"blockId":"serial_setbaudrate","block":"serial|set baud rate %rate","blockGap":"8","inlineInputMode":"inline","help":"serial/set-baud-rate","group":"Configuration","advanced":true,"jsDoc":"Set the baud rate of the serial port","_def":{"parts":[{"kind":"label","text":"serial","style":[]},{"kind":"break"},{"kind":"label","text":"set baud rate ","style":[]},{"kind":"param","name":"rate","ref":false}],"parameters":[{"kind":"param","name":"rate","ref":false}]}},"parameters":[{"name":"rate","type":"BaudRate","isEnum":true}],"pyQName":"serial.set_baud_rate"},"serial.redirectToUSB":{"kind":-3,"attributes":{"weight":9,"help":"serial/redirect-to-usb","blockId":"serial_redirect_to_usb","block":"serial|redirect to USB","jsDoc":"Direct the serial input and output to use the USB connection.","_def":{"parts":[{"kind":"label","text":"serial","style":[]},{"kind":"break"},{"kind":"label","text":"redirect to USB","style":[]}],"parameters":[]}},"parameters":[],"pyQName":"serial.redirect_to_usb"},"serial.setRxBufferSize":{"kind":-3,"attributes":{"paramDefl":{"size":"32"},"help":"serial/set-rx-buffer-size","blockId":"serialSetRxBufferSize","block":"serial set rx buffer size to $size","advanced":true,"paramHelp":{"size":"length of the rx buffer in bytes, eg: 32"},"jsDoc":"Sets the size of the RX buffer in bytes","_def":{"parts":[{"kind":"label","text":"serial set rx buffer size to ","style":[]},{"kind":"param","name":"size","ref":true}],"parameters":[{"kind":"param","name":"size","ref":true}]}},"parameters":[{"name":"size","description":"length of the rx buffer in bytes, eg: 32","default":"32"}],"pyQName":"serial.set_rx_buffer_size"},"serial.setTxBufferSize":{"kind":-3,"attributes":{"paramDefl":{"size":"32"},"help":"serial/set-tx-buffer-size","blockId":"serialSetTxBufferSize","block":"serial set tx buffer size to $size","advanced":true,"paramHelp":{"size":"length of the tx buffer in bytes, eg: 32"},"jsDoc":"Sets the size of the TX buffer in bytes","_def":{"parts":[{"kind":"label","text":"serial set tx buffer size to ","style":[]},{"kind":"param","name":"size","ref":true}],"parameters":[{"kind":"param","name":"size","ref":true}]}},"parameters":[{"name":"size","description":"length of the tx buffer in bytes, eg: 32","default":"32"}],"pyQName":"serial.set_tx_buffer_size"},"serial.writeDmesg":{"kind":-3,"attributes":{"jsDoc":"Send DMESG debug buffer over serial."},"parameters":[],"pyQName":"serial.write_dmesg"},"Buffer":{"kind":5,"retType":""},"Buffer.getUint8":{"kind":-1,"retType":"number","attributes":{"jsDoc":"Reads an unsigned byte at a particular location"},"parameters":[{"name":"off"}],"isInstance":true,"pyQName":"Buffer.get_uint8"},"Buffer.isReadOnly":{"kind":-1,"retType":"boolean","attributes":{"jsDoc":"Returns false when the buffer can be written to."},"parameters":[],"isInstance":true,"pyQName":"Buffer.is_read_only"},"Buffer.setUint8":{"kind":-1,"attributes":{"jsDoc":"Writes an unsigned byte at a particular location"},"parameters":[{"name":"off"},{"name":"v"}],"isInstance":true,"pyQName":"Buffer.set_uint8"},"Buffer.setNumber":{"kind":-1,"attributes":{"jsDoc":"Write a number in specified format in the buffer."},"parameters":[{"name":"format","type":"NumberFormat","isEnum":true},{"name":"offset"},{"name":"value"}],"isInstance":true,"pyQName":"Buffer.set_number"},"Buffer.getNumber":{"kind":-1,"retType":"number","attributes":{"jsDoc":"Read a number in specified format from the buffer."},"parameters":[{"name":"format","type":"NumberFormat","isEnum":true},{"name":"offset"}],"isInstance":true,"pyQName":"Buffer.get_number"},"Buffer.length":{"kind":2,"retType":"number","attributes":{"property":"true","jsDoc":"Returns the length of a Buffer object."},"isInstance":true},"Buffer.fill":{"kind":-1,"attributes":{"paramDefl":{"offset":"0","length":"-1"},"explicitDefaults":["offset","length"],"jsDoc":"Fill (a fragment) of the buffer with given value."},"parameters":[{"name":"value"},{"name":"offset","initializer":"0","default":"0"},{"name":"length","initializer":"-1","default":"-1"}],"isInstance":true},"Buffer.slice":{"kind":-1,"retType":"Buffer","attributes":{"paramDefl":{"offset":"0","length":"-1"},"explicitDefaults":["offset","length"],"jsDoc":"Return a copy of a fragment of a buffer."},"parameters":[{"name":"offset","initializer":"0","default":"0"},{"name":"length","initializer":"-1","default":"-1"}],"isInstance":true},"Buffer.shift":{"kind":-1,"attributes":{"paramDefl":{"start":"0","length":"-1"},"explicitDefaults":["start","length"],"paramHelp":{"offset":"number of bytes to shift; use negative value to shift right","start":"start offset in buffer. Default is 0.","length":"number of elements in buffer. If negative, length is set as the buffer length minus"},"jsDoc":"Shift buffer left in place, with zero padding.\n\n\n\nstart. eg: -1"},"parameters":[{"name":"offset","description":"number of bytes to shift; use negative value to shift right"},{"name":"start","description":"start offset in buffer. Default is 0.","initializer":"0","default":"0"},{"name":"length","description":"number of elements in buffer. If negative, length is set as the buffer length minus","initializer":"-1","default":"-1"}],"isInstance":true},"Buffer.toString":{"kind":-1,"retType":"string","attributes":{"jsDoc":"Convert a buffer to string assuming UTF8 encoding"},"parameters":[],"isInstance":true,"pyQName":"Buffer.to_string"},"Buffer.toHex":{"kind":-1,"retType":"string","attributes":{"jsDoc":"Convert a buffer to its hexadecimal representation."},"parameters":[],"isInstance":true,"pyQName":"Buffer.to_hex"},"Buffer.rotate":{"kind":-1,"attributes":{"paramDefl":{"start":"0","length":"-1"},"explicitDefaults":["start","length"],"paramHelp":{"offset":"number of bytes to shift; use negative value to shift right","start":"start offset in buffer. Default is 0.","length":"number of elements in buffer. If negative, length is set as the buffer length minus"},"jsDoc":"Rotate buffer left in place.\n\n\n\nstart. eg: -1"},"parameters":[{"name":"offset","description":"number of bytes to shift; use negative value to shift right"},{"name":"start","description":"start offset in buffer. Default is 0.","initializer":"0","default":"0"},{"name":"length","description":"number of elements in buffer. If negative, length is set as the buffer length minus","initializer":"-1","default":"-1"}],"isInstance":true},"Buffer.write":{"kind":-1,"attributes":{"jsDoc":"Write contents of `src` at `dstOffset` in current buffer."},"parameters":[{"name":"dstOffset"},{"name":"src","type":"Buffer"}],"isInstance":true},"Buffer.hash":{"kind":-1,"retType":"number","attributes":{"jsDoc":"Compute k-bit FNV-1 non-cryptographic hash of the buffer."},"parameters":[{"name":"bits"}],"isInstance":true},"control.createBuffer":{"kind":-3,"retType":"Buffer","attributes":{"deprecated":"1","paramHelp":{"size":"number of bytes in the buffer"},"jsDoc":"Create a new zero-initialized buffer."},"parameters":[{"name":"size","description":"number of bytes in the buffer"}],"pyQName":"bytearray"},"control.createBufferFromUTF8":{"kind":-3,"retType":"Buffer","attributes":{"deprecated":"1","paramHelp":{"str":"the string to put in the buffer"},"jsDoc":"Create a new buffer with UTF8-encoded string"},"parameters":[{"name":"str","description":"the string to put in the buffer","type":"string"}],"pyQName":"control.create_buffer_from_utf8"},"light":{"kind":5,"retType":""},"light.sendWS2812Buffer":{"kind":-3,"attributes":{"advanced":true,"jsDoc":"Sends a color buffer to a light strip"},"parameters":[{"name":"buf","type":"Buffer"},{"name":"pin"}],"pyQName":"light.send_ws2812_buffer"},"light.sendWS2812BufferWithBrightness":{"kind":-3,"attributes":{"advanced":true,"jsDoc":"Sends a color buffer to a light strip"},"parameters":[{"name":"buf","type":"Buffer"},{"name":"pin"},{"name":"brightness"}],"pyQName":"light.send_ws2812_buffer_with_brightness"},"light.setMode":{"kind":-3,"attributes":{"advanced":true,"jsDoc":"Sets the light mode of a pin"},"parameters":[{"name":"pin"},{"name":"mode"}],"pyQName":"light.set_mode"},"input.onLogoEvent":{"kind":-3,"attributes":{"weight":83,"blockGap":"32","blockId":"input_logo_event","block":"on logo $action","group":"micro:bit (V2)","parts":"logotouch","help":"input/on-logo-event","paramHelp":{"body":"the code to run when the logo is pressed"},"jsDoc":"Do something when the logo is touched and released again.","_def":{"parts":[{"kind":"label","text":"on logo ","style":[]},{"kind":"param","name":"action","ref":true}],"parameters":[{"kind":"param","name":"action","ref":true}]}},"parameters":[{"name":"action","type":"TouchButtonEvent","isEnum":true},{"name":"body","description":"the code to run when the logo is pressed","type":"() => void","handlerParameters":[]}],"pyQName":"input.on_logo_event"},"input.logoIsPressed":{"kind":-3,"retType":"boolean","attributes":{"weight":58,"blockId":"input_logo_is_pressed","block":"logo is pressed","blockGap":"8","group":"micro:bit (V2)","parts":"logotouch","help":"input/logo-is-pressed","jsDoc":"Get the logo state (pressed or not).","_def":{"parts":[{"kind":"label","text":"logo is pressed","style":[]}],"parameters":[]}},"parameters":[],"pyQName":"input.logo_is_pressed"},"pins.touchSetMode":{"kind":-3,"attributes":{"weight":60,"blockId":"device_touch_set_type","block":"set %name to touch mode %mode","advanced":true,"group":"micro:bit (V2)","help":"pins/touch-set-mode","paramHelp":{"name":"target to change the touch mode for","mode":"the touch mode to use"},"jsDoc":"Configure the touch detection for the pins and logo.\nP0, P1, P2 use resistive touch by default.\nThe logo uses capacitative touch by default.","_def":{"parts":[{"kind":"label","text":"set ","style":[]},{"kind":"param","name":"name","ref":false},{"kind":"label","text":" to touch mode ","style":[]},{"kind":"param","name":"mode","ref":false}],"parameters":[{"kind":"param","name":"name","ref":false},{"kind":"param","name":"mode","ref":false}]}},"parameters":[{"name":"name","description":"target to change the touch mode for","type":"TouchTarget","isEnum":true},{"name":"mode","description":"the touch mode to use","type":"TouchTargetMode","isEnum":true}],"pyQName":"pins.touch_set_mode"},"music.__playSoundExpression":{"kind":-3,"attributes":{"callingConvention":1,"async":"true","jsDoc":"Internal use only"},"parameters":[{"name":"nodes","type":"string"},{"name":"waitTillDone","type":"boolean"}]},"music.__stopSoundExpressions":{"kind":-3,"attributes":{"jsDoc":"Internal use only"},"parameters":[]},"Array":{"kind":5,"retType":"","attributes":{"blockNamespace":"Arrays","jsDoc":"Add, remove, and replace items in lists."}},"Array.length":{"kind":2,"retType":"number","attributes":{"weight":84,"blockId":"lists_length","block":"length of %VALUE","blockBuiltin":"true","blockNamespace":"arrays","jsDoc":"Get or set the length of an array. This number is one more than the index of the last element the array.","_def":{"parts":[{"kind":"label","text":"length of ","style":[]},{"kind":"param","name":"VALUE","ref":false}],"parameters":[{"kind":"param","name":"VALUE","ref":false}]}},"isInstance":true},"Array.push":{"kind":-1,"attributes":{"help":"arrays/push","weight":50,"blockId":"array_push","block":"%list| add value %value| to end","blockNamespace":"arrays","group":"Modify","paramHelp":{"items":"New elements of the Array."},"jsDoc":"Append a new element to an array.","_def":{"parts":[{"kind":"param","name":"list","ref":false},{"kind":"break"},{"kind":"label","text":" add value ","style":[]},{"kind":"param","name":"value","ref":false},{"kind":"break"},{"kind":"label","text":" to end","style":[]}],"parameters":[{"kind":"param","name":"list","ref":false},{"kind":"param","name":"value","ref":false}]}},"parameters":[{"name":"item","type":"T"}],"isInstance":true,"pyQName":"Array.append"},"Array.concat":{"kind":-1,"retType":"T[]","attributes":{"helper":"arrayConcat","weight":40,"paramHelp":{"arr":"The other array that is being concatenated with"},"jsDoc":"Concatenates the values with another array."},"parameters":[{"name":"arr","description":"The other array that is being concatenated with","type":"T[]"}],"isInstance":true},"Array.pop":{"kind":-1,"retType":"T","attributes":{"help":"arrays/pop","weight":45,"blockId":"array_pop","block":"get and remove last value from %list","blockNamespace":"arrays","group":"Read","jsDoc":"Remove the last element from an array and return it.","_def":{"parts":[{"kind":"label","text":"get and remove last value from ","style":[]},{"kind":"param","name":"list","ref":false}],"parameters":[{"kind":"param","name":"list","ref":false}]}},"parameters":[],"isInstance":true},"Array.reverse":{"kind":-1,"attributes":{"help":"arrays/reverse","helper":"arrayReverse","weight":10,"blockId":"array_reverse","block":"reverse %list","blockNamespace":"arrays","group":"Operations","jsDoc":"Reverse the elements in an array. The first array element becomes the last, and the last array element becomes the first.","_def":{"parts":[{"kind":"label","text":"reverse ","style":[]},{"kind":"param","name":"list","ref":false}],"parameters":[{"kind":"param","name":"list","ref":false}]}},"parameters":[],"isInstance":true},"Array.shift":{"kind":-1,"retType":"T","attributes":{"help":"arrays/shift","helper":"arrayShift","weight":30,"blockId":"array_shift","block":"get and remove first value from %list","blockNamespace":"arrays","group":"Read","jsDoc":"Remove the first element from an array and return it. This method changes the length of the array.","_def":{"parts":[{"kind":"label","text":"get and remove first value from ","style":[]},{"kind":"param","name":"list","ref":false}],"parameters":[{"kind":"param","name":"list","ref":false}]}},"parameters":[],"isInstance":true},"Array.unshift":{"kind":-1,"retType":"number","attributes":{"help":"arrays/unshift","helper":"arrayUnshift","weight":25,"blockId":"array_unshift","block":"%list| insert %value| at beginning","blockNamespace":"arrays","group":"Modify","paramHelp":{"element":"to insert at the start of the Array."},"jsDoc":"Add one element to the beginning of an array and return the new length of the array.","_def":{"parts":[{"kind":"param","name":"list","ref":false},{"kind":"break"},{"kind":"label","text":" insert ","style":[]},{"kind":"param","name":"value","ref":false},{"kind":"break"},{"kind":"label","text":" at beginning","style":[]}],"parameters":[{"kind":"param","name":"list","ref":false},{"kind":"param","name":"value","ref":false}]}},"parameters":[{"name":"value","type":"T"}],"isInstance":true},"Array.slice":{"kind":-1,"retType":"T[]","attributes":{"paramDefl":{"start":"0","end":"0"},"help":"arrays/slice","helper":"arraySlice","weight":41,"blockNamespace":"arrays","paramHelp":{"start":"The beginning of the specified portion of the array. eg: 0","end":"The end of the specified portion of the array. eg: 0"},"jsDoc":"Return a section of an array."},"parameters":[{"name":"start","description":"The beginning of the specified portion of the array. eg: 0","initializer":"undefined","default":"0"},{"name":"end","description":"The end of the specified portion of the array. eg: 0","initializer":"undefined","default":"0"}],"isInstance":true},"Array.splice":{"kind":-1,"attributes":{"paramDefl":{"start":"0","deleteCount":"0"},"helper":"arraySplice","weight":40,"paramHelp":{"start":"The zero-based location in the array from which to start removing elements. eg: 0","deleteCount":"The number of elements to remove. eg: 0"},"jsDoc":"Remove elements from an array."},"parameters":[{"name":"start","description":"The zero-based location in the array from which to start removing elements. eg: 0","default":"0"},{"name":"deleteCount","description":"The number of elements to remove. eg: 0","default":"0"}],"isInstance":true},"Array.join":{"kind":-1,"retType":"string","attributes":{"helper":"arrayJoin","weight":40,"paramHelp":{"sep":"the string separator"},"jsDoc":"joins all elements of an array into a string and returns this string."},"parameters":[{"name":"sep","description":"the string separator","type":"string","initializer":"undefined"}],"isInstance":true},"Array.some":{"kind":-1,"retType":"boolean","attributes":{"helper":"arraySome","weight":40,"paramHelp":{"callbackfn":"A function that accepts up to two arguments. The some method calls the callbackfn function one time for each element in the array."},"jsDoc":"Tests whether at least one element in the array passes the test implemented by the provided function."},"parameters":[{"name":"callbackfn","description":"A function that accepts up to two arguments. The some method calls the callbackfn function one time for each element in the array.","type":"(value: T, index: number) => boolean","handlerParameters":[{"name":"value","type":"T"},{"name":"index","type":"number"}]}],"isInstance":true},"Array.every":{"kind":-1,"retType":"boolean","attributes":{"helper":"arrayEvery","weight":40,"paramHelp":{"callbackfn":"A function that accepts up to two arguments. The every method calls the callbackfn function one time for each element in the array."},"jsDoc":"Tests whether all elements in the array pass the test implemented by the provided function."},"parameters":[{"name":"callbackfn","description":"A function that accepts up to two arguments. The every method calls the callbackfn function one time for each element in the array.","type":"(value: T, index: number) => boolean","handlerParameters":[{"name":"value","type":"T"},{"name":"index","type":"number"}]}],"isInstance":true},"Array.sort":{"kind":-1,"retType":"T[]","attributes":{"helper":"arraySort","weight":40,"paramHelp":{"specifies":"a function that defines the sort order. If omitted, the array is sorted according to the prmitive type"},"jsDoc":"Sort the elements of an array in place and returns the array. The sort is not necessarily stable."},"parameters":[{"name":"callbackfn","type":"(value1: T, value2: T) => number","initializer":"undefined","handlerParameters":[{"name":"value1","type":"T"},{"name":"value2","type":"T"}]}],"isInstance":true},"Array.map":{"kind":-1,"retType":"U[]","attributes":{"helper":"arrayMap","weight":40,"paramHelp":{"callbackfn":"A function that accepts up to two arguments. The map method calls the callbackfn function one time for each element in the array."},"jsDoc":"Call a defined callback function on each element of an array, and return an array containing the results."},"parameters":[{"name":"callbackfn","description":"A function that accepts up to two arguments. The map method calls the callbackfn function one time for each element in the array.","type":"(value: T, index: number) => U","handlerParameters":[{"name":"value","type":"T"},{"name":"index","type":"number"}]}],"isInstance":true},"Array.forEach":{"kind":-1,"attributes":{"helper":"arrayForEach","weight":40,"paramHelp":{"callbackfn":"A function that accepts up to two arguments. The forEach method calls the callbackfn function one time for each element in the array."},"jsDoc":"Call a defined callback function on each element of an array."},"parameters":[{"name":"callbackfn","description":"A function that accepts up to two arguments. The forEach method calls the callbackfn function one time for each element in the array.","type":"(value: T, index: number) => void","handlerParameters":[{"name":"value","type":"T"},{"name":"index","type":"number"}]}],"isInstance":true,"pyQName":"Array.for_each"},"Array.filter":{"kind":-1,"retType":"T[]","attributes":{"helper":"arrayFilter","weight":40,"paramHelp":{"callbackfn":"A function that accepts up to two arguments. The filter method calls the callbackfn function one time for each element in the array."},"jsDoc":"Return the elements of an array that meet the condition specified in a callback function."},"parameters":[{"name":"callbackfn","description":"A function that accepts up to two arguments. The filter method calls the callbackfn function one time for each element in the array.","type":"(value: T, index: number) => boolean","handlerParameters":[{"name":"value","type":"T"},{"name":"index","type":"number"}]}],"isInstance":true},"Array.fill":{"kind":-1,"retType":"T[]","attributes":{"helper":"arrayFill","weight":39,"jsDoc":"Fills all the elements of an array from a start index to an end index with a static value. The end index is not included."},"parameters":[{"name":"value","type":"T"},{"name":"start","initializer":"undefined"},{"name":"end","initializer":"undefined"}],"isInstance":true},"Array.find":{"kind":-1,"retType":"T","attributes":{"helper":"arrayFind","weight":40,"paramHelp":{"callbackfn":""},"jsDoc":"Returns the value of the first element in the array that satisfies the provided testing function. Otherwise undefined is returned."},"parameters":[{"name":"callbackfn","type":"(value: T, index: number) => boolean","handlerParameters":[{"name":"value","type":"T"},{"name":"index","type":"number"}]}],"isInstance":true},"Array.reduce":{"kind":-1,"retType":"U","attributes":{"helper":"arrayReduce","weight":40,"paramHelp":{"callbackfn":"A function that accepts up to three arguments. The reduce method calls the callbackfn function one time for each element in the array.","initialValue":"Initial value to start the accumulation. The first call to the callbackfn function provides this value as an argument instead of an array value."},"jsDoc":"Call the specified callback function for all the elements in an array. The return value of the callback function is the accumulated result, and is provided as an argument in the next call to the callback function."},"parameters":[{"name":"callbackfn","description":"A function that accepts up to three arguments. The reduce method calls the callbackfn function one time for each element in the array.","type":"(previousValue: U, currentValue: T, currentIndex: number) => U","handlerParameters":[{"name":"previousValue","type":"U"},{"name":"currentValue","type":"T"},{"name":"currentIndex","type":"number"}]},{"name":"initialValue","description":"Initial value to start the accumulation. The first call to the callbackfn function provides this value as an argument instead of an array value.","type":"U"}],"isInstance":true},"Array.removeElement":{"kind":-1,"retType":"boolean","attributes":{"weight":48,"jsDoc":"Remove the first occurrence of an object. Returns true if removed."},"parameters":[{"name":"element","type":"T"}],"isInstance":true,"pyQName":"Array.remove_element"},"Array.removeAt":{"kind":-1,"retType":"T","attributes":{"help":"arrays/remove-at","weight":47,"blockId":"array_removeat","block":"%list| get and remove value at %index","blockNamespace":"arrays","group":"Read","jsDoc":"Remove and return the element at a certain index.","_def":{"parts":[{"kind":"param","name":"list","ref":false},{"kind":"break"},{"kind":"label","text":" get and remove value at ","style":[]},{"kind":"param","name":"index","ref":false}],"parameters":[{"kind":"param","name":"list","ref":false},{"kind":"param","name":"index","ref":false}]}},"parameters":[{"name":"index"}],"isInstance":true,"pyQName":"Array.remove_at"},"Array.insertAt":{"kind":-1,"attributes":{"paramDefl":{"index":"0","the":"0"},"help":"arrays/insert-at","weight":20,"blockId":"array_insertAt","block":"%list| insert at %index| value %value","blockNamespace":"arrays","group":"Modify","paramHelp":{"index":"the zero-based position in the list to insert the value, eg: 0","the":"value to insert, eg: 0"},"jsDoc":"Insert the value at a particular index, increases length by 1","_def":{"parts":[{"kind":"param","name":"list","ref":false},{"kind":"break"},{"kind":"label","text":" insert at ","style":[]},{"kind":"param","name":"index","ref":false},{"kind":"break"},{"kind":"label","text":" value ","style":[]},{"kind":"param","name":"value","ref":false}],"parameters":[{"kind":"param","name":"list","ref":false},{"kind":"param","name":"index","ref":false},{"kind":"param","name":"value","ref":false}]}},"parameters":[{"name":"index","description":"the zero-based position in the list to insert the value, eg: 0","default":"0"},{"name":"value","type":"T"}],"isInstance":true,"pyQName":"Array.insert_at"},"Array.indexOf":{"kind":-1,"retType":"number","attributes":{"help":"arrays/index-of","weight":40,"blockId":"array_indexof","block":"%list| find index of %value","blockNamespace":"arrays","group":"Operations","paramHelp":{"item":"The value to locate in the array.","fromIndex":"The array index at which to begin the search. If fromIndex is omitted, the search starts at index 0."},"jsDoc":"Return the index of the first occurrence of a value in an array.","_def":{"parts":[{"kind":"param","name":"list","ref":false},{"kind":"break"},{"kind":"label","text":" find index of ","style":[]},{"kind":"param","name":"value","ref":false}],"parameters":[{"kind":"param","name":"list","ref":false},{"kind":"param","name":"value","ref":false}]}},"parameters":[{"name":"item","description":"The value to locate in the array.","type":"T"},{"name":"fromIndex","description":"The array index at which to begin the search. If fromIndex is omitted, the search starts at index 0.","initializer":"undefined"}],"isInstance":true,"pyQName":"Array.index_of"},"Array.get":{"kind":-1,"retType":"T","attributes":{"paramDefl":{"index":"0"},"help":"arrays/get","weight":85,"paramHelp":{"index":"the zero-based position in the list of the item, eg: 0"},"jsDoc":"Get the value at a particular index"},"parameters":[{"name":"index","description":"the zero-based position in the list of the item, eg: 0","default":"0"}],"isInstance":true},"Array.set":{"kind":-1,"attributes":{"paramDefl":{"index":"0","value":"0"},"help":"arrays/set","weight":84,"paramHelp":{"index":"the zero-based position in the list to store the value, eg: 0","value":"the value to insert, eg: 0"},"jsDoc":"Store a value at a particular index"},"parameters":[{"name":"index","description":"the zero-based position in the list to store the value, eg: 0","default":"0"},{"name":"value","description":"the value to insert, eg: 0","type":"T","default":"0"}],"isInstance":true},"Array._pickRandom":{"kind":-1,"retType":"T","attributes":{"help":"arrays/pick-random","helper":"arrayPickRandom","weight":25,"blockId":"array_pickRandom","block":"get random value from %list","blockNamespace":"arrays","group":"Read","jsDoc":"Return a random value from the array","_def":{"parts":[{"kind":"label","text":"get random value from ","style":[]},{"kind":"param","name":"list","ref":false}],"parameters":[{"kind":"param","name":"list","ref":false}]}},"parameters":[],"isInstance":true,"pyQName":"Array._pick_random"},"Array._unshiftStatement":{"kind":-1,"attributes":{"help":"arrays/unshift","helper":"arrayUnshift","weight":24,"blockId":"array_unshift_statement","block":"%list| insert %value| at beginning","blockNamespace":"arrays","blockAliasFor":"Array.unshift","group":"Modify","paramHelp":{"element":"to insert at the start of the Array."},"jsDoc":"Add one element to the beginning of an array and return the new length of the array.","_def":{"parts":[{"kind":"param","name":"list","ref":false},{"kind":"break"},{"kind":"label","text":" insert ","style":[]},{"kind":"param","name":"value","ref":false},{"kind":"break"},{"kind":"label","text":" at beginning","style":[]}],"parameters":[{"kind":"param","name":"list","ref":false},{"kind":"param","name":"value","ref":false}]}},"parameters":[{"name":"value","type":"T"}],"isInstance":true,"pyQName":"Array._unshift_statement"},"Array._popStatement":{"kind":-1,"attributes":{"help":"arrays/pop","weight":44,"blockId":"array_pop_statement","block":"remove last value from %list","blockNamespace":"arrays","blockAliasFor":"Array.pop","group":"Modify","jsDoc":"Remove the last element from an array and return it.","_def":{"parts":[{"kind":"label","text":"remove last value from ","style":[]},{"kind":"param","name":"list","ref":false}],"parameters":[{"kind":"param","name":"list","ref":false}]}},"parameters":[],"isInstance":true,"pyQName":"Array._pop_statement"},"Array._shiftStatement":{"kind":-1,"attributes":{"help":"arrays/shift","helper":"arrayShift","weight":29,"blockId":"array_shift_statement","block":"remove first value from %list","blockNamespace":"arrays","blockAliasFor":"Array.shift","group":"Modify","jsDoc":"Remove the first element from an array and return it. This method changes the length of the array.","_def":{"parts":[{"kind":"label","text":"remove first value from ","style":[]},{"kind":"param","name":"list","ref":false}],"parameters":[{"kind":"param","name":"list","ref":false}]}},"parameters":[],"isInstance":true,"pyQName":"Array._shift_statement"},"Array._removeAtStatement":{"kind":-1,"attributes":{"help":"arrays/remove-at-statement","weight":14,"blockId":"array_removeat_statement","block":"%list| remove value at %index","blockNamespace":"arrays","blockAliasFor":"Array.removeAt","group":"Modify","jsDoc":"Remove the element at a certain index.","_def":{"parts":[{"kind":"param","name":"list","ref":false},{"kind":"break"},{"kind":"label","text":" remove value at ","style":[]},{"kind":"param","name":"index","ref":false}],"parameters":[{"kind":"param","name":"list","ref":false},{"kind":"param","name":"index","ref":false}]}},"parameters":[{"name":"index"}],"isInstance":true,"pyQName":"Array._remove_at_statement"},"String":{"kind":5,"retType":"","attributes":{"blockNamespace":"text","jsDoc":"Combine, split, and search text strings."}},"String.concat":{"kind":-1,"retType":"string","attributes":{"weight":49,"blockId":"string_concat","blockNamespace":"text","paramHelp":{"other":"The string to append to the end of the string."},"jsDoc":"Returns a string that contains the concatenation of two or more strings."},"parameters":[{"name":"other","description":"The string to append to the end of the string.","type":"string"}],"isInstance":true},"String.charAt":{"kind":-1,"retType":"string","attributes":{"paramDefl":{"this":"this"},"weight":48,"help":"text/char-at","blockId":"string_get","block":"char from %this=text|at %pos","blockNamespace":"text","explicitDefaults":["this"],"paramHelp":{"index":"The zero-based index of the desired character."},"jsDoc":"Return the character at the specified index.","_def":{"parts":[{"kind":"label","text":"char from ","style":[]},{"kind":"param","name":"this","shadowBlockId":"text","ref":false},{"kind":"break"},{"kind":"label","text":"at ","style":[]},{"kind":"param","name":"pos","ref":false}],"parameters":[{"kind":"param","name":"this","shadowBlockId":"text","ref":false},{"kind":"param","name":"pos","ref":false}]}},"parameters":[{"name":"index","description":"The zero-based index of the desired character."}],"isInstance":true,"pyQName":"String.char_at"},"String.length":{"kind":2,"retType":"number","attributes":{"property":"true","weight":47,"blockId":"text_length","block":"length of %VALUE","blockBuiltin":"true","blockNamespace":"text","jsDoc":"Returns the length of a String object.","_def":{"parts":[{"kind":"label","text":"length of ","style":[]},{"kind":"param","name":"VALUE","ref":false}],"parameters":[{"kind":"param","name":"VALUE","ref":false}]}},"isInstance":true},"String.charCodeAt":{"kind":-1,"retType":"number","attributes":{"paramDefl":{"this":"this"},"weight":46,"help":"text/char-code-at","blockId":"string_charcode_at","block":"char code from $this=text|at $index","blockNamespace":"text","explicitDefaults":["this"],"paramHelp":{"index":"The zero-based index of the desired character. If there is no character at the specified index, NaN is returned."},"jsDoc":"Return the Unicode value of the character at the specified location.","_def":{"parts":[{"kind":"label","text":"char code from ","style":[]},{"kind":"param","name":"this","shadowBlockId":"text","ref":true},{"kind":"break"},{"kind":"label","text":"at ","style":[]},{"kind":"param","name":"index","ref":true}],"parameters":[{"kind":"param","name":"this","shadowBlockId":"text","ref":true},{"kind":"param","name":"index","ref":true}]}},"parameters":[{"name":"index","description":"The zero-based index of the desired character. If there is no character at the specified index, NaN is returned."}],"isInstance":true,"pyQName":"String.char_code_at"},"String.compare":{"kind":-1,"retType":"number","attributes":{"paramDefl":{"this":"this"},"help":"text/compare","blockId":"string_compare","block":"compare %this=text| to %that","blockNamespace":"text","explicitDefaults":["this"],"paramHelp":{"that":"String to compare to target string"},"jsDoc":"See how the order of characters in two strings is different (in ASCII encoding).","_def":{"parts":[{"kind":"label","text":"compare ","style":[]},{"kind":"param","name":"this","shadowBlockId":"text","ref":false},{"kind":"break"},{"kind":"label","text":" to ","style":[]},{"kind":"param","name":"that","ref":false}],"parameters":[{"kind":"param","name":"this","shadowBlockId":"text","ref":false},{"kind":"param","name":"that","ref":false}]}},"parameters":[{"name":"that","description":"String to compare to target string","type":"string"}],"isInstance":true},"String.substr":{"kind":-1,"retType":"string","attributes":{"paramDefl":{"this":"this","start":"0","length":"10"},"helper":"stringSubstr","help":"text/substr","blockId":"string_substr_new","block":"substring of $this|from $start||of length $length","_shadowOverrides":{"this":"text"},"explicitDefaults":["this"],"blockNamespace":"text","expandArgumentsInToolbox":true,"paramHelp":{"start":"first character index; can be negative from counting from the end, eg:0","length":"number of characters to extract, eg: 10"},"jsDoc":"Return a substring of the current string.","_def":{"parts":[{"kind":"label","text":"substring of ","style":[]},{"kind":"param","name":"this","shadowBlockId":"text","ref":true},{"kind":"break"},{"kind":"label","text":"from ","style":[]},{"kind":"param","name":"start","ref":true}],"parameters":[{"kind":"param","name":"this","shadowBlockId":"text","ref":true},{"kind":"param","name":"start","ref":true}]},"_expandedDef":{"parts":[{"kind":"label","text":"of length ","style":[]},{"kind":"param","name":"length","ref":true}],"parameters":[{"kind":"param","name":"length","ref":true}]}},"parameters":[{"name":"start","description":"first character index; can be negative from counting from the end, eg:0","default":"0"},{"name":"length","description":"number of characters to extract, eg: 10","initializer":"undefined","default":"10"}],"isInstance":true},"String.replace":{"kind":-1,"retType":"string","attributes":{"helper":"stringReplace","paramHelp":{"toReplace":"the substring to replace in the current string","replacer":"either the string that replaces toReplace in the current string,"},"jsDoc":"Return the current string with the first occurrence of toReplace\nreplaced with the replacer\n\n\nor a function that accepts the substring and returns the replacement string."},"parameters":[{"name":"toReplace","description":"the substring to replace in the current string","type":"string"},{"name":"replacer","description":"either the string that replaces toReplace in the current string,","type":"string | ((sub: string) => string)"}],"isInstance":true},"String.replaceAll":{"kind":-1,"retType":"string","attributes":{"helper":"stringReplaceAll","paramHelp":{"toReplace":"the substring to replace in the current string","replacer":"either the string that replaces toReplace in the current string,"},"jsDoc":"Return the current string with each occurrence of toReplace\nreplaced with the replacer\n\n\nor a function that accepts the substring and returns the replacement string."},"parameters":[{"name":"toReplace","description":"the substring to replace in the current string","type":"string"},{"name":"replacer","description":"either the string that replaces toReplace in the current string,","type":"string | ((sub: string) => string)"}],"isInstance":true,"pyQName":"String.replace_all"},"String.slice":{"kind":-1,"retType":"string","attributes":{"paramDefl":{"start":"0"},"helper":"stringSlice","paramHelp":{"start":"first character index; can be negative from counting from the end, eg:0","end":"one-past-last character index"},"jsDoc":"Return a substring of the current string."},"parameters":[{"name":"start","description":"first character index; can be negative from counting from the end, eg:0","default":"0"},{"name":"end","description":"one-past-last character index","initializer":"undefined"}],"isInstance":true},"String.isEmpty":{"kind":-1,"retType":"boolean","attributes":{"paramDefl":{"this":"this"},"helper":"stringEmpty","help":"text/is-empty","blockId":"string_isempty","blockNamespace":"text","block":"%this=text| is empty","explicitDefaults":["this"],"jsDoc":"Returns a value indicating if the string is empty","_def":{"parts":[{"kind":"param","name":"this","shadowBlockId":"text","ref":false},{"kind":"break"},{"kind":"label","text":" is empty","style":[]}],"parameters":[{"kind":"param","name":"this","shadowBlockId":"text","ref":false}]}},"parameters":[],"isInstance":true,"pyQName":"String.is_empty"},"String.indexOf":{"kind":-1,"retType":"number","attributes":{"paramDefl":{"this":"this"},"help":"text/index-of","blockId":"string_indexof","blockNamespace":"text","block":"%this=text|find index of %searchValue","explicitDefaults":["this"],"paramHelp":{"searchValue":"the text to find","start":"optional start index for the search"},"jsDoc":"Returns the position of the first occurrence of a specified value in a string.","_def":{"parts":[{"kind":"param","name":"this","shadowBlockId":"text","ref":false},{"kind":"break"},{"kind":"label","text":"find index of ","style":[]},{"kind":"param","name":"searchValue","ref":false}],"parameters":[{"kind":"param","name":"this","shadowBlockId":"text","ref":false},{"kind":"param","name":"searchValue","ref":false}]}},"parameters":[{"name":"searchValue","description":"the text to find","type":"string"},{"name":"start","description":"optional start index for the search","initializer":"undefined"}],"isInstance":true,"pyQName":"String.index_of"},"String.includes":{"kind":-1,"retType":"boolean","attributes":{"paramDefl":{"this":"this"},"help":"text/includes","blockId":"string_includes","blockNamespace":"text","block":"%this=text|includes %searchValue","explicitDefaults":["this"],"paramHelp":{"searchValue":"the text to find","start":"optional start index for the search"},"jsDoc":"Determines whether a string contains the characters of a specified string.","_def":{"parts":[{"kind":"param","name":"this","shadowBlockId":"text","ref":false},{"kind":"break"},{"kind":"label","text":"includes ","style":[]},{"kind":"param","name":"searchValue","ref":false}],"parameters":[{"kind":"param","name":"this","shadowBlockId":"text","ref":false},{"kind":"param","name":"searchValue","ref":false}]}},"parameters":[{"name":"searchValue","description":"the text to find","type":"string"},{"name":"start","description":"optional start index for the search","initializer":"undefined"}],"isInstance":true},"String.split":{"kind":-1,"retType":"string[]","attributes":{"paramDefl":{"this":"this"},"helper":"stringSplit","help":"text/split","blockId":"string_split","blockNamespace":"text","block":"split %this=text|at %separator","explicitDefaults":["this"],"paramHelp":{"separator":"@param limit"},"jsDoc":"Splits the string according to the separators","_def":{"parts":[{"kind":"label","text":"split ","style":[]},{"kind":"param","name":"this","shadowBlockId":"text","ref":false},{"kind":"break"},{"kind":"label","text":"at ","style":[]},{"kind":"param","name":"separator","ref":false}],"parameters":[{"kind":"param","name":"this","shadowBlockId":"text","ref":false},{"kind":"param","name":"separator","ref":false}]}},"parameters":[{"name":"separator","description":"@param limit","type":"string","initializer":"undefined"},{"name":"limit","initializer":"undefined"}],"isInstance":true},"String.trim":{"kind":-1,"retType":"string","attributes":{"helper":"stringTrim","jsDoc":"Return a substring of the current string with whitespace removed from both ends"},"parameters":[],"isInstance":true},"String.toUpperCase":{"kind":-1,"retType":"string","attributes":{"helper":"stringToUpperCase","help":"text/to-upper-case","jsDoc":"Converts the string to upper case characters."},"parameters":[],"isInstance":true,"pyQName":"String.to_upper_case"},"String.toLowerCase":{"kind":-1,"retType":"string","attributes":{"helper":"stringToLowerCase","help":"text/to-lower-case","jsDoc":"Converts the string to lower case characters."},"parameters":[],"isInstance":true,"pyQName":"String.to_lower_case"},"String.__substr":{"kind":-1,"retType":"string","attributes":{"paramDefl":{"this":"this","start":"0","length":"10"},"helper":"stringSubstr","help":"text/substr","blockId":"string_substr","block":"substring of %this=text|from %start|of length %length","blockNamespace":"text","explicitDefaults":["this"],"blockAliasFor":"String.substr","deprecated":"true","paramHelp":{"start":"first character index; can be negative from counting from the end, eg:0","length":"number of characters to extract, eg: 10"},"jsDoc":"Return a substring of the current string.","_def":{"parts":[{"kind":"label","text":"substring of ","style":[]},{"kind":"param","name":"this","shadowBlockId":"text","ref":false},{"kind":"break"},{"kind":"label","text":"from ","style":[]},{"kind":"param","name":"start","ref":false},{"kind":"break"},{"kind":"label","text":"of length ","style":[]},{"kind":"param","name":"length","ref":false}],"parameters":[{"kind":"param","name":"this","shadowBlockId":"text","ref":false},{"kind":"param","name":"start","ref":false},{"kind":"param","name":"length","ref":false}]}},"parameters":[{"name":"start","description":"first character index; can be negative from counting from the end, eg:0","default":"0"},{"name":"length","description":"number of characters to extract, eg: 10","initializer":"undefined","default":"10"}],"isInstance":true},"parseFloat":{"kind":-3,"retType":"number","attributes":{"paramDefl":{"text":"123","s":"123"},"help":"text/parse-float","blockId":"string_parsefloat","block":"parse to number %text","blockNamespace":"text","explicitDefaults":["text"],"paramHelp":{"s":"A string to convert into a number. eg: 123"},"jsDoc":"Convert a string to a number.","_def":{"parts":[{"kind":"label","text":"parse to number ","style":[]},{"kind":"param","name":"text","ref":false}],"parameters":[{"kind":"param","name":"text","ref":false}]}},"parameters":[{"name":"text","type":"string","initializer":"123","default":"123"}],"pyQName":"parse_float"},"randint":{"kind":-3,"retType":"number","attributes":{"paramDefl":{"min":"0","max":"10"},"blockId":"device_random","block":"pick random %min|to %limit","blockNamespace":"Math","help":"math/randint","paramHelp":{"min":"the lower inclusive bound, eg: 0","max":"the upper inclusive bound, eg: 10"},"jsDoc":"Returns a pseudorandom number between min and max included.\nIf both numbers are integral, the result is integral.","_def":{"parts":[{"kind":"label","text":"pick random ","style":[]},{"kind":"param","name":"min","ref":false},{"kind":"break"},{"kind":"label","text":"to ","style":[]},{"kind":"param","name":"limit","ref":false}],"parameters":[{"kind":"param","name":"min","ref":false},{"kind":"param","name":"limit","ref":false}]}},"parameters":[{"name":"min","description":"the lower inclusive bound, eg: 0","default":"0"},{"name":"max","description":"the upper inclusive bound, eg: 10","default":"10"}]},"Object":{"kind":5,"retType":""},"Function":{"kind":9,"retType":"Function","extendsTypes":[]},"Function.__assignableToFunction":{"kind":2,"retType":"Function","isInstance":true},"IArguments":{"kind":9,"retType":"IArguments","extendsTypes":[]},"IArguments.__assignableToIArguments":{"kind":2,"retType":"IArguments","isInstance":true},"RegExp":{"kind":9,"retType":"RegExp","extendsTypes":[]},"RegExp.__assignableToRegExp":{"kind":2,"retType":"RegExp","isInstance":true},"Boolean":{"kind":9,"retType":"Boolean","extendsTypes":[]},"Boolean.toString":{"kind":-1,"retType":"string","attributes":{"jsDoc":"Returns a string representation of an object."},"parameters":[],"isInstance":true,"pyQName":"Boolean.to_string"},"String@type":{"kind":9,"retType":"String","attributes":{"blockNamespace":"text","jsDoc":"Combine, split, and search text strings."},"extendsTypes":[],"pyQName":"String"},"String.fromCharCode":{"kind":-3,"retType":"string","attributes":{"help":"math/from-char-code","weight":1,"blockNamespace":"text","blockId":"stringFromCharCode","block":"text from char code %code","jsDoc":"Make a string from the given ASCII character code.","_def":{"parts":[{"kind":"label","text":"text from char code ","style":[]},{"kind":"param","name":"code","ref":false}],"parameters":[{"kind":"param","name":"code","ref":false}]}},"parameters":[{"name":"code"}],"pyQName":"String.from_char_code"},"Number@type":{"kind":9,"retType":"Number","extendsTypes":[],"pyQName":"Number"},"Number.toString":{"kind":-1,"retType":"string","attributes":{"jsDoc":"Returns a string representation of a number."},"parameters":[],"isInstance":true,"pyQName":"Number.to_string"},"Array@type":{"kind":9,"retType":"T[]","attributes":{"blockNamespace":"Arrays","jsDoc":"Add, remove, and replace items in lists."},"extendsTypes":[],"pyQName":"Array"},"Array.isArray":{"kind":-3,"retType":"boolean","attributes":{"jsDoc":"Check if a given object is an array."},"parameters":[{"name":"obj","type":"any"}],"pyQName":"Array.is_array"},"Object@type":{"kind":9,"retType":"Object","extendsTypes":[],"pyQName":"Object"},"Object.keys":{"kind":-3,"retType":"string[]","attributes":{"jsDoc":"Return the field names in an object."},"parameters":[{"name":"obj","type":"any"}]},"Math.pow":{"kind":-3,"retType":"number","attributes":{"paramHelp":{"x":"The base value of the expression.","y":"The exponent value of the expression."},"jsDoc":"Returns the value of a base expression taken to a specified power."},"parameters":[{"name":"x","description":"The base value of the expression."},{"name":"y","description":"The exponent value of the expression."}]},"Math.random":{"kind":-3,"retType":"number","attributes":{"help":"math/random","jsDoc":"Returns a pseudorandom number between 0 and 1."},"parameters":[]},"Math.randomRange":{"kind":-3,"retType":"number","attributes":{"paramDefl":{"min":"0","max":"10"},"blockId":"device_random_deprecated","block":"pick random %min|to %limit","help":"math/random-range","deprecated":"true","paramHelp":{"min":"the lower inclusive bound, eg: 0","max":"the upper inclusive bound, eg: 10"},"jsDoc":"Returns a pseudorandom number between min and max included.\nIf both numbers are integral, the result is integral.","_def":{"parts":[{"kind":"label","text":"pick random ","style":[]},{"kind":"param","name":"min","ref":false},{"kind":"break"},{"kind":"label","text":"to ","style":[]},{"kind":"param","name":"limit","ref":false}],"parameters":[{"kind":"param","name":"min","ref":false},{"kind":"param","name":"limit","ref":false}]}},"parameters":[{"name":"min","description":"the lower inclusive bound, eg: 0","default":"0"},{"name":"max","description":"the upper inclusive bound, eg: 10","default":"10"}],"pyQName":"Math.random_range"},"Math.log":{"kind":-3,"retType":"number","attributes":{"help":"math","paramHelp":{"x":"A number"},"jsDoc":"Returns the natural logarithm (base e) of a number."},"parameters":[{"name":"x","description":"A number"}]},"Math.exp":{"kind":-3,"retType":"number","attributes":{"help":"math","paramHelp":{"x":"A number"},"jsDoc":"Returns returns ``e^x``."},"parameters":[{"name":"x","description":"A number"}]},"Math.sin":{"kind":-3,"retType":"number","attributes":{"help":"math/trigonometry","paramHelp":{"x":"An angle in radians"},"jsDoc":"Returns the sine of a number."},"parameters":[{"name":"x","description":"An angle in radians"}]},"Math.cos":{"kind":-3,"retType":"number","attributes":{"help":"math/trigonometry","paramHelp":{"x":"An angle in radians"},"jsDoc":"Returns the cosine of a number."},"parameters":[{"name":"x","description":"An angle in radians"}]},"Math.tan":{"kind":-3,"retType":"number","attributes":{"help":"math/trigonometry","paramHelp":{"x":"An angle in radians"},"jsDoc":"Returns the tangent of a number."},"parameters":[{"name":"x","description":"An angle in radians"}]},"Math.asin":{"kind":-3,"retType":"number","attributes":{"help":"math/trigonometry","paramHelp":{"x":"A number"},"jsDoc":"Returns the arcsine (in radians) of a number"},"parameters":[{"name":"x","description":"A number"}]},"Math.acos":{"kind":-3,"retType":"number","attributes":{"help":"math/trigonometry","paramHelp":{"x":"A number"},"jsDoc":"Returns the arccosine (in radians) of a number"},"parameters":[{"name":"x","description":"A number"}]},"Math.atan":{"kind":-3,"retType":"number","attributes":{"help":"math/trigonometry","paramHelp":{"x":"A number"},"jsDoc":"Returns the arctangent (in radians) of a number"},"parameters":[{"name":"x","description":"A number"}]},"Math.atan2":{"kind":-3,"retType":"number","attributes":{"help":"math/trigonometry","paramHelp":{"y":"A number","x":"A number"},"jsDoc":"Returns the arctangent of the quotient of its arguments."},"parameters":[{"name":"y","description":"A number"},{"name":"x","description":"A number"}]},"Math.sqrt":{"kind":-3,"retType":"number","attributes":{"help":"math","paramHelp":{"x":"A numeric expression."},"jsDoc":"Returns the square root of a number."},"parameters":[{"name":"x","description":"A numeric expression."}]},"Math.ceil":{"kind":-3,"retType":"number","attributes":{"help":"math","paramHelp":{"x":"A numeric expression."},"jsDoc":"Returns the smallest number greater than or equal to its numeric argument."},"parameters":[{"name":"x","description":"A numeric expression."}]},"Math.floor":{"kind":-3,"retType":"number","attributes":{"help":"math","paramHelp":{"x":"A numeric expression."},"jsDoc":"Returns the greatest number less than or equal to its numeric argument."},"parameters":[{"name":"x","description":"A numeric expression."}]},"Math.trunc":{"kind":-3,"retType":"number","attributes":{"help":"math","paramHelp":{"x":"A numeric expression."},"jsDoc":"Returns the number with the decimal part truncated."},"parameters":[{"name":"x","description":"A numeric expression."}],"pyQName":"int"},"Math.round":{"kind":-3,"retType":"number","attributes":{"help":"math","paramHelp":{"x":"The value to be rounded to the nearest number."},"jsDoc":"Returns a supplied numeric expression rounded to the nearest number."},"parameters":[{"name":"x","description":"The value to be rounded to the nearest number."}]},"Math.imul":{"kind":-3,"retType":"number","attributes":{"help":"math","paramHelp":{"x":"The first number","y":"The second number"},"jsDoc":"Returns the value of integer signed 32 bit multiplication of two numbers."},"parameters":[{"name":"x","description":"The first number"},{"name":"y","description":"The second number"}]},"Math.idiv":{"kind":-3,"retType":"number","attributes":{"help":"math","paramHelp":{"x":"The first number","y":"The second number"},"jsDoc":"Returns the value of integer signed 32 bit division of two numbers."},"parameters":[{"name":"x","description":"The first number"},{"name":"y","description":"The second number"}]},"control._onCodeStart":{"kind":-3,"parameters":[{"name":"arg","type":"any"}],"pyQName":"control._on_code_start"},"control._onCodeStop":{"kind":-3,"parameters":[{"name":"arg","type":"any"}],"pyQName":"control._on_code_stop"},"NaN":{"kind":4,"retType":"number","attributes":{"jsDoc":"Constant representing Not-A-Number."},"pyQName":"na_n"},"Infinity":{"kind":4,"retType":"number","attributes":{"jsDoc":"Constant representing positive infinity."},"pyQName":"infinity"},"isNaN":{"kind":-3,"retType":"boolean","parameters":[{"name":"x"}],"pyQName":"is_na_n"},"Number.isNaN":{"kind":-3,"retType":"boolean","attributes":{"jsDoc":"Check if a given value is of type Number and it is a NaN."},"parameters":[{"name":"x","type":"any"}],"pyQName":"Number.is_na_n"},"StringMap":{"kind":9,"retType":"StringMap","attributes":{"jsDoc":"A dictionary from string key to string values"},"extendsTypes":[]},"parseInt":{"kind":-3,"retType":"number","attributes":{"paramDefl":{"text":"123"},"help":"text/parse-int","blockId":"string_parseint","block":"parse to integer %text","blockNamespace":"text","explicitDefaults":["text"],"blockHidden":true,"paramHelp":{"text":"A string to convert into an integral number. eg: \"123\"","radix":"optional A value between 2 and 36 that specifies the base of the number in text."},"jsDoc":"Convert a string to an integer.\n\n\nIf this argument is not supplied, strings with a prefix of '0x' are considered hexadecimal.\nAll other strings are considered decimal.","_def":{"parts":[{"kind":"label","text":"parse to integer ","style":[]},{"kind":"param","name":"text","ref":false}],"parameters":[{"kind":"param","name":"text","ref":false}]}},"parameters":[{"name":"text","description":"A string to convert into an integral number. eg: \"123\"","type":"string","initializer":"123","default":"123"},{"name":"radix","description":"optional A value between 2 and 36 that specifies the base of the number in text.","initializer":"undefined"}],"pyQName":"int"},"helpers":{"kind":5,"retType":""},"helpers.arrayFill":{"kind":-3,"retType":"T[]","parameters":[{"name":"O","type":"T[]"},{"name":"value","type":"T"},{"name":"start","initializer":"undefined"},{"name":"end","initializer":"undefined"}],"pyQName":"helpers.array_fill"},"helpers.arraySplice":{"kind":-3,"parameters":[{"name":"arr","type":"T[]"},{"name":"start"},{"name":"len"}],"pyQName":"helpers.array_splice"},"helpers.arrayReverse":{"kind":-3,"parameters":[{"name":"arr","type":"T[]"}],"pyQName":"helpers.array_reverse"},"helpers.arrayShift":{"kind":-3,"retType":"T","parameters":[{"name":"arr","type":"T[]"}],"pyQName":"helpers.array_shift"},"helpers.arrayJoin":{"kind":-3,"retType":"string","parameters":[{"name":"arr","type":"T[]"},{"name":"sep","type":"string","initializer":"undefined"}],"pyQName":"helpers.array_join"},"helpers.arrayUnshift":{"kind":-3,"retType":"number","parameters":[{"name":"arr","type":"T[]"},{"name":"value","type":"T"}],"pyQName":"helpers.array_unshift"},"helpers.arraySort":{"kind":-3,"retType":"T[]","parameters":[{"name":"arr","type":"T[]"},{"name":"callbackfn","type":"(value1: T, value2: T) => number","initializer":"undefined","handlerParameters":[{"name":"value1","type":"T"},{"name":"value2","type":"T"}]}],"pyQName":"helpers.array_sort"},"helpers.arrayMap":{"kind":-3,"retType":"U[]","parameters":[{"name":"arr","type":"T[]"},{"name":"callbackfn","type":"(value: T, index: number) => U","handlerParameters":[{"name":"value","type":"T"},{"name":"index","type":"number"}]}],"pyQName":"helpers.array_map"},"helpers.arraySome":{"kind":-3,"retType":"boolean","parameters":[{"name":"arr","type":"T[]"},{"name":"callbackfn","type":"(value: T, index: number) => boolean","handlerParameters":[{"name":"value","type":"T"},{"name":"index","type":"number"}]}],"pyQName":"helpers.array_some"},"helpers.arrayEvery":{"kind":-3,"retType":"boolean","parameters":[{"name":"arr","type":"T[]"},{"name":"callbackfn","type":"(value: T, index: number) => boolean","handlerParameters":[{"name":"value","type":"T"},{"name":"index","type":"number"}]}],"pyQName":"helpers.array_every"},"helpers.arrayForEach":{"kind":-3,"parameters":[{"name":"arr","type":"T[]"},{"name":"callbackfn","type":"(value: T, index: number) => void","handlerParameters":[{"name":"value","type":"T"},{"name":"index","type":"number"}]}],"pyQName":"helpers.array_for_each"},"helpers.arrayFilter":{"kind":-3,"retType":"T[]","parameters":[{"name":"arr","type":"T[]"},{"name":"callbackfn","type":"(value: T, index: number) => boolean","handlerParameters":[{"name":"value","type":"T"},{"name":"index","type":"number"}]}],"pyQName":"helpers.array_filter"},"helpers.arrayFind":{"kind":-3,"retType":"T","parameters":[{"name":"arr","type":"T[]"},{"name":"callbackfn","type":"(value: T, index: number) => boolean","handlerParameters":[{"name":"value","type":"T"},{"name":"index","type":"number"}]}],"pyQName":"helpers.array_find"},"helpers.arrayReduce":{"kind":-3,"retType":"U","parameters":[{"name":"arr","type":"T[]"},{"name":"callbackfn","type":"(previousValue: U, currentValue: T, currentIndex: number) => U","handlerParameters":[{"name":"previousValue","type":"U"},{"name":"currentValue","type":"T"},{"name":"currentIndex","type":"number"}]},{"name":"initialValue","type":"U"}],"pyQName":"helpers.array_reduce"},"helpers.arrayConcat":{"kind":-3,"retType":"T[]","parameters":[{"name":"arr","type":"T[]"},{"name":"otherArr","type":"T[]"}],"pyQName":"helpers.array_concat"},"helpers.arrayPickRandom":{"kind":-3,"retType":"T","parameters":[{"name":"arr","type":"T[]"}],"pyQName":"helpers.array_pick_random"},"helpers.arraySlice":{"kind":-3,"retType":"T[]","parameters":[{"name":"arr","type":"T[]"},{"name":"start","initializer":"undefined"},{"name":"end","initializer":"undefined"}],"pyQName":"helpers.array_slice"},"helpers.stringReplace":{"kind":-3,"retType":"string","parameters":[{"name":"s","type":"string"},{"name":"toReplace","type":"string"},{"name":"replacer","type":"string | ((sub: string) => string)"}],"pyQName":"helpers.string_replace"},"helpers.stringReplaceAll":{"kind":-3,"retType":"string","parameters":[{"name":"s","type":"string"},{"name":"toReplace","type":"string"},{"name":"replacer","type":"string | ((sub: string) => string)"}],"pyQName":"helpers.string_replace_all"},"helpers.stringSubstr":{"kind":-3,"retType":"string","parameters":[{"name":"s","type":"string"},{"name":"start"},{"name":"length","initializer":"undefined"}],"pyQName":"helpers.string_substr"},"helpers.stringSlice":{"kind":-3,"retType":"string","parameters":[{"name":"s","type":"string"},{"name":"start"},{"name":"end","initializer":"undefined"}],"pyQName":"helpers.string_slice"},"helpers.stringToUpperCase":{"kind":-3,"retType":"string","parameters":[{"name":"s","type":"string"}],"pyQName":"helpers.string_to_upper_case"},"helpers.stringToLowerCase":{"kind":-3,"retType":"string","parameters":[{"name":"s","type":"string"}],"pyQName":"helpers.string_to_lower_case"},"helpers.stringSplit":{"kind":-3,"retType":"string[]","parameters":[{"name":"S","type":"string"},{"name":"separator","type":"string","initializer":"undefined"},{"name":"limit","initializer":"undefined"}],"pyQName":"helpers.string_split"},"helpers.stringTrim":{"kind":-3,"retType":"string","parameters":[{"name":"s","type":"string"}],"pyQName":"helpers.string_trim"},"helpers.isWhitespace":{"kind":-3,"retType":"boolean","parameters":[{"name":"c"}],"pyQName":"helpers.is_whitespace"},"helpers.stringEmpty":{"kind":-3,"retType":"boolean","parameters":[{"name":"S","type":"string"}],"pyQName":"helpers.string_empty"},"Math.clamp":{"kind":-3,"retType":"number","parameters":[{"name":"min"},{"name":"max"},{"name":"value"}]},"Math.abs":{"kind":-3,"retType":"number","attributes":{"blockId":"math_op3","help":"math/abs","paramHelp":{"x":"A numeric expression for which the absolute value is needed."},"jsDoc":"Returns the absolute value of a number (the value without regard to whether it is positive or negative).\nFor example, the absolute value of -5 is the same as the absolute value of 5."},"parameters":[{"name":"x","description":"A numeric expression for which the absolute value is needed."}],"pyQName":"abs"},"Math.sign":{"kind":-3,"retType":"number","attributes":{"paramHelp":{"x":"The numeric expression to test"},"jsDoc":"Returns the sign of the x, indicating whether x is positive, negative or zero."},"parameters":[{"name":"x","description":"The numeric expression to test"}]},"Math.max":{"kind":-3,"retType":"number","attributes":{"blockId":"math_op2","help":"math/max","jsDoc":"Returns the larger of two supplied numeric expressions."},"parameters":[{"name":"a"},{"name":"b"}],"pyQName":"max"},"Math.min":{"kind":-3,"retType":"number","attributes":{"blockId":"math_op2","help":"math/min","jsDoc":"Returns the smaller of two supplied numeric expressions."},"parameters":[{"name":"a"},{"name":"b"}],"pyQName":"min"},"Math.roundWithPrecision":{"kind":-3,"retType":"number","attributes":{"paramHelp":{"x":"the number to round","digits":"the number of resulting digits"},"jsDoc":"Rounds ``x`` to a number with the given number of ``digits``"},"parameters":[{"name":"x","description":"the number to round"},{"name":"digits","description":"the number of resulting digits"}],"pyQName":"Math.round_with_precision"},"__internal":{"kind":5,"retType":"","attributes":{"blockHidden":true}},"__internal.__downUp":{"kind":-3,"retType":"boolean","attributes":{"shim":"TD_ID","blockHidden":true,"blockId":"toggleDownUp","block":"%down","paramFieldEditor":{"down":"toggledownup"},"paramFieldEditorOptions":{"down":{"decompileLiterals":"true"}},"jsDoc":"A shim to render a boolean as a down/up toggle","_def":{"parts":[{"kind":"param","name":"down","ref":false}],"parameters":[{"kind":"param","name":"down","ref":false}]}},"parameters":[{"name":"down","type":"boolean"}]},"__internal.__upDown":{"kind":-3,"retType":"boolean","attributes":{"shim":"TD_ID","blockHidden":true,"blockId":"toggleUpDown","block":"%up","paramFieldEditor":{"up":"toggleupdown"},"paramFieldEditorOptions":{"up":{"decompileLiterals":"true"}},"jsDoc":"A shim to render a boolean as a up/down toggle","_def":{"parts":[{"kind":"param","name":"up","ref":false}],"parameters":[{"kind":"param","name":"up","ref":false}]}},"parameters":[{"name":"up","type":"boolean"}]},"__internal.__highLow":{"kind":-3,"retType":"boolean","attributes":{"shim":"TD_ID","blockHidden":true,"blockId":"toggleHighLow","block":"%high","paramFieldEditor":{"high":"togglehighlow"},"paramFieldEditorOptions":{"high":{"decompileLiterals":"true"}},"jsDoc":"A shim to render a boolean as a high/low toggle","_def":{"parts":[{"kind":"param","name":"high","ref":false}],"parameters":[{"kind":"param","name":"high","ref":false}]}},"parameters":[{"name":"high","type":"boolean"}]},"__internal.__onOff":{"kind":-3,"retType":"boolean","attributes":{"shim":"TD_ID","blockHidden":true,"blockId":"toggleOnOff","block":"%on","paramFieldEditor":{"on":"toggleonoff"},"paramFieldEditorOptions":{"on":{"decompileLiterals":"true"}},"jsDoc":"A shim to render a boolean as a on/off toggle","_def":{"parts":[{"kind":"param","name":"on","ref":false}],"parameters":[{"kind":"param","name":"on","ref":false}]}},"parameters":[{"name":"on","type":"boolean"}]},"__internal.__yesNo":{"kind":-3,"retType":"boolean","attributes":{"shim":"TD_ID","blockHidden":true,"blockId":"toggleYesNo","block":"%yes","paramFieldEditor":{"yes":"toggleyesno"},"paramFieldEditorOptions":{"yes":{"decompileLiterals":"true"}},"jsDoc":"A shim to render a boolean as a yes/no toggle","_def":{"parts":[{"kind":"param","name":"yes","ref":false}],"parameters":[{"kind":"param","name":"yes","ref":false}]}},"parameters":[{"name":"yes","type":"boolean"}]},"__internal.__winLose":{"kind":-3,"retType":"boolean","attributes":{"shim":"TD_ID","blockHidden":true,"blockId":"toggleWinLose","block":"%win","paramFieldEditor":{"win":"togglewinlose"},"paramFieldEditorOptions":{"win":{"decompileLiterals":"true"}},"jsDoc":"A shim to render a boolean as a win/lose toggle","_def":{"parts":[{"kind":"param","name":"win","ref":false}],"parameters":[{"kind":"param","name":"win","ref":false}]}},"parameters":[{"name":"win","type":"boolean"}]},"__internal.__colorNumberPicker":{"kind":-3,"retType":"number","attributes":{"paramDefl":{"value":"0xff0000"},"blockId":"colorNumberPicker","block":"%value","blockHidden":true,"shim":"TD_ID","colorSecondary":"#FFFFFF","paramFieldEditor":{"value":"colornumber"},"paramFieldEditorOptions":{"value":{"decompileLiterals":"true","colours":"[\"#ff0000\",\"#ff8000\",\"#ffff00\",\"#ff9da5\",\"#00ff00\",\"#b09eff\",\"#00ffff\",\"#007fff\",\"#65471f\",\"#0000ff\",\"#7f00ff\",\"#ff0080\",\"#ff00ff\",\"#ffffff\",\"#999999\",\"#000000\"]","columns":"4","className":"rgbColorPicker"}},"explicitDefaults":["value"],"paramHelp":{"color":"color"},"jsDoc":"Get the color wheel field editor","_def":{"parts":[{"kind":"param","name":"value","ref":false}],"parameters":[{"kind":"param","name":"value","ref":false}]}},"parameters":[{"name":"value","initializer":"0xff0000","default":"0xff0000"}]},"__internal.__colorWheelPicker":{"kind":-3,"retType":"number","attributes":{"paramDefl":{"value":"10"},"blockId":"colorWheelPicker","block":"%value","blockHidden":true,"shim":"TD_ID","colorSecondary":"#FFFFFF","paramFieldEditor":{"value":"colorwheel"},"paramFieldEditorOptions":{"value":{"decompileLiterals":"true","sliderWidth":"200","min":"0","max":"255"}},"paramHelp":{"value":"value between 0 to 255 to get a color value, eg: 10"},"jsDoc":"Get the color wheel field editor","_def":{"parts":[{"kind":"param","name":"value","ref":false}],"parameters":[{"kind":"param","name":"value","ref":false}]}},"parameters":[{"name":"value","description":"value between 0 to 255 to get a color value, eg: 10","default":"10"}]},"__internal.__colorWheelHsvPicker":{"kind":-3,"retType":"number","attributes":{"paramDefl":{"value":"10"},"blockId":"colorWheelHsvPicker","block":"%value","blockHidden":true,"shim":"TD_ID","colorSecondary":"#FFFFFF","paramFieldEditor":{"value":"colorwheel"},"paramFieldEditorOptions":{"value":{"decompileLiterals":"true","sliderWidth":"200","min":"0","max":"255","channel":"hsvfast"}},"paramHelp":{"value":"value between 0 to 255 to get a color value, eg: 10"},"jsDoc":"Get the color wheel field editor using HSV values","_def":{"parts":[{"kind":"param","name":"value","ref":false}],"parameters":[{"kind":"param","name":"value","ref":false}]}},"parameters":[{"name":"value","description":"value between 0 to 255 to get a color value, eg: 10","default":"10"}]},"__internal.__speedPicker":{"kind":-3,"retType":"number","attributes":{"paramDefl":{"speed":"50"},"blockId":"speedPicker","block":"%speed","shim":"TD_ID","paramFieldEditor":{"speed":"speed"},"colorSecondary":"#FFFFFF","weight":0,"blockHidden":true,"paramFieldEditorOptions":{"speed":{"decompileLiterals":"1"}},"paramHelp":{"speed":"the speed, eg: 50"},"jsDoc":"A speed picker","_def":{"parts":[{"kind":"param","name":"speed","ref":false}],"parameters":[{"kind":"param","name":"speed","ref":false}]}},"parameters":[{"name":"speed","description":"the speed, eg: 50","default":"50"}]},"__internal.__turnRatioPicker":{"kind":-3,"retType":"number","attributes":{"paramDefl":{"turnratio":"0"},"blockId":"turnRatioPicker","block":"%turnratio","shim":"TD_ID","paramFieldEditor":{"turnratio":"turnratio"},"colorSecondary":"#FFFFFF","weight":0,"blockHidden":true,"paramFieldEditorOptions":{"turnRatio":{"decompileLiterals":"1"}},"paramHelp":{"turnratio":"the turn ratio, eg: 0"},"jsDoc":"A turn ratio picker","_def":{"parts":[{"kind":"param","name":"turnratio","ref":false}],"parameters":[{"kind":"param","name":"turnratio","ref":false}]}},"parameters":[{"name":"turnratio","description":"the turn ratio, eg: 0","default":"0"}]},"__internal.__protractor":{"kind":-3,"retType":"number","attributes":{"blockId":"protractorPicker","block":"%angle","shim":"TD_ID","paramFieldEditor":{"angle":"protractor"},"paramFieldEditorOptions":{"angle":{"decompileLiterals":"1"}},"colorSecondary":"#FFFFFF","blockHidden":true,"jsDoc":"A field editor that displays a protractor","_def":{"parts":[{"kind":"param","name":"angle","ref":false}],"parameters":[{"kind":"param","name":"angle","ref":false}]}},"parameters":[{"name":"angle"}]},"__internal.__timePicker":{"kind":-3,"retType":"number","attributes":{"paramDefl":{"ms":"500"},"blockId":"timePicker","block":"%ms","blockHidden":true,"shim":"TD_ID","colorSecondary":"#FFFFFF","paramFieldEditor":{"ms":"numberdropdown"},"paramFieldEditorOptions":{"ms":{"decompileLiterals":"true","data":"[[\"100 ms\", 100], [\"200 ms\", 200], [\"500 ms\", 500], [\"1 second\", 1000], [\"2 seconds\", 2000], [\"5 seconds\", 5000]]"}},"paramHelp":{"ms":"time duration in milliseconds, eg: 500, 1000"},"jsDoc":"Get the time field editor","_def":{"parts":[{"kind":"param","name":"ms","ref":false}],"parameters":[{"kind":"param","name":"ms","ref":false}]}},"parameters":[{"name":"ms","description":"time duration in milliseconds, eg: 500, 1000","default":"500"}]},"Math.randomBoolean":{"kind":-3,"retType":"boolean","attributes":{"blockId":"logic_random","block":"pick random true or false","help":"math/random-boolean","weight":0,"jsDoc":"Generates a `true` or `false` value randomly, just like flipping a coin.","_def":{"parts":[{"kind":"label","text":"pick random true or false","style":[]}],"parameters":[]}},"parameters":[],"pyQName":"Math.random_boolean"},"_py":{"kind":5,"retType":""},"_py.Array":{"kind":9,"retType":"_py.Array","extendsTypes":[]},"_py.Array.append":{"kind":-1,"attributes":{"py2tsOverride":"push($0)"},"parameters":[{"name":"value","type":"any"}],"isInstance":true},"_py.Array.extend":{"kind":-1,"attributes":{"py2tsOverride":"concat($0)"},"parameters":[{"name":"other","type":"_py.Array"}],"isInstance":true},"_py.Array.insert":{"kind":-1,"attributes":{"py2tsOverride":"insertAt($0, $1)"},"parameters":[{"name":"index"},{"name":"value","type":"any"}],"isInstance":true},"_py.Array.remove":{"kind":-1,"attributes":{"py2tsOverride":"removeElement($0)"},"parameters":[{"name":"value","type":"any"}],"isInstance":true},"_py.Array.sort":{"kind":-1,"attributes":{"py2tsOverride":"sort($0?)"},"parameters":[{"name":"sorter","type":"(a: any, b: any) => number","initializer":"undefined","handlerParameters":[{"name":"a","type":"any"},{"name":"b","type":"any"}]}],"isInstance":true},"_py.Array.reverse":{"kind":-1,"attributes":{"py2tsOverride":"reverse()"},"parameters":[],"isInstance":true},"_py.Array.copy":{"kind":-1,"attributes":{"py2tsOverride":"slice()"},"parameters":[],"isInstance":true},"_py.Array.pop":{"kind":-1,"retType":"any","attributes":{"pyHelper":"py_array_pop"},"parameters":[{"name":"index","initializer":"undefined"}],"isInstance":true},"_py.Array.clear":{"kind":-1,"attributes":{"pyHelper":"py_array_clear"},"parameters":[],"isInstance":true},"_py.Array.index":{"kind":-1,"retType":"number","attributes":{"pyHelper":"py_array_index"},"parameters":[{"name":"value","type":"any"},{"name":"start","initializer":"undefined"},{"name":"end","initializer":"undefined"}],"isInstance":true},"_py.Array.count":{"kind":-1,"retType":"number","attributes":{"pyHelper":"py_array_count"},"parameters":[{"name":"value","type":"any"}],"isInstance":true},"_py.String":{"kind":9,"retType":"_py.String","extendsTypes":[]},"_py.String.capitalize":{"kind":-1,"retType":"string","attributes":{"pyHelper":"py_string_capitalize"},"parameters":[],"isInstance":true},"_py.String.casefold":{"kind":-1,"retType":"string","attributes":{"pyHelper":"py_string_casefold"},"parameters":[],"isInstance":true},"_py.String.center":{"kind":-1,"retType":"string","attributes":{"pyHelper":"py_string_center"},"parameters":[{"name":"width"},{"name":"fillChar","type":"string","initializer":"undefined"}],"isInstance":true},"_py.String.count":{"kind":-1,"retType":"number","attributes":{"pyHelper":"py_string_count"},"parameters":[{"name":"sub","type":"string"},{"name":"start","initializer":"undefined"},{"name":"end","initializer":"undefined"}],"isInstance":true},"_py.String.endswith":{"kind":-1,"retType":"boolean","attributes":{"pyHelper":"py_string_endswith"},"parameters":[{"name":"suffix","type":"string"},{"name":"start","initializer":"undefined"},{"name":"end","initializer":"undefined"}],"isInstance":true},"_py.String.find":{"kind":-1,"retType":"number","attributes":{"pyHelper":"py_string_find"},"parameters":[{"name":"sub","type":"string"},{"name":"start","initializer":"undefined"},{"name":"end","initializer":"undefined"}],"isInstance":true},"_py.String.index":{"kind":-1,"retType":"number","attributes":{"pyHelper":"py_string_index"},"parameters":[{"name":"sub","type":"string"},{"name":"start","initializer":"undefined"},{"name":"end","initializer":"undefined"}],"isInstance":true},"_py.String.isalnum":{"kind":-1,"retType":"boolean","attributes":{"pyHelper":"py_string_isalnum"},"parameters":[],"isInstance":true},"_py.String.isalpha":{"kind":-1,"retType":"boolean","attributes":{"pyHelper":"py_string_isalpha"},"parameters":[],"isInstance":true},"_py.String.isascii":{"kind":-1,"retType":"boolean","attributes":{"pyHelper":"py_string_isascii"},"parameters":[],"isInstance":true},"_py.String.isdigit":{"kind":-1,"retType":"boolean","attributes":{"pyHelper":"py_string_isdigit"},"parameters":[],"isInstance":true},"_py.String.isnumeric":{"kind":-1,"retType":"boolean","attributes":{"pyHelper":"py_string_isnumeric"},"parameters":[],"isInstance":true},"_py.String.isspace":{"kind":-1,"retType":"boolean","attributes":{"pyHelper":"py_string_isspace"},"parameters":[],"isInstance":true},"_py.String.isdecimal":{"kind":-1,"retType":"boolean","attributes":{"pyHelper":"py_string_isdecimal"},"parameters":[],"isInstance":true},"_py.String.isidentifier":{"kind":-1,"retType":"boolean","attributes":{"pyHelper":"py_string_isidentifier"},"parameters":[],"isInstance":true},"_py.String.islower":{"kind":-1,"retType":"boolean","attributes":{"pyHelper":"py_string_islower"},"parameters":[],"isInstance":true},"_py.String.isprintable":{"kind":-1,"retType":"boolean","attributes":{"pyHelper":"py_string_isprintable"},"parameters":[],"isInstance":true},"_py.String.istitle":{"kind":-1,"retType":"boolean","attributes":{"pyHelper":"py_string_istitle"},"parameters":[],"isInstance":true},"_py.String.isupper":{"kind":-1,"retType":"boolean","attributes":{"pyHelper":"py_string_isupper"},"parameters":[],"isInstance":true},"_py.String.join":{"kind":-1,"retType":"string","attributes":{"pyHelper":"py_string_join"},"parameters":[{"name":"iterable","type":"any[]"}],"isInstance":true},"_py.String.ljust":{"kind":-1,"retType":"string","attributes":{"pyHelper":"py_string_ljust"},"parameters":[{"name":"width"},{"name":"fillChar","type":"string","initializer":"undefined"}],"isInstance":true},"_py.String.lower":{"kind":-1,"retType":"string","attributes":{"pyHelper":"py_string_lower"},"parameters":[],"isInstance":true},"_py.String.lstrip":{"kind":-1,"retType":"string","attributes":{"pyHelper":"py_string_lstrip"},"parameters":[{"name":"chars","type":"string","initializer":"undefined"}],"isInstance":true},"_py.String.replace":{"kind":-1,"retType":"string","attributes":{"py2tsOverride":"replace($0, $1)"},"parameters":[{"name":"oldString","type":"string"},{"name":"newString","type":"string"}],"isInstance":true},"_py.String.rfind":{"kind":-1,"retType":"number","attributes":{"pyHelper":"py_string_rfind"},"parameters":[{"name":"sub","type":"string"},{"name":"start","initializer":"undefined"},{"name":"end","initializer":"undefined"}],"isInstance":true},"_py.String.rindex":{"kind":-1,"retType":"number","attributes":{"pyHelper":"py_string_rindex"},"parameters":[{"name":"sub","type":"string"},{"name":"start","initializer":"undefined"},{"name":"end","initializer":"undefined"}],"isInstance":true},"_py.String.rjust":{"kind":-1,"retType":"string","attributes":{"pyHelper":"py_string_rjust"},"parameters":[{"name":"width"},{"name":"fillChar","type":"string","initializer":"undefined"}],"isInstance":true},"_py.String.rsplit":{"kind":-1,"retType":"string[]","attributes":{"pyHelper":"py_string_rsplit"},"parameters":[{"name":"sep","type":"string","initializer":"undefined"},{"name":"maxSplit","initializer":"undefined"}],"isInstance":true},"_py.String.rstrip":{"kind":-1,"retType":"string","attributes":{"pyHelper":"py_string_rstrip"},"parameters":[{"name":"chars","type":"string","initializer":"undefined"}],"isInstance":true},"_py.String.split":{"kind":-1,"retType":"string[]","attributes":{"pyHelper":"py_string_split"},"parameters":[{"name":"sep","type":"string","initializer":"undefined"},{"name":"maxsplit","initializer":"undefined"}],"isInstance":true},"_py.String.splitlines":{"kind":-1,"retType":"string[]","attributes":{"pyHelper":"py_string_splitlines"},"parameters":[{"name":"keepends","type":"boolean","initializer":"undefined"}],"isInstance":true},"_py.String.startswith":{"kind":-1,"retType":"boolean","attributes":{"pyHelper":"py_string_startswith"},"parameters":[{"name":"prefix","type":"string"},{"name":"start","initializer":"undefined"},{"name":"end","initializer":"undefined"}],"isInstance":true},"_py.String.strip":{"kind":-1,"retType":"string","attributes":{"pyHelper":"py_string_strip"},"parameters":[{"name":"chars","type":"string","initializer":"undefined"}],"isInstance":true},"_py.String.swapcase":{"kind":-1,"retType":"string","attributes":{"pyHelper":"py_string_swapcase"},"parameters":[],"isInstance":true},"_py.String.title":{"kind":-1,"retType":"string","attributes":{"pyHelper":"py_string_title"},"parameters":[],"isInstance":true},"_py.String.upper":{"kind":-1,"retType":"string","attributes":{"pyHelper":"py_string_upper"},"parameters":[],"isInstance":true},"_py.String.zfill":{"kind":-1,"retType":"string","attributes":{"pyHelper":"py_string_zfill"},"parameters":[{"name":"width"}],"isInstance":true},"_py.Dict":{"kind":9,"retType":"_py.Dict","extendsTypes":[]},"_py.Dict.clear":{"kind":-1,"parameters":[],"isInstance":true},"_py.Dict.copy":{"kind":-1,"parameters":[],"isInstance":true},"_py.Dict.get":{"kind":-1,"retType":"any","parameters":[{"name":"key","type":"string"},{"name":"defaultValue","type":"any","initializer":"undefined"}],"isInstance":true},"_py.Dict.keys":{"kind":-1,"retType":"string[]","parameters":[],"isInstance":true},"_py.Dict.pop":{"kind":-1,"retType":"any","parameters":[{"name":"key","type":"string"},{"name":"defaultValue","type":"any","initializer":"undefined"}],"isInstance":true},"_py.Dict.setdefault":{"kind":-1,"retType":"any","parameters":[{"name":"key","type":"string"},{"name":"defaultValue","type":"any","initializer":"undefined"}],"isInstance":true},"_py.Dict.update":{"kind":-1,"parameters":[{"name":"other","type":"_py.Dict"}],"isInstance":true},"_py.Dict.values":{"kind":-1,"retType":"any[]","parameters":[],"isInstance":true},"_py.Set":{"kind":9,"retType":"_py.Set","extendsTypes":[]},"_py.Set.isdisjoint":{"kind":-1,"retType":"boolean","parameters":[{"name":"other","type":"_py.Set"}],"isInstance":true},"_py.Set.issubset":{"kind":-1,"retType":"boolean","parameters":[{"name":"other","type":"_py.Set"}],"isInstance":true},"_py.Set.issuperset":{"kind":-1,"retType":"boolean","parameters":[{"name":"other","type":"_py.Set"}],"isInstance":true},"_py.Set.union":{"kind":-1,"retType":"_py.Set","parameters":[{"name":"other","type":"_py.Set"}],"isInstance":true},"_py.Set.intersection":{"kind":-1,"retType":"_py.Set","parameters":[{"name":"other","type":"_py.Set"}],"isInstance":true},"_py.Set.difference":{"kind":-1,"retType":"_py.Set","parameters":[{"name":"other","type":"_py.Set"}],"isInstance":true},"_py.Set.symmetric_difference":{"kind":-1,"retType":"_py.Set","parameters":[{"name":"other","type":"_py.Set"}],"isInstance":true},"_py.Set.copy":{"kind":-1,"retType":"_py.Set","parameters":[],"isInstance":true},"_py.Set.update":{"kind":-1,"parameters":[{"name":"other","type":"_py.Set"}],"isInstance":true},"_py.Set.intersection_update":{"kind":-1,"parameters":[{"name":"other","type":"_py.Set"}],"isInstance":true},"_py.Set.difference_update":{"kind":-1,"parameters":[{"name":"other","type":"_py.Set"}],"isInstance":true},"_py.Set.symmetric_difference_update":{"kind":-1,"parameters":[{"name":"other","type":"_py.Set"}],"isInstance":true},"_py.Set.add":{"kind":-1,"parameters":[{"name":"elem","type":"any"}],"isInstance":true},"_py.Set.remove":{"kind":-1,"parameters":[{"name":"elem","type":"any"}],"isInstance":true},"_py.Set.discard":{"kind":-1,"parameters":[{"name":"elem","type":"any"}],"isInstance":true},"_py.Set.pop":{"kind":-1,"retType":"any","parameters":[],"isInstance":true},"_py.Set.clear":{"kind":-1,"parameters":[],"isInstance":true},"_py.ATTRIBUTE_ERROR":{"kind":4,"retType":"string"},"_py.INDEX_ERROR":{"kind":4,"retType":"string"},"_py.VALUE_ERROR":{"kind":4,"retType":"string"},"_py.TYPE_ERROR":{"kind":4,"retType":"string"},"_py.py_string_capitalize":{"kind":-3,"retType":"string","parameters":[{"name":"str","type":"string"}]},"_py.py_string_casefold":{"kind":-3,"retType":"string","parameters":[{"name":"str","type":"string"}]},"_py.py_string_center":{"kind":-3,"retType":"string","parameters":[{"name":"str","type":"string"},{"name":"width"},{"name":"fillChar","type":"string","initializer":"undefined"}]},"_py.py_string_count":{"kind":-3,"retType":"number","parameters":[{"name":"str","type":"string"},{"name":"sub","type":"string"},{"name":"start","initializer":"undefined"},{"name":"end","initializer":"undefined"}]},"_py.py_string_endswith":{"kind":-3,"retType":"boolean","parameters":[{"name":"str","type":"string"},{"name":"suffix","type":"string"},{"name":"start","initializer":"undefined"},{"name":"end","initializer":"undefined"}]},"_py.py_string_find":{"kind":-3,"retType":"number","parameters":[{"name":"str","type":"string"},{"name":"sub","type":"string"},{"name":"start","initializer":"undefined"},{"name":"end","initializer":"undefined"}]},"_py.py_string_index":{"kind":-3,"retType":"number","parameters":[{"name":"str","type":"string"},{"name":"sub","type":"string"},{"name":"start","initializer":"undefined"},{"name":"end","initializer":"undefined"}]},"_py.py_string_isalnum":{"kind":-3,"retType":"boolean","parameters":[{"name":"str","type":"string"}]},"_py.py_string_isalpha":{"kind":-3,"retType":"boolean","parameters":[{"name":"str","type":"string"}]},"_py.py_string_isascii":{"kind":-3,"retType":"boolean","parameters":[{"name":"str","type":"string"}]},"_py.py_string_isdigit":{"kind":-3,"retType":"boolean","parameters":[{"name":"str","type":"string"}]},"_py.py_string_isnumeric":{"kind":-3,"retType":"boolean","parameters":[{"name":"str","type":"string"}]},"_py.py_string_isspace":{"kind":-3,"retType":"boolean","parameters":[{"name":"str","type":"string"}]},"_py.py_string_isdecimal":{"kind":-3,"retType":"boolean","parameters":[{"name":"str","type":"string"}]},"_py.py_string_isidentifier":{"kind":-3,"retType":"boolean","parameters":[{"name":"str","type":"string"}]},"_py.py_string_islower":{"kind":-3,"retType":"boolean","parameters":[{"name":"str","type":"string"}]},"_py.py_string_isprintable":{"kind":-3,"retType":"boolean","parameters":[{"name":"str","type":"string"}]},"_py.py_string_istitle":{"kind":-3,"retType":"boolean","parameters":[{"name":"str","type":"string"}]},"_py.py_string_isupper":{"kind":-3,"retType":"boolean","parameters":[{"name":"str","type":"string"}]},"_py.py_string_join":{"kind":-3,"retType":"string","parameters":[{"name":"str","type":"string"},{"name":"iterable","type":"any[]"}]},"_py.py_string_ljust":{"kind":-3,"retType":"string","parameters":[{"name":"str","type":"string"},{"name":"width"},{"name":"fillChar","type":"string","initializer":"undefined"}]},"_py.py_string_lower":{"kind":-3,"retType":"string","parameters":[{"name":"str","type":"string"}]},"_py.py_string_rfind":{"kind":-3,"retType":"number","parameters":[{"name":"str","type":"string"},{"name":"sub","type":"string"},{"name":"start","initializer":"undefined"},{"name":"end","initializer":"undefined"}]},"_py.py_string_rindex":{"kind":-3,"retType":"number","parameters":[{"name":"str","type":"string"},{"name":"sub","type":"string"},{"name":"start","initializer":"undefined"},{"name":"end","initializer":"undefined"}]},"_py.py_string_rjust":{"kind":-3,"retType":"string","parameters":[{"name":"str","type":"string"},{"name":"width"},{"name":"fillChar","type":"string","initializer":"undefined"}]},"_py.py_string_rsplit":{"kind":-3,"retType":"string[]","parameters":[{"name":"str","type":"string"},{"name":"sep","type":"string","initializer":"undefined"},{"name":"maxsplit","initializer":"undefined"}]},"_py.py_string_split":{"kind":-3,"retType":"string[]","parameters":[{"name":"str","type":"string"},{"name":"sep","type":"string","initializer":"undefined"},{"name":"maxsplit","initializer":"undefined"}]},"_py.py_string_splitlines":{"kind":-3,"retType":"string[]","parameters":[{"name":"str","type":"string"},{"name":"keepends","type":"boolean","initializer":"undefined"}]},"_py.py_string_startswith":{"kind":-3,"retType":"boolean","parameters":[{"name":"str","type":"string"},{"name":"prefix","type":"string"},{"name":"start","initializer":"undefined"},{"name":"end","initializer":"undefined"}]},"_py.py_string_rstrip":{"kind":-3,"retType":"string","parameters":[{"name":"str","type":"string"},{"name":"chars","type":"string","initializer":"undefined"}]},"_py.py_string_lstrip":{"kind":-3,"retType":"string","parameters":[{"name":"str","type":"string"},{"name":"chars","type":"string","initializer":"undefined"}]},"_py.py_string_strip":{"kind":-3,"retType":"string","parameters":[{"name":"str","type":"string"},{"name":"chars","type":"string","initializer":"undefined"}]},"_py.py_string_swapcase":{"kind":-3,"retType":"string","parameters":[{"name":"str","type":"string"}]},"_py.py_string_title":{"kind":-3,"retType":"string","parameters":[{"name":"str","type":"string"}]},"_py.py_string_upper":{"kind":-3,"retType":"string","parameters":[{"name":"str","type":"string"}]},"_py.py_string_zfill":{"kind":-3,"retType":"string","parameters":[{"name":"str","type":"string"},{"name":"width"}]},"_py.py_array_pop":{"kind":-3,"retType":"any","parameters":[{"name":"arr","type":"any[]"},{"name":"index","initializer":"undefined"}]},"_py.py_array_clear":{"kind":-3,"parameters":[{"name":"arr","type":"any[]"}]},"_py.py_array_index":{"kind":-3,"retType":"number","parameters":[{"name":"arr","type":"any[]"},{"name":"value","type":"any"},{"name":"start","initializer":"undefined"},{"name":"end","initializer":"undefined"}]},"_py.py_array_count":{"kind":-3,"retType":"number","parameters":[{"name":"arr","type":"any[]"},{"name":"value","type":"any"}]},"_py.range":{"kind":-3,"retType":"number[]","attributes":{"paramHelp":{"first":"The value to end the sequence before. This value will not show up in the result.","stop":"The value to end the sequence before. This value will not show up in the result","step":"The value to increase or decrease by for each step in the range. Must be a nonzero integer"},"jsDoc":"Returns a sequence of numbers up to but not including the limit\n\nIf more than one argument is passed, this argument is instead used for the first value in the range"},"parameters":[{"name":"first","description":"The value to end the sequence before. This value will not show up in the result."},{"name":"stop","description":"The value to end the sequence before. This value will not show up in the result","initializer":"undefined"},{"name":"step","description":"The value to increase or decrease by for each step in the range. Must be a nonzero integer","initializer":"undefined"}],"pyQName":"range"},"_py.slice":{"kind":-3,"retType":"U[]","attributes":{"jsDoc":"Returns a section of an array according to python's extended slice syntax"},"parameters":[{"name":"value","type":"U[]"},{"name":"start","initializer":"undefined"},{"name":"stop","initializer":"undefined"},{"name":"step","initializer":"undefined"}]},"_py.stringSlice":{"kind":-3,"retType":"string","attributes":{"jsDoc":"Returns a section of a string according to python's extended slice syntax"},"parameters":[{"name":"value","type":"string"},{"name":"start","initializer":"undefined"},{"name":"stop","initializer":"undefined"},{"name":"step","initializer":"undefined"}],"pyQName":"_py.string_slice"},"PinEvent":{"kind":6,"retType":"PinEvent","extendsTypes":["PinEvent","Number"]},"PinEvent.PulseHigh":{"retType":"PinEvent","attributes":{"block":"pulse high","_def":{"parts":[{"kind":"label","text":"pulse high","style":[]}],"parameters":[]}},"extendsTypes":["PinEvent.PulseHigh","Number"],"pyQName":"PinEvent.PULSE_HIGH"},"PinEvent.PulseLow":{"retType":"PinEvent","attributes":{"block":"pulse low","_def":{"parts":[{"kind":"label","text":"pulse low","style":[]}],"parameters":[]}},"extendsTypes":["PinEvent.PulseLow","Number"],"pyQName":"PinEvent.PULSE_LOW"},"PinEvent.Rise":{"retType":"PinEvent","attributes":{"block":"rise","_def":{"parts":[{"kind":"label","text":"rise","style":[]}],"parameters":[]}},"extendsTypes":["PinEvent.Rise","Number"],"pyQName":"PinEvent.RISE"},"PinEvent.Fall":{"retType":"PinEvent","attributes":{"block":"fall","_def":{"parts":[{"kind":"label","text":"fall","style":[]}],"parameters":[]}},"extendsTypes":["PinEvent.Fall","Number"],"pyQName":"PinEvent.FALL"},"AnalogReadWritePin":{"kind":6,"retType":"AnalogReadWritePin","extendsTypes":["AnalogReadWritePin","Number"]},"AnalogReadWritePin.P0":{"retType":"AnalogReadWritePin","attributes":{"blockIdentity":"pins._analogReadWritePinShadow"},"extendsTypes":["AnalogReadWritePin.P0","Number"]},"AnalogReadWritePin.P1":{"retType":"AnalogReadWritePin","attributes":{"blockIdentity":"pins._analogReadWritePinShadow"},"extendsTypes":["AnalogReadWritePin.P1","Number"]},"AnalogReadWritePin.P2":{"retType":"AnalogReadWritePin","attributes":{"blockIdentity":"pins._analogReadWritePinShadow"},"extendsTypes":["AnalogReadWritePin.P2","Number"]},"AnalogReadWritePin.P3":{"retType":"AnalogReadWritePin","attributes":{"blockIdentity":"pins._analogReadWritePinShadow"},"extendsTypes":["AnalogReadWritePin.P3","Number"]},"AnalogReadWritePin.P4":{"retType":"AnalogReadWritePin","attributes":{"blockIdentity":"pins._analogReadWritePinShadow"},"extendsTypes":["AnalogReadWritePin.P4","Number"]},"AnalogReadWritePin.P10":{"retType":"AnalogReadWritePin","attributes":{"blockIdentity":"pins._analogReadWritePinShadow"},"extendsTypes":["AnalogReadWritePin.P10","Number"]},"DigitalInOutPin":{"kind":9,"retType":"DigitalInOutPin","attributes":{"noRefCounting":"true","fixedInstances":"true"},"extendsTypes":["DigitalInOutPin"]},"DigitalInOutPin.digitalRead":{"kind":-1,"retType":"boolean","parameters":[],"isInstance":true,"pyQName":"DigitalInOutPin.digital_read"},"DigitalInOutPin.digitalWrite":{"kind":-1,"parameters":[{"name":"value","type":"boolean"}],"isInstance":true,"pyQName":"DigitalInOutPin.digital_write"},"DigitalInOutPin.onPulsed":{"kind":-1,"parameters":[{"name":"pulse","type":"PulseValue","isEnum":true},{"name":"body","type":"() => void","handlerParameters":[]}],"isInstance":true,"pyQName":"DigitalInOutPin.on_pulsed"},"DigitalInOutPin.onEvent":{"kind":-1,"parameters":[{"name":"event","type":"PinEvent","isEnum":true},{"name":"body","type":"() => void","handlerParameters":[]}],"isInstance":true,"pyQName":"DigitalInOutPin.on_event"},"DigitalInOutPin.pulseIn":{"kind":-1,"retType":"number","parameters":[{"name":"value","type":"PulseValue","isEnum":true},{"name":"maxDuration","initializer":"undefined"}],"isInstance":true,"pyQName":"DigitalInOutPin.pulse_in"},"DigitalInOutPin.setPull":{"kind":-1,"parameters":[{"name":"pull","type":"PinPullMode","isEnum":true}],"isInstance":true,"pyQName":"DigitalInOutPin.set_pull"},"AnalogInPin":{"kind":9,"retType":"AnalogInPin","attributes":{"noRefCounting":"true","fixedInstances":"true"},"extendsTypes":["AnalogInPin","DigitalInOutPin"]},"AnalogInPin.analogRead":{"kind":-1,"retType":"number","parameters":[],"isInstance":true,"pyQName":"AnalogInPin.analog_read"},"AnalogOutPin":{"kind":9,"retType":"AnalogOutPin","attributes":{"noRefCounting":"true","fixedInstances":"true"},"extendsTypes":["AnalogOutPin","DigitalInOutPin"]},"AnalogOutPin.analogWrite":{"kind":-1,"parameters":[{"name":"value"}],"isInstance":true,"pyQName":"AnalogOutPin.analog_write"},"AnalogInOutPin":{"kind":9,"retType":"AnalogInOutPin","attributes":{"noRefCounting":"true","fixedInstances":"true"},"extendsTypes":["AnalogInOutPin","AnalogInPin","DigitalInOutPin","AnalogOutPin"]},"PwmOnlyPin":{"kind":9,"retType":"PwmOnlyPin","attributes":{"noRefCounting":"true","fixedInstances":"true"},"extendsTypes":["PwmOnlyPin","DigitalInOutPin","AnalogOutPin"]},"PwmOnlyPin.analogSetPeriod":{"kind":-1,"attributes":{"parts":"microservo","trackArgs":[0]},"parameters":[{"name":"period"}],"isInstance":true,"pyQName":"PwmOnlyPin.analog_set_period"},"PwmOnlyPin.servoWrite":{"kind":-1,"attributes":{"parts":"microservo","trackArgs":[0]},"parameters":[{"name":"value"}],"isInstance":true,"pyQName":"PwmOnlyPin.servo_write"},"PwmOnlyPin.servoSetPulse":{"kind":-1,"attributes":{"parts":"microservo","trackArgs":[0]},"parameters":[{"name":"duration"}],"isInstance":true,"pyQName":"PwmOnlyPin.servo_set_pulse"},"PwmOnlyPin.servoSetContinuous":{"kind":-1,"attributes":{"parts":"microservo","tracArgs":"0"},"parameters":[{"name":"value","type":"boolean"}],"isInstance":true,"pyQName":"PwmOnlyPin.servo_set_continuous"},"PwmPin":{"kind":9,"retType":"PwmPin","attributes":{"noRefCounting":"true","fixedInstances":"true"},"extendsTypes":["PwmPin","PwmOnlyPin","DigitalInOutPin","AnalogOutPin","AnalogInPin"]},"MicrobitPin":{"kind":8,"retType":"MicrobitPin","attributes":{"noRefCounting":"true","fixedInstances":"true"},"extendsTypes":["MicrobitPin","AnalogInPin","DigitalInOutPin","AnalogOutPin","AnalogInOutPin","PwmOnlyPin"]},"MicrobitPin.id":{"kind":2,"retType":"number","isInstance":true},"MicrobitPin.__constructor":{"kind":-3,"parameters":[{"name":"id"}],"isInstance":true},"MicrobitPin.digitalRead":{"kind":-1,"retType":"boolean","parameters":[],"isInstance":true,"pyQName":"MicrobitPin.digital_read"},"MicrobitPin.digitalWrite":{"kind":-1,"parameters":[{"name":"value","type":"boolean"}],"isInstance":true,"pyQName":"MicrobitPin.digital_write"},"MicrobitPin.onPulsed":{"kind":-1,"parameters":[{"name":"pulse","type":"PulseValue","isEnum":true},{"name":"body","type":"() => void","handlerParameters":[]}],"isInstance":true,"pyQName":"MicrobitPin.on_pulsed"},"MicrobitPin.onEvent":{"kind":-1,"parameters":[{"name":"event","type":"PinEvent","isEnum":true},{"name":"body","type":"() => void","handlerParameters":[]}],"isInstance":true,"pyQName":"MicrobitPin.on_event"},"MicrobitPin.pulseIn":{"kind":-1,"retType":"number","parameters":[{"name":"value","type":"PulseValue","isEnum":true},{"name":"maxDuration","initializer":"undefined"}],"isInstance":true,"pyQName":"MicrobitPin.pulse_in"},"MicrobitPin.setPull":{"kind":-1,"parameters":[{"name":"pull","type":"PinPullMode","isEnum":true}],"isInstance":true,"pyQName":"MicrobitPin.set_pull"},"MicrobitPin.analogRead":{"kind":-1,"retType":"number","parameters":[],"isInstance":true,"pyQName":"MicrobitPin.analog_read"},"MicrobitPin.analogWrite":{"kind":-1,"parameters":[{"name":"value"}],"isInstance":true,"pyQName":"MicrobitPin.analog_write"},"MicrobitPin.analogSetPeriod":{"kind":-1,"parameters":[{"name":"period"}],"isInstance":true,"pyQName":"MicrobitPin.analog_set_period"},"MicrobitPin.servoWrite":{"kind":-1,"parameters":[{"name":"value"}],"isInstance":true,"pyQName":"MicrobitPin.servo_write"},"MicrobitPin.servoSetContinuous":{"kind":-1,"parameters":[{"name":"value","type":"boolean"}],"isInstance":true,"pyQName":"MicrobitPin.servo_set_continuous"},"MicrobitPin.servoSetPulse":{"kind":-1,"parameters":[{"name":"duration"}],"isInstance":true,"pyQName":"MicrobitPin.servo_set_pulse"},"pins.P0":{"kind":4,"retType":"PwmPin","attributes":{"fixedInstance":"true","whenUsed":"true","jsDoc":"Pin P0"}},"pins.P1":{"kind":4,"retType":"PwmPin","attributes":{"fixedInstance":"true","whenUsed":"true","jsDoc":"Pin P1"}},"pins.P2":{"kind":4,"retType":"PwmPin","attributes":{"fixedInstance":"true","whenUsed":"true","jsDoc":"Pin P2"}},"pins.P3":{"kind":4,"retType":"AnalogInPin","attributes":{"fixedInstance":"true","whenUsed":"true","jsDoc":"Pin P3"}},"pins.P4":{"kind":4,"retType":"AnalogInPin","attributes":{"fixedInstance":"true","whenUsed":"true","jsDoc":"Pin P4"}},"pins.P5":{"kind":4,"retType":"DigitalInOutPin","attributes":{"fixedInstance":"true","whenUsed":"true","jsDoc":"Pin P5"}},"pins.P6":{"kind":4,"retType":"DigitalInOutPin","attributes":{"fixedInstance":"true","whenUsed":"true","jsDoc":"Pin P6"}},"pins.P7":{"kind":4,"retType":"DigitalInOutPin","attributes":{"fixedInstance":"true","whenUsed":"true","jsDoc":"Pin P7"}},"pins.P8":{"kind":4,"retType":"DigitalInOutPin","attributes":{"fixedInstance":"true","whenUsed":"true","jsDoc":"Pin P8"}},"pins.P9":{"kind":4,"retType":"DigitalInOutPin","attributes":{"fixedInstance":"true","whenUsed":"true","jsDoc":"Pin P9"}},"pins.P10":{"kind":4,"retType":"AnalogInPin","attributes":{"fixedInstance":"true","whenUsed":"true","jsDoc":"Pin P10"}},"pins.P11":{"kind":4,"retType":"DigitalInOutPin","attributes":{"fixedInstance":"true","whenUsed":"true","jsDoc":"Pin P3"}},"pins.P12":{"kind":4,"retType":"DigitalInOutPin","attributes":{"fixedInstance":"true","whenUsed":"true","jsDoc":"Pin P12"}},"pins.P13":{"kind":4,"retType":"DigitalInOutPin","attributes":{"fixedInstance":"true","whenUsed":"true","jsDoc":"Pin P13"}},"pins.P14":{"kind":4,"retType":"DigitalInOutPin","attributes":{"fixedInstance":"true","whenUsed":"true","jsDoc":"Pin P14"}},"pins.P15":{"kind":4,"retType":"DigitalInOutPin","attributes":{"fixedInstance":"true","whenUsed":"true","jsDoc":"Pin P15"}},"pins.P16":{"kind":4,"retType":"DigitalInOutPin","attributes":{"fixedInstance":"true","whenUsed":"true","jsDoc":"Pin P16"}},"pins.P19":{"kind":4,"retType":"DigitalInOutPin","attributes":{"fixedInstance":"true","whenUsed":"true","jsDoc":"Pin P19"}},"pins.P20":{"kind":4,"retType":"DigitalInOutPin","attributes":{"fixedInstance":"true","whenUsed":"true","jsDoc":"Pin P19"}},"basic.showNumber":{"kind":-3,"attributes":{"paramDefl":{"interval":"150"},"callingConvention":1,"help":"basic/show-number","weight":96,"blockId":"device_show_number","block":"show|number %number","blockGap":"8","async":"true","parts":"ledmatrix","explicitDefaults":["interval"],"paramHelp":{"interval":"speed of scroll; eg: 150, 100, 200, -100"},"jsDoc":"Scroll a number on the screen. If the number fits on the screen (i.e. is a single digit), do not scroll.","_def":{"parts":[{"kind":"label","text":"show","style":[]},{"kind":"break"},{"kind":"label","text":"number ","style":[]},{"kind":"param","name":"number","ref":false}],"parameters":[{"kind":"param","name":"number","ref":false}]}},"parameters":[{"name":"value"},{"name":"interval","description":"speed of scroll; eg: 150, 100, 200, -100","initializer":"150","default":"150"}],"pyQName":"basic.show_number"},"pause":{"kind":-3,"attributes":{"paramDefl":{"ms":"100"},"paramHelp":{"ms":"how long to pause for, eg: 100, 200, 500, 1000, 2000"},"jsDoc":"Pause for the specified time in milliseconds"},"parameters":[{"name":"ms","description":"how long to pause for, eg: 100, 200, 500, 1000, 2000","default":"100"}]},"forever":{"kind":-3,"attributes":{"paramHelp":{"body":"code to execute"},"jsDoc":"Repeats the code forever in the background. On each iteration, allows other codes to run."},"parameters":[{"name":"a","type":"() => void","handlerParameters":[]}]},"IconNames":{"kind":6,"retType":"IconNames","extendsTypes":["IconNames","Number"]},"IconNames.Heart":{"retType":"IconNames.Heart","attributes":{"block":"heart","jres":"icons.heart","whenUsed":true,"_def":{"parts":[{"kind":"label","text":"heart","style":[]}],"parameters":[]}},"extendsTypes":["IconNames.Heart","Number"],"pyQName":"IconNames.HEART"},"IconNames.SmallHeart":{"retType":"IconNames.SmallHeart","attributes":{"block":"small heart","jres":"icons.smallheart","whenUsed":true,"_def":{"parts":[{"kind":"label","text":"small heart","style":[]}],"parameters":[]}},"extendsTypes":["IconNames.SmallHeart","Number"],"pyQName":"IconNames.SMALL_HEART"},"IconNames.Yes":{"retType":"IconNames.Yes","attributes":{"block":"yes","jres":"icons.yes","whenUsed":true,"_def":{"parts":[{"kind":"label","text":"yes","style":[]}],"parameters":[]}},"extendsTypes":["IconNames.Yes","Number"],"pyQName":"IconNames.YES"},"IconNames.No":{"retType":"IconNames.No","attributes":{"block":"no","jres":"icons.no","whenUsed":true,"_def":{"parts":[{"kind":"label","text":"no","style":[]}],"parameters":[]}},"extendsTypes":["IconNames.No","Number"],"pyQName":"IconNames.NO"},"IconNames.Happy":{"retType":"IconNames.Happy","attributes":{"block":"happy","jres":"icons.happy","whenUsed":true,"_def":{"parts":[{"kind":"label","text":"happy","style":[]}],"parameters":[]}},"extendsTypes":["IconNames.Happy","Number"],"pyQName":"IconNames.HAPPY"},"IconNames.Sad":{"retType":"IconNames.Sad","attributes":{"block":"sad","jres":"icons.sad","whenUsed":true,"_def":{"parts":[{"kind":"label","text":"sad","style":[]}],"parameters":[]}},"extendsTypes":["IconNames.Sad","Number"],"pyQName":"IconNames.SAD"},"IconNames.Confused":{"retType":"IconNames.Confused","attributes":{"block":"confused","jres":"icons.confused","whenUsed":true,"_def":{"parts":[{"kind":"label","text":"confused","style":[]}],"parameters":[]}},"extendsTypes":["IconNames.Confused","Number"],"pyQName":"IconNames.CONFUSED"},"IconNames.Angry":{"retType":"IconNames.Angry","attributes":{"block":"angry","jres":"icons.angry","whenUsed":true,"_def":{"parts":[{"kind":"label","text":"angry","style":[]}],"parameters":[]}},"extendsTypes":["IconNames.Angry","Number"],"pyQName":"IconNames.ANGRY"},"IconNames.Asleep":{"retType":"IconNames.Asleep","attributes":{"block":"asleep","jres":"icons.asleep","whenUsed":true,"_def":{"parts":[{"kind":"label","text":"asleep","style":[]}],"parameters":[]}},"extendsTypes":["IconNames.Asleep","Number"],"pyQName":"IconNames.ASLEEP"},"IconNames.Surprised":{"retType":"IconNames.Surprised","attributes":{"block":"surprised","jres":"icons.surprised","whenUsed":true,"_def":{"parts":[{"kind":"label","text":"surprised","style":[]}],"parameters":[]}},"extendsTypes":["IconNames.Surprised","Number"],"pyQName":"IconNames.SURPRISED"},"IconNames.Silly":{"retType":"IconNames.Silly","attributes":{"block":"silly","jres":"icons.silly","whenUsed":true,"_def":{"parts":[{"kind":"label","text":"silly","style":[]}],"parameters":[]}},"extendsTypes":["IconNames.Silly","Number"],"pyQName":"IconNames.SILLY"},"IconNames.Fabulous":{"retType":"IconNames.Fabulous","attributes":{"block":"fabulous","jres":"icons.fabulous","whenUsed":true,"_def":{"parts":[{"kind":"label","text":"fabulous","style":[]}],"parameters":[]}},"extendsTypes":["IconNames.Fabulous","Number"],"pyQName":"IconNames.FABULOUS"},"IconNames.Meh":{"retType":"IconNames.Meh","attributes":{"block":"meh","jres":"icons.meh","whenUsed":true,"_def":{"parts":[{"kind":"label","text":"meh","style":[]}],"parameters":[]}},"extendsTypes":["IconNames.Meh","Number"],"pyQName":"IconNames.MEH"},"IconNames.TShirt":{"retType":"IconNames.TShirt","attributes":{"block":"t-shirt","jres":"icons.tshirt","whenUsed":true,"_def":{"parts":[{"kind":"label","text":"t-shirt","style":[]}],"parameters":[]}},"extendsTypes":["IconNames.TShirt","Number"],"pyQName":"IconNames.TSHIRT"},"IconNames.Rollerskate":{"retType":"IconNames.Rollerskate","attributes":{"block":"roller skate","jres":"icons.rollerskate","whenUsed":true,"_def":{"parts":[{"kind":"label","text":"roller skate","style":[]}],"parameters":[]}},"extendsTypes":["IconNames.Rollerskate","Number"],"pyQName":"IconNames.ROLLERSKATE"},"IconNames.Duck":{"retType":"IconNames.Duck","attributes":{"block":"duck","jres":"icons.duck","whenUsed":true,"_def":{"parts":[{"kind":"label","text":"duck","style":[]}],"parameters":[]}},"extendsTypes":["IconNames.Duck","Number"],"pyQName":"IconNames.DUCK"},"IconNames.House":{"retType":"IconNames.House","attributes":{"block":"house","jres":"icons.house","whenUsed":true,"_def":{"parts":[{"kind":"label","text":"house","style":[]}],"parameters":[]}},"extendsTypes":["IconNames.House","Number"],"pyQName":"IconNames.HOUSE"},"IconNames.Tortoise":{"retType":"IconNames.Tortoise","attributes":{"block":"tortoise","jres":"icons.tortoise","whenUsed":true,"_def":{"parts":[{"kind":"label","text":"tortoise","style":[]}],"parameters":[]}},"extendsTypes":["IconNames.Tortoise","Number"],"pyQName":"IconNames.TORTOISE"},"IconNames.Butterfly":{"retType":"IconNames.Butterfly","attributes":{"block":"butterfly","jres":"icons.butterfly","whenUsed":true,"_def":{"parts":[{"kind":"label","text":"butterfly","style":[]}],"parameters":[]}},"extendsTypes":["IconNames.Butterfly","Number"],"pyQName":"IconNames.BUTTERFLY"},"IconNames.StickFigure":{"retType":"IconNames.StickFigure","attributes":{"block":"stick figure","jres":"icons.stickfigure","whenUsed":true,"_def":{"parts":[{"kind":"label","text":"stick figure","style":[]}],"parameters":[]}},"extendsTypes":["IconNames.StickFigure","Number"],"pyQName":"IconNames.STICK_FIGURE"},"IconNames.Ghost":{"retType":"IconNames.Ghost","attributes":{"block":"ghost","jres":"icons.ghost","whenUsed":true,"_def":{"parts":[{"kind":"label","text":"ghost","style":[]}],"parameters":[]}},"extendsTypes":["IconNames.Ghost","Number"],"pyQName":"IconNames.GHOST"},"IconNames.Sword":{"retType":"IconNames.Sword","attributes":{"block":"sword","jres":"icons.sword","whenUsed":true,"_def":{"parts":[{"kind":"label","text":"sword","style":[]}],"parameters":[]}},"extendsTypes":["IconNames.Sword","Number"],"pyQName":"IconNames.SWORD"},"IconNames.Giraffe":{"retType":"IconNames.Giraffe","attributes":{"block":"giraffe","jres":"icons.giraffe","whenUsed":true,"_def":{"parts":[{"kind":"label","text":"giraffe","style":[]}],"parameters":[]}},"extendsTypes":["IconNames.Giraffe","Number"],"pyQName":"IconNames.GIRAFFE"},"IconNames.Skull":{"retType":"IconNames.Skull","attributes":{"block":"skull","jres":"icons.skull","whenUsed":true,"_def":{"parts":[{"kind":"label","text":"skull","style":[]}],"parameters":[]}},"extendsTypes":["IconNames.Skull","Number"],"pyQName":"IconNames.SKULL"},"IconNames.Umbrella":{"retType":"IconNames.Umbrella","attributes":{"block":"umbrella","jres":"icons.umbrella","whenUsed":true,"_def":{"parts":[{"kind":"label","text":"umbrella","style":[]}],"parameters":[]}},"extendsTypes":["IconNames.Umbrella","Number"],"pyQName":"IconNames.UMBRELLA"},"IconNames.Snake":{"retType":"IconNames.Snake","attributes":{"block":"snake","jres":"icons.snake","whenUsed":true,"_def":{"parts":[{"kind":"label","text":"snake","style":[]}],"parameters":[]}},"extendsTypes":["IconNames.Snake","Number"],"pyQName":"IconNames.SNAKE"},"IconNames.Rabbit":{"retType":"IconNames.Rabbit","attributes":{"block":"rabbit","jres":"icons.rabbit","whenUsed":true,"_def":{"parts":[{"kind":"label","text":"rabbit","style":[]}],"parameters":[]}},"extendsTypes":["IconNames.Rabbit","Number"],"pyQName":"IconNames.RABBIT"},"IconNames.Cow":{"retType":"IconNames.Cow","attributes":{"block":"cow","jres":"icons.cow","whenUsed":true,"_def":{"parts":[{"kind":"label","text":"cow","style":[]}],"parameters":[]}},"extendsTypes":["IconNames.Cow","Number"],"pyQName":"IconNames.COW"},"IconNames.QuarterNote":{"retType":"IconNames.QuarterNote","attributes":{"block":"quarter note","jres":"icons.quarternote","whenUsed":true,"_def":{"parts":[{"kind":"label","text":"quarter note","style":[]}],"parameters":[]}},"extendsTypes":["IconNames.QuarterNote","Number"],"pyQName":"IconNames.QUARTER_NOTE"},"IconNames.EigthNote":{"retType":"IconNames.EigthNote","attributes":{"block":"eigth note","jres":"icons.eighthnote","deprecated":"true","blockHidden":true,"whenUsed":true,"_def":{"parts":[{"kind":"label","text":"eigth note","style":[]}],"parameters":[]}},"extendsTypes":["IconNames.EigthNote","Number"],"pyQName":"IconNames.EIGTH_NOTE"},"IconNames.EighthNote":{"retType":"IconNames.EighthNote","attributes":{"block":"eighth note","jres":"icons.eighthnote","whenUsed":true,"_def":{"parts":[{"kind":"label","text":"eighth note","style":[]}],"parameters":[]}},"extendsTypes":["IconNames.EighthNote","Number"],"pyQName":"IconNames.EIGHTH_NOTE"},"IconNames.Pitchfork":{"retType":"IconNames.Pitchfork","attributes":{"block":"pitchfork","jres":"icons.pitchfork","whenUsed":true,"_def":{"parts":[{"kind":"label","text":"pitchfork","style":[]}],"parameters":[]}},"extendsTypes":["IconNames.Pitchfork","Number"],"pyQName":"IconNames.PITCHFORK"},"IconNames.Target":{"retType":"IconNames.Target","attributes":{"block":"target","jres":"icons.target","whenUsed":true,"_def":{"parts":[{"kind":"label","text":"target","style":[]}],"parameters":[]}},"extendsTypes":["IconNames.Target","Number"],"pyQName":"IconNames.TARGET"},"IconNames.Triangle":{"retType":"IconNames.Triangle","attributes":{"block":"triangle","jres":"icons.triangle","whenUsed":true,"_def":{"parts":[{"kind":"label","text":"triangle","style":[]}],"parameters":[]}},"extendsTypes":["IconNames.Triangle","Number"],"pyQName":"IconNames.TRIANGLE"},"IconNames.LeftTriangle":{"retType":"IconNames.LeftTriangle","attributes":{"block":"left triangle","jres":"icons.lefttriangle","whenUsed":true,"_def":{"parts":[{"kind":"label","text":"left triangle","style":[]}],"parameters":[]}},"extendsTypes":["IconNames.LeftTriangle","Number"],"pyQName":"IconNames.LEFT_TRIANGLE"},"IconNames.Chessboard":{"retType":"IconNames.Chessboard","attributes":{"block":"chess board","jres":"icons.chessboard","whenUsed":true,"_def":{"parts":[{"kind":"label","text":"chess board","style":[]}],"parameters":[]}},"extendsTypes":["IconNames.Chessboard","Number"],"pyQName":"IconNames.CHESSBOARD"},"IconNames.Diamond":{"retType":"IconNames.Diamond","attributes":{"block":"diamond","jres":"icons.diamond","whenUsed":true,"_def":{"parts":[{"kind":"label","text":"diamond","style":[]}],"parameters":[]}},"extendsTypes":["IconNames.Diamond","Number"],"pyQName":"IconNames.DIAMOND"},"IconNames.SmallDiamond":{"retType":"IconNames.SmallDiamond","attributes":{"block":"small diamond","jres":"icons.smalldiamond","whenUsed":true,"_def":{"parts":[{"kind":"label","text":"small diamond","style":[]}],"parameters":[]}},"extendsTypes":["IconNames.SmallDiamond","Number"],"pyQName":"IconNames.SMALL_DIAMOND"},"IconNames.Square":{"retType":"IconNames.Square","attributes":{"block":"square","jres":"icons.square","whenUsed":true,"_def":{"parts":[{"kind":"label","text":"square","style":[]}],"parameters":[]}},"extendsTypes":["IconNames.Square","Number"],"pyQName":"IconNames.SQUARE"},"IconNames.SmallSquare":{"retType":"IconNames.SmallSquare","attributes":{"block":"small square","jres":"icons.smallsquare","whenUsed":true,"_def":{"parts":[{"kind":"label","text":"small square","style":[]}],"parameters":[]}},"extendsTypes":["IconNames.SmallSquare","Number"],"pyQName":"IconNames.SMALL_SQUARE"},"IconNames.Scissors":{"retType":"IconNames.Scissors","attributes":{"block":"scissors","jres":"icons.scissors","whenUsed":true,"_def":{"parts":[{"kind":"label","text":"scissors","style":[]}],"parameters":[]}},"extendsTypes":["IconNames.Scissors","Number"],"pyQName":"IconNames.SCISSORS"},"ArrowNames":{"kind":6,"retType":"ArrowNames","extendsTypes":["ArrowNames","Number"]},"ArrowNames.North":{"retType":"ArrowNames.North","attributes":{"blockIdentity":"images.arrowNumber","block":"North","_def":{"parts":[{"kind":"label","text":"North","style":[]}],"parameters":[]}},"extendsTypes":["ArrowNames.North","Number"],"pyQName":"ArrowNames.NORTH"},"ArrowNames.NorthEast":{"retType":"ArrowNames.NorthEast","attributes":{"blockIdentity":"images.arrowNumber","block":"North East","_def":{"parts":[{"kind":"label","text":"North East","style":[]}],"parameters":[]}},"extendsTypes":["ArrowNames.NorthEast","Number"],"pyQName":"ArrowNames.NORTH_EAST"},"ArrowNames.East":{"retType":"ArrowNames.East","attributes":{"blockIdentity":"images.arrowNumber","block":"East","_def":{"parts":[{"kind":"label","text":"East","style":[]}],"parameters":[]}},"extendsTypes":["ArrowNames.East","Number"],"pyQName":"ArrowNames.EAST"},"ArrowNames.SouthEast":{"retType":"ArrowNames.SouthEast","attributes":{"blockIdentity":"images.arrowNumber","block":"South East","_def":{"parts":[{"kind":"label","text":"South East","style":[]}],"parameters":[]}},"extendsTypes":["ArrowNames.SouthEast","Number"],"pyQName":"ArrowNames.SOUTH_EAST"},"ArrowNames.South":{"retType":"ArrowNames.South","attributes":{"blockIdentity":"images.arrowNumber","block":"South","_def":{"parts":[{"kind":"label","text":"South","style":[]}],"parameters":[]}},"extendsTypes":["ArrowNames.South","Number"],"pyQName":"ArrowNames.SOUTH"},"ArrowNames.SouthWest":{"retType":"ArrowNames.SouthWest","attributes":{"blockIdentity":"images.arrowNumber","block":"South West","_def":{"parts":[{"kind":"label","text":"South West","style":[]}],"parameters":[]}},"extendsTypes":["ArrowNames.SouthWest","Number"],"pyQName":"ArrowNames.SOUTH_WEST"},"ArrowNames.West":{"retType":"ArrowNames.West","attributes":{"blockIdentity":"images.arrowNumber","block":"West","_def":{"parts":[{"kind":"label","text":"West","style":[]}],"parameters":[]}},"extendsTypes":["ArrowNames.West","Number"],"pyQName":"ArrowNames.WEST"},"ArrowNames.NorthWest":{"retType":"ArrowNames.NorthWest","attributes":{"blockIdentity":"images.arrowNumber","block":"North West","_def":{"parts":[{"kind":"label","text":"North West","style":[]}],"parameters":[]}},"extendsTypes":["ArrowNames.NorthWest","Number"],"pyQName":"ArrowNames.NORTH_WEST"},"basic.showIcon":{"kind":-3,"attributes":{"weight":90,"blockGap":"8","blockId":"basic_show_icon","block":"show icon %i","icon":"","parts":"ledmatrix","help":"basic/show-icon","paramFieldEditor":{"icon":"imagedropdown"},"paramFieldEditorOptions":{"icon":{"columns":"5","width":"380","maxRows":"4"}},"paramHelp":{"icon":"the predefined icon id","interval":"the amount of time (milliseconds) to show the icon. Default is 600."},"jsDoc":"Draws the selected icon on the LED screen","_def":{"parts":[{"kind":"label","text":"show icon ","style":[]},{"kind":"param","name":"i","ref":false}],"parameters":[{"kind":"param","name":"i","ref":false}]}},"parameters":[{"name":"icon","description":"the predefined icon id","type":"IconNames","isEnum":true},{"name":"interval","description":"the amount of time (milliseconds) to show the icon. Default is 600.","initializer":"600"}],"pyQName":"basic.show_icon"},"basic.showArrow":{"kind":-3,"attributes":{"weight":50,"blockGap":"8","blockId":"basic_show_arrow","block":"show arrow %i=device_arrow","parts":"ledmatrix","help":"basic/show-arrow","paramHelp":{"direction":"the direction of the arrow","interval":"the amount of time (milliseconds) to show the icon. Default is 600."},"jsDoc":"Draws an arrow on the LED screen","_def":{"parts":[{"kind":"label","text":"show arrow ","style":[]},{"kind":"param","name":"i","shadowBlockId":"device_arrow","ref":false}],"parameters":[{"kind":"param","name":"i","shadowBlockId":"device_arrow","ref":false}]}},"parameters":[{"name":"direction","description":"the direction of the arrow"},{"name":"interval","description":"the amount of time (milliseconds) to show the icon. Default is 600.","initializer":"600"}],"pyQName":"basic.show_arrow"},"images.arrowImage":{"kind":-3,"retType":"Image","attributes":{"weight":50,"blockGap":"8","help":"images/arrow-image","blockId":"builtin_arrow_image","block":"arrow image %i","_def":{"parts":[{"kind":"label","text":"arrow image ","style":[]},{"kind":"param","name":"i","ref":false}],"parameters":[{"kind":"param","name":"i","ref":false}]}},"parameters":[{"name":"i","type":"ArrowNames","isEnum":true}],"pyQName":"images.arrow_image"},"images.iconImage":{"kind":-3,"retType":"Image","attributes":{"weight":50,"blockGap":"8","help":"images/icon-image","blockId":"builtin_image","block":"icon image %i","paramFieldEditor":{"i":"imagedropdown"},"paramFieldEditorOptions":{"i":{"columns":"5","width":"380","maxRows":"4"}},"_def":{"parts":[{"kind":"label","text":"icon image ","style":[]},{"kind":"param","name":"i","ref":false}],"parameters":[{"kind":"param","name":"i","ref":false}]}},"parameters":[{"name":"i","type":"IconNames","isEnum":true}],"pyQName":"images.icon_image"},"images.arrowNumber":{"kind":-3,"retType":"number","attributes":{"weight":50,"blockGap":"8","help":"images/arrow-number","blockId":"device_arrow","block":"%arrow","shim":"TD_ID","_def":{"parts":[{"kind":"param","name":"arrow","ref":false}],"parameters":[{"kind":"param","name":"arrow","ref":false}]}},"parameters":[{"name":"arrow","type":"ArrowNames","isEnum":true}],"pyQName":"images.arrow_number"},"input.onScreenUp":{"kind":-3,"attributes":{"help":"input/on-screen-up","paramHelp":{"body":"TODO"},"jsDoc":"Attaches code to run when the screen is facing up."},"parameters":[{"name":"body","description":"TODO","type":"() => void","handlerParameters":[]}],"pyQName":"input.on_screen_up"},"input.onScreenDown":{"kind":-3,"attributes":{"help":"input/on-screen-down","paramHelp":{"body":"TODO"},"jsDoc":"Attaches code to run when the screen is facing down."},"parameters":[{"name":"body","description":"TODO","type":"() => void","handlerParameters":[]}],"pyQName":"input.on_screen_down"},"input.onShake":{"kind":-3,"attributes":{"deprecated":"true","help":"input/on-shake","paramHelp":{"body":"TODO"},"jsDoc":"Attaches code to run when the device is shaken."},"parameters":[{"name":"body","description":"TODO","type":"() => void","handlerParameters":[]}],"pyQName":"input.on_shake"},"input.onLogoUp":{"kind":-3,"attributes":{"help":"input/on-logo-up","paramHelp":{"body":"TODO"},"jsDoc":"Attaches code to run when the logo is oriented upwards and the board is vertical."},"parameters":[{"name":"body","description":"TODO","type":"() => void","handlerParameters":[]}],"pyQName":"input.on_logo_up"},"input.onLogoDown":{"kind":-3,"attributes":{"help":"input/on-logo-down","paramHelp":{"body":"TODO"},"jsDoc":"Attaches code to run when the logo is oriented downwards and the board is vertical."},"parameters":[{"name":"body","description":"TODO","type":"() => void","handlerParameters":[]}],"pyQName":"input.on_logo_down"},"input.calibrate":{"kind":-3,"attributes":{"weight":0,"help":"input/calibrate-compass","jsDoc":"Obsolete, use input.calibrateCompass instead."},"parameters":[]},"input.runningTime":{"kind":-3,"retType":"number","attributes":{"help":"input/running-time","weight":50,"blockGap":"8","blockId":"device_get_running_time","block":"running time (ms)","advanced":true,"jsDoc":"Gets the number of milliseconds elapsed since power on.","_def":{"parts":[{"kind":"label","text":"running time (ms)","style":[]}],"parameters":[]}},"parameters":[],"pyQName":"input.running_time"},"input.runningTimeMicros":{"kind":-3,"retType":"number","attributes":{"help":"input/running-time-micros","weight":49,"blockId":"device_get_running_time_micros","block":"running time (micros)","advanced":true,"jsDoc":"Gets the number of microseconds elapsed since power on.","_def":{"parts":[{"kind":"label","text":"running time (micros)","style":[]}],"parameters":[]}},"parameters":[],"pyQName":"input.running_time_micros"},"control.runInParallel":{"kind":-3,"attributes":{"hidden":"1","jsDoc":"Run other code in the parallel."},"parameters":[{"name":"a","type":"() => void","handlerParameters":[]}],"pyQName":"control.run_in_parallel"},"control.runInBackground":{"kind":-3,"attributes":{"hidden":"1","deprecated":"1"},"parameters":[{"name":"a","type":"() => void","handlerParameters":[]}],"pyQName":"control.run_in_background"},"control.singleSimulator":{"kind":-3,"attributes":{"jsDoc":"Allow only one simulator"},"parameters":[],"pyQName":"control.single_simulator"},"control.eventSourceId":{"kind":-3,"retType":"number","attributes":{"weight":19,"blockId":"control_event_source_id","block":"%id","blockGap":"8","help":"control/event-source-id","shim":"TD_ID","advanced":true,"jsDoc":"Returns the value of a C++ runtime constant","_def":{"parts":[{"kind":"param","name":"id","ref":false}],"parameters":[{"kind":"param","name":"id","ref":false}]}},"parameters":[{"name":"id","type":"EventBusSource","isEnum":true}],"pyQName":"control.event_source_id"},"control.eventValueId":{"kind":-3,"retType":"number","attributes":{"weight":19,"blockId":"control_event_value_id","block":"%id","help":"control/event-value-id","shim":"TD_ID","advanced":true,"jsDoc":"Returns the value of a C++ runtime constant","_def":{"parts":[{"kind":"param","name":"id","ref":false}],"parameters":[{"kind":"param","name":"id","ref":false}]}},"parameters":[{"name":"id","type":"EventBusValue","isEnum":true}],"pyQName":"control.event_value_id"},"control.PXT_PANIC":{"kind":6,"retType":"control.PXT_PANIC","extendsTypes":["control.PXT_PANIC","Number"]},"control.PXT_PANIC.CODAL_OOM":{"retType":"control.PXT_PANIC.CODAL_OOM","extendsTypes":["control.PXT_PANIC.CODAL_OOM","Number"]},"control.PXT_PANIC.GC_OOM":{"retType":"control.PXT_PANIC.GC_OOM","extendsTypes":["control.PXT_PANIC.GC_OOM","Number"]},"control.PXT_PANIC.GC_TOO_BIG_ALLOCATION":{"retType":"control.PXT_PANIC.GC_TOO_BIG_ALLOCATION","extendsTypes":["control.PXT_PANIC.GC_TOO_BIG_ALLOCATION","Number"]},"control.PXT_PANIC.CODAL_HEAP_ERROR":{"retType":"control.PXT_PANIC.CODAL_HEAP_ERROR","extendsTypes":["control.PXT_PANIC.CODAL_HEAP_ERROR","Number"]},"control.PXT_PANIC.CODAL_NULL_DEREFERENCE":{"retType":"control.PXT_PANIC.CODAL_NULL_DEREFERENCE","extendsTypes":["control.PXT_PANIC.CODAL_NULL_DEREFERENCE","Number"]},"control.PXT_PANIC.CODAL_USB_ERROR":{"retType":"control.PXT_PANIC.CODAL_USB_ERROR","extendsTypes":["control.PXT_PANIC.CODAL_USB_ERROR","Number"]},"control.PXT_PANIC.CODAL_HARDWARE_CONFIGURATION_ERROR":{"retType":"control.PXT_PANIC.CODAL_HARDWARE_CONFIGURATION_ERROR","extendsTypes":["control.PXT_PANIC.CODAL_HARDWARE_CONFIGURATION_ERROR","Number"]},"control.PXT_PANIC.INVALID_BINARY_HEADER":{"retType":"control.PXT_PANIC.INVALID_BINARY_HEADER","extendsTypes":["control.PXT_PANIC.INVALID_BINARY_HEADER","Number"]},"control.PXT_PANIC.OUT_OF_BOUNDS":{"retType":"control.PXT_PANIC.OUT_OF_BOUNDS","extendsTypes":["control.PXT_PANIC.OUT_OF_BOUNDS","Number"]},"control.PXT_PANIC.REF_DELETED":{"retType":"control.PXT_PANIC.REF_DELETED","extendsTypes":["control.PXT_PANIC.REF_DELETED","Number"]},"control.PXT_PANIC.SIZE":{"retType":"control.PXT_PANIC.SIZE","extendsTypes":["control.PXT_PANIC.SIZE","Number"]},"control.PXT_PANIC.INVALID_VTABLE":{"retType":"control.PXT_PANIC.INVALID_VTABLE","extendsTypes":["control.PXT_PANIC.INVALID_VTABLE","Number"]},"control.PXT_PANIC.INTERNAL_ERROR":{"retType":"control.PXT_PANIC.INTERNAL_ERROR","extendsTypes":["control.PXT_PANIC.INTERNAL_ERROR","Number"]},"control.PXT_PANIC.NO_SUCH_CONFIG":{"retType":"control.PXT_PANIC.NO_SUCH_CONFIG","extendsTypes":["control.PXT_PANIC.NO_SUCH_CONFIG","Number"]},"control.PXT_PANIC.NO_SUCH_PIN":{"retType":"control.PXT_PANIC.NO_SUCH_PIN","extendsTypes":["control.PXT_PANIC.NO_SUCH_PIN","Number"]},"control.PXT_PANIC.INVALID_ARGUMENT":{"retType":"control.PXT_PANIC.INVALID_ARGUMENT","extendsTypes":["control.PXT_PANIC.INVALID_ARGUMENT","Number"]},"control.PXT_PANIC.MEMORY_LIMIT_EXCEEDED":{"retType":"control.PXT_PANIC.MEMORY_LIMIT_EXCEEDED","extendsTypes":["control.PXT_PANIC.MEMORY_LIMIT_EXCEEDED","Number"]},"control.PXT_PANIC.SCREEN_ERROR":{"retType":"control.PXT_PANIC.SCREEN_ERROR","extendsTypes":["control.PXT_PANIC.SCREEN_ERROR","Number"]},"control.PXT_PANIC.MISSING_PROPERTY":{"retType":"control.PXT_PANIC.MISSING_PROPERTY","extendsTypes":["control.PXT_PANIC.MISSING_PROPERTY","Number"]},"control.PXT_PANIC.INVALID_IMAGE":{"retType":"control.PXT_PANIC.INVALID_IMAGE","extendsTypes":["control.PXT_PANIC.INVALID_IMAGE","Number"]},"control.PXT_PANIC.CALLED_FROM_ISR":{"retType":"control.PXT_PANIC.CALLED_FROM_ISR","extendsTypes":["control.PXT_PANIC.CALLED_FROM_ISR","Number"]},"control.PXT_PANIC.HEAP_DUMPED":{"retType":"control.PXT_PANIC.HEAP_DUMPED","extendsTypes":["control.PXT_PANIC.HEAP_DUMPED","Number"]},"control.PXT_PANIC.STACK_OVERFLOW":{"retType":"control.PXT_PANIC.STACK_OVERFLOW","extendsTypes":["control.PXT_PANIC.STACK_OVERFLOW","Number"]},"control.PXT_PANIC.BLOCKING_TO_STRING":{"retType":"control.PXT_PANIC.BLOCKING_TO_STRING","extendsTypes":["control.PXT_PANIC.BLOCKING_TO_STRING","Number"]},"control.PXT_PANIC.VM_ERROR":{"retType":"control.PXT_PANIC.VM_ERROR","extendsTypes":["control.PXT_PANIC.VM_ERROR","Number"]},"control.PXT_PANIC.SETTINGS_CLEARED":{"retType":"control.PXT_PANIC.SETTINGS_CLEARED","extendsTypes":["control.PXT_PANIC.SETTINGS_CLEARED","Number"]},"control.PXT_PANIC.SETTINGS_OVERLOAD":{"retType":"control.PXT_PANIC.SETTINGS_OVERLOAD","extendsTypes":["control.PXT_PANIC.SETTINGS_OVERLOAD","Number"]},"control.PXT_PANIC.SETTINGS_SECRET_MISSING":{"retType":"control.PXT_PANIC.SETTINGS_SECRET_MISSING","extendsTypes":["control.PXT_PANIC.SETTINGS_SECRET_MISSING","Number"]},"control.PXT_PANIC.DELETE_ON_CLASS":{"retType":"control.PXT_PANIC.DELETE_ON_CLASS","extendsTypes":["control.PXT_PANIC.DELETE_ON_CLASS","Number"]},"control.PXT_PANIC.CAST_FIRST":{"retType":"control.PXT_PANIC.CAST_FIRST","extendsTypes":["control.PXT_PANIC.CAST_FIRST","Number"]},"control.PXT_PANIC.CAST_FROM_UNDEFINED":{"retType":"control.PXT_PANIC.CAST_FIRST","extendsTypes":["control.PXT_PANIC.CAST_FROM_UNDEFINED","Number"]},"control.PXT_PANIC.CAST_FROM_BOOLEAN":{"retType":"control.PXT_PANIC.CAST_FROM_BOOLEAN","extendsTypes":["control.PXT_PANIC.CAST_FROM_BOOLEAN","Number"]},"control.PXT_PANIC.CAST_FROM_NUMBER":{"retType":"control.PXT_PANIC.CAST_FROM_NUMBER","extendsTypes":["control.PXT_PANIC.CAST_FROM_NUMBER","Number"]},"control.PXT_PANIC.CAST_FROM_STRING":{"retType":"control.PXT_PANIC.CAST_FROM_STRING","extendsTypes":["control.PXT_PANIC.CAST_FROM_STRING","Number"]},"control.PXT_PANIC.CAST_FROM_OBJECT":{"retType":"control.PXT_PANIC.CAST_FROM_OBJECT","extendsTypes":["control.PXT_PANIC.CAST_FROM_OBJECT","Number"]},"control.PXT_PANIC.CAST_FROM_FUNCTION":{"retType":"control.PXT_PANIC.CAST_FROM_FUNCTION","extendsTypes":["control.PXT_PANIC.CAST_FROM_FUNCTION","Number"]},"control.PXT_PANIC.CAST_FROM_NULL":{"retType":"control.PXT_PANIC.CAST_FROM_NULL","extendsTypes":["control.PXT_PANIC.CAST_FROM_NULL","Number"]},"control.PXT_PANIC.UNHANDLED_EXCEPTION":{"retType":"control.PXT_PANIC.UNHANDLED_EXCEPTION","extendsTypes":["control.PXT_PANIC.UNHANDLED_EXCEPTION","Number"]},"control.panic":{"kind":-3,"attributes":{"jsDoc":"Display specified error code and stop the program."},"parameters":[{"name":"code"}]},"control.assert":{"kind":-3,"attributes":{"jsDoc":"If the condition is false, display msg on serial console, and panic with code 098."},"parameters":[{"name":"condition","type":"boolean"},{"name":"msg","type":"string","initializer":"undefined"}]},"control.fail":{"kind":-3,"parameters":[{"name":"message","type":"string"}]},"control.allocateEventSource":{"kind":-3,"retType":"number","attributes":{"jsDoc":"Incrementally allocates event source identifiers."},"parameters":[],"pyQName":"control.allocate_event_source"},"control.runtimeWarning":{"kind":-3,"attributes":{"jsDoc":"Display warning in the simulator."},"parameters":[{"name":"message","type":"string"}],"pyQName":"control.runtime_warning"},"control.programHash":{"kind":-3,"retType":"number","parameters":[],"pyQName":"control.program_hash"},"control.programName":{"kind":-3,"retType":"string","parameters":[],"pyQName":"control.program_name"},"control.ramSize":{"kind":-3,"retType":"number","attributes":{"jsDoc":"Returns estimated size of memory in bytes."},"parameters":[],"pyQName":"control.ram_size"},"control.benchmark":{"kind":-3,"retType":"number","attributes":{"jsDoc":"Runs the function and returns run time in microseconds."},"parameters":[{"name":"f","type":"() => void","handlerParameters":[]}]},"control.compareVersion":{"kind":-3,"retType":"number","attributes":{"jsDoc":"Given two versions, returns -1 if the first version is less than\nthe second, 1 if it's greater, and 0 if it's the same."},"parameters":[{"name":"version1","type":"string"},{"name":"version2","type":"string"}],"pyQName":"control.compare_version"},"control.hardwareVersion":{"kind":-3,"retType":"string","parameters":[],"pyQName":"control.hardware_version"},"convertToText":{"kind":-3,"retType":"string","attributes":{"help":"text/convert-to-text","weight":1,"block":"convert $value=math_number to text","blockId":"variable_to_text","blockNamespace":"text","paramHelp":{"value":"value to be converted to text"},"jsDoc":"Convert any value to text","_def":{"parts":[{"kind":"label","text":"convert ","style":[]},{"kind":"param","name":"value","shadowBlockId":"math_number","ref":true},{"kind":"label","text":" to text","style":[]}],"parameters":[{"kind":"param","name":"value","shadowBlockId":"math_number","ref":true}]}},"parameters":[{"name":"value","description":"value to be converted to text","type":"any"}],"pyQName":"convert_to_text"},"control.enablePerfCounter":{"kind":-3,"attributes":{"shim":"TD_NOOP","shimArgument":"perfCounter","jsDoc":"Enable profiling for current function."},"parameters":[{"name":"name","type":"string","initializer":"undefined"}],"pyQName":"control.enable_perf_counter"},"control.dmesgPerfCounters":{"kind":-3,"attributes":{"jsDoc":"Dump values of profiling performance counters."},"parameters":[],"pyQName":"control.dmesg_perf_counters"},"control.IntervalMode":{"kind":6,"retType":"control.IntervalMode","extendsTypes":["control.IntervalMode","Number"]},"control.IntervalMode.Interval":{"retType":"control.IntervalMode.Interval","extendsTypes":["control.IntervalMode.Interval","Number"],"pyQName":"control.IntervalMode.INTERVAL"},"control.IntervalMode.Timeout":{"retType":"control.IntervalMode.Timeout","extendsTypes":["control.IntervalMode.Timeout","Number"],"pyQName":"control.IntervalMode.TIMEOUT"},"control.IntervalMode.Immediate":{"retType":"control.IntervalMode.Immediate","extendsTypes":["control.IntervalMode.Immediate","Number"],"pyQName":"control.IntervalMode.IMMEDIATE"},"control.setInterval":{"kind":-3,"retType":"number","parameters":[{"name":"func","type":"() => void","handlerParameters":[]},{"name":"delay"},{"name":"mode","type":"control.IntervalMode","isEnum":true}],"pyQName":"control.set_interval"},"control.clearInterval":{"kind":-3,"parameters":[{"name":"intervalId"},{"name":"mode","type":"control.IntervalMode","isEnum":true}],"pyQName":"control.clear_interval"},"control.GCStats":{"kind":9,"retType":"control.GCStats","extendsTypes":[]},"control.GCStats.numGC":{"kind":2,"retType":"number","isInstance":true,"pyQName":"control.GCStats.num_gc"},"control.GCStats.numBlocks":{"kind":2,"retType":"number","isInstance":true,"pyQName":"control.GCStats.num_blocks"},"control.GCStats.totalBytes":{"kind":2,"retType":"number","isInstance":true,"pyQName":"control.GCStats.total_bytes"},"control.GCStats.lastFreeBytes":{"kind":2,"retType":"number","isInstance":true,"pyQName":"control.GCStats.last_free_bytes"},"control.GCStats.lastMaxBlockBytes":{"kind":2,"retType":"number","isInstance":true,"pyQName":"control.GCStats.last_max_block_bytes"},"control.GCStats.minFreeBytes":{"kind":2,"retType":"number","isInstance":true,"pyQName":"control.GCStats.min_free_bytes"},"control.gcStats":{"kind":-3,"retType":"control.GCStats","attributes":{"jsDoc":"Get various statistics about the garbage collector (GC)"},"parameters":[],"pyQName":"control.gc_stats"},"ConsolePriority":{"kind":6,"retType":"ConsolePriority","extendsTypes":["ConsolePriority","Number"]},"ConsolePriority.Debug":{"retType":"ConsolePriority.Debug","extendsTypes":["ConsolePriority.Debug","Number"],"pyQName":"ConsolePriority.DEBUG"},"ConsolePriority.Log":{"retType":"ConsolePriority.Log","extendsTypes":["ConsolePriority.Log","Number"],"pyQName":"ConsolePriority.LOG"},"ConsolePriority.Warning":{"retType":"ConsolePriority.Warning","extendsTypes":["ConsolePriority.Warning","Number"],"pyQName":"ConsolePriority.WARNING"},"ConsolePriority.Error":{"retType":"ConsolePriority.Error","extendsTypes":["ConsolePriority.Error","Number"],"pyQName":"ConsolePriority.ERROR"},"ConsolePriority.Silent":{"retType":"ConsolePriority.Silent","extendsTypes":["ConsolePriority.Silent","Number"],"pyQName":"ConsolePriority.SILENT"},"console":{"kind":5,"retType":"","attributes":{"weight":12,"color":"#002050","icon":"","advanced":true,"jsDoc":"Reading and writing data to the console output."}},"console.minPriority":{"kind":4,"retType":"ConsolePriority","attributes":{"jsDoc":"Minimum priority to send messages to listeners"},"pyQName":"console.min_priority"},"console.add":{"kind":-3,"parameters":[{"name":"priority","type":"ConsolePriority","isEnum":true},{"name":"message","type":"any"}]},"console.debug":{"kind":-3,"parameters":[{"name":"text","type":"any"}]},"console.warn":{"kind":-3,"parameters":[{"name":"text","type":"any"}]},"console.error":{"kind":-3,"parameters":[{"name":"text","type":"any"}]},"console.log":{"kind":-3,"attributes":{"weight":90,"help":"console/log","blockGap":"8","paramHelp":{"value":"to send"},"jsDoc":"Write a line of text to the console output."},"parameters":[{"name":"value","description":"to send","type":"any"}],"pyQName":"print"},"console.logValue":{"kind":-3,"attributes":{"paramDefl":{"name":"x"},"weight":88,"blockGap":"8","help":"console/log-value","paramHelp":{"name":"name of the value stream, eg: \"x\"","value":"to write"},"jsDoc":"Write a name:value pair as a line of text to the console output."},"parameters":[{"name":"name","description":"name of the value stream, eg: \"x\"","type":"any","default":"x"},{"name":"value","description":"to write","type":"any"}],"pyQName":"console.log_value"},"console.inspect":{"kind":-3,"retType":"string","attributes":{"paramHelp":{"obj":"value to be converted to a string","maxElements":"[optional] max number values in an object to include in output"},"jsDoc":"Convert any object or value to a string representation"},"parameters":[{"name":"obj","description":"value to be converted to a string","type":"any"},{"name":"maxElements","description":"[optional] max number values in an object to include in output","initializer":"20"}]},"console.addListener":{"kind":-3,"attributes":{"paramHelp":{"listener":""},"jsDoc":"Adds a listener for the log messages"},"parameters":[{"name":"listener","type":"(priority: ConsolePriority, text: string) => void","handlerParameters":[{"name":"priority","type":"ConsolePriority"},{"name":"text","type":"string"}]}],"pyQName":"console.add_listener"},"console.removeListener":{"kind":-3,"attributes":{"paramHelp":{"listener":""},"jsDoc":"Removes a listener"},"parameters":[{"name":"listener","type":"(priority: ConsolePriority, text: string) => void","handlerParameters":[{"name":"priority","type":"ConsolePriority"},{"name":"text","type":"string"}]}],"pyQName":"console.remove_listener"},"Direction":{"kind":6,"retType":"Direction","extendsTypes":["Direction","Number"]},"Direction.Right":{"retType":"Direction.Right","attributes":{"block":"right","_def":{"parts":[{"kind":"label","text":"right","style":[]}],"parameters":[]}},"extendsTypes":["Direction.Right","Number"],"pyQName":"Direction.RIGHT"},"Direction.Left":{"retType":"Direction.Left","attributes":{"block":"left","_def":{"parts":[{"kind":"label","text":"left","style":[]}],"parameters":[]}},"extendsTypes":["Direction.Left","Number"],"pyQName":"Direction.LEFT"},"LedSpriteProperty":{"kind":6,"retType":"LedSpriteProperty","extendsTypes":["LedSpriteProperty","Number"]},"LedSpriteProperty.X":{"retType":"LedSpriteProperty.X","attributes":{"block":"x","_def":{"parts":[{"kind":"label","text":"x","style":[]}],"parameters":[]}},"extendsTypes":["LedSpriteProperty.X","Number"]},"LedSpriteProperty.Y":{"retType":"LedSpriteProperty.Y","attributes":{"block":"y","_def":{"parts":[{"kind":"label","text":"y","style":[]}],"parameters":[]}},"extendsTypes":["LedSpriteProperty.Y","Number"]},"LedSpriteProperty.Direction":{"retType":"LedSpriteProperty.Direction","attributes":{"block":"direction","_def":{"parts":[{"kind":"label","text":"direction","style":[]}],"parameters":[]}},"extendsTypes":["LedSpriteProperty.Direction","Number"],"pyQName":"LedSpriteProperty.DIRECTION"},"LedSpriteProperty.Brightness":{"retType":"LedSpriteProperty.Brightness","attributes":{"block":"brightness","_def":{"parts":[{"kind":"label","text":"brightness","style":[]}],"parameters":[]}},"extendsTypes":["LedSpriteProperty.Brightness","Number"],"pyQName":"LedSpriteProperty.BRIGHTNESS"},"LedSpriteProperty.Blink":{"retType":"LedSpriteProperty.Blink","attributes":{"block":"blink","_def":{"parts":[{"kind":"label","text":"blink","style":[]}],"parameters":[]}},"extendsTypes":["LedSpriteProperty.Blink","Number"],"pyQName":"LedSpriteProperty.BLINK"},"game":{"kind":5,"retType":"","attributes":{"color":"#007A4B","weight":32,"icon":"","advanced":true,"jsDoc":"A single-LED sprite game engine"}},"game.createSprite":{"kind":-3,"retType":"game.LedSprite","attributes":{"paramDefl":{"x":"2","y":"2"},"weight":60,"blockGap":"8","help":"game/create-sprite","blockId":"game_create_sprite","block":"create sprite at|x: %x|y: %y","parts":"ledmatrix","paramHelp":{"x":"sprite horizontal coordinate, eg: 2","y":"sprite vertical coordinate, eg: 2"},"jsDoc":"Creates a new LED sprite pointing to the right.","_def":{"parts":[{"kind":"label","text":"create sprite at","style":[]},{"kind":"break"},{"kind":"label","text":"x: ","style":[]},{"kind":"param","name":"x","ref":false},{"kind":"break"},{"kind":"label","text":"y: ","style":[]},{"kind":"param","name":"y","ref":false}],"parameters":[{"kind":"param","name":"x","ref":false},{"kind":"param","name":"y","ref":false}]}},"parameters":[{"name":"x","description":"sprite horizontal coordinate, eg: 2","default":"2"},{"name":"y","description":"sprite vertical coordinate, eg: 2","default":"2"}],"pyQName":"game.create_sprite"},"game.score":{"kind":-3,"retType":"number","attributes":{"weight":9,"help":"game/score","blockId":"game_score","block":"score","blockGap":"8","jsDoc":"Gets the current score","_def":{"parts":[{"kind":"label","text":"score","style":[]}],"parameters":[]}},"parameters":[]},"game.addScore":{"kind":-3,"attributes":{"paramDefl":{"points":"1"},"weight":10,"help":"game/add-score","blockId":"game_add_score","block":"change score by|%points","blockGap":"8","parts":"ledmatrix","paramHelp":{"points":"amount of points to change, eg: 1"},"jsDoc":"Adds points to the current score and shows an animation","_def":{"parts":[{"kind":"label","text":"change score by","style":[]},{"kind":"break"},{"kind":"param","name":"points","ref":false}],"parameters":[{"kind":"param","name":"points","ref":false}]}},"parameters":[{"name":"points","description":"amount of points to change, eg: 1","default":"1"}],"pyQName":"game.add_score"},"game.startCountdown":{"kind":-3,"attributes":{"paramDefl":{"ms":"10000"},"weight":9,"help":"game/start-countdown","blockId":"game_start_countdown","block":"start countdown|(ms) %duration","blockGap":"8","parts":"ledmatrix","paramHelp":{"ms":"countdown duration in milliseconds, eg: 10000"},"jsDoc":"Shows an animation, then starts a game countdown timer, which causes Game Over when it reaches 0","_def":{"parts":[{"kind":"label","text":"start countdown","style":[]},{"kind":"break"},{"kind":"label","text":"(ms) ","style":[]},{"kind":"param","name":"duration","ref":false}],"parameters":[{"kind":"param","name":"duration","ref":false}]}},"parameters":[{"name":"ms","description":"countdown duration in milliseconds, eg: 10000","default":"10000"}],"pyQName":"game.start_countdown"},"game.gameOver":{"kind":-3,"attributes":{"weight":8,"help":"game/game-over","blockId":"game_game_over","block":"game over","parts":"ledmatrix","jsDoc":"Displays a game over animation and the score.","_def":{"parts":[{"kind":"label","text":"game over","style":[]}],"parameters":[]}},"parameters":[],"pyQName":"game.game_over"},"game.setScore":{"kind":-3,"attributes":{"blockId":"game_set_score","block":"set score %points","blockGap":"8","weight":10,"help":"game/set-score","paramHelp":{"value":"new score value."},"jsDoc":"Sets the current score value","_def":{"parts":[{"kind":"label","text":"set score ","style":[]},{"kind":"param","name":"points","ref":false}],"parameters":[{"kind":"param","name":"points","ref":false}]}},"parameters":[{"name":"value","description":"new score value."}],"pyQName":"game.set_score"},"game.life":{"kind":-3,"retType":"number","attributes":{"weight":10,"jsDoc":"Gets the current life"},"parameters":[]},"game.setLife":{"kind":-3,"attributes":{"weight":10,"help":"game/set-life","blockId":"game_set_life","block":"set life %value","blockGap":"8","paramHelp":{"value":"current life value"},"jsDoc":"Sets the current life value","_def":{"parts":[{"kind":"label","text":"set life ","style":[]},{"kind":"param","name":"value","ref":false}],"parameters":[{"kind":"param","name":"value","ref":false}]}},"parameters":[{"name":"value","description":"current life value"}],"pyQName":"game.set_life"},"game.addLife":{"kind":-3,"attributes":{"weight":10,"help":"game/add-life","blockId":"game_add_life","block":"add life %lives","blockGap":"8","paramHelp":{"lives":"amount of lives to add"},"jsDoc":"Add life points to the current life amount","_def":{"parts":[{"kind":"label","text":"add life ","style":[]},{"kind":"param","name":"lives","ref":false}],"parameters":[{"kind":"param","name":"lives","ref":false}]}},"parameters":[{"name":"lives","description":"amount of lives to add"}],"pyQName":"game.add_life"},"game.currentTime":{"kind":-3,"retType":"number","attributes":{"weight":10,"jsDoc":"Gets the remaining time (since `start countdown`) or current time (since the device started or `start stopwatch`) in milliseconds."},"parameters":[],"pyQName":"game.current_time"},"game.removeLife":{"kind":-3,"attributes":{"weight":10,"help":"game/remove-life","parts":"ledmatrix","blockId":"game_remove_life","block":"remove life %life","blockGap":"8","paramHelp":{"life":"amount of life to remove"},"jsDoc":"Remove some life","_def":{"parts":[{"kind":"label","text":"remove life ","style":[]},{"kind":"param","name":"life","ref":false}],"parameters":[{"kind":"param","name":"life","ref":false}]}},"parameters":[{"name":"life","description":"amount of life to remove"}],"pyQName":"game.remove_life"},"game.levelUp":{"kind":-3,"attributes":{"weight":10,"parts":"ledmatrix","jsDoc":"Increments the level and display a message."},"parameters":[],"pyQName":"game.level_up"},"game.level":{"kind":-3,"retType":"number","attributes":{"weight":10,"jsDoc":"Gets the current level"},"parameters":[]},"game.startStopwatch":{"kind":-3,"attributes":{"weight":10,"jsDoc":"Starts a stopwatch timer. `current time` will return the elapsed time."},"parameters":[],"pyQName":"game.start_stopwatch"},"game.isRunning":{"kind":-3,"retType":"boolean","attributes":{"weight":5,"help":"game/is-running","blockId":"game_isrunning","block":"is running","blockGap":"8","jsDoc":"Indicates if the game is still running. Returns `false` if the game is over or paused.","_def":{"parts":[{"kind":"label","text":"is running","style":[]}],"parameters":[]}},"parameters":[],"pyQName":"game.is_running"},"game.showScore":{"kind":-3,"attributes":{"weight":60,"parts":"ledmatrix","jsDoc":"Displays the score on the screen."},"parameters":[],"pyQName":"game.show_score"},"game.isGameOver":{"kind":-3,"retType":"boolean","attributes":{"weight":7,"help":"game/is-game-over","blockId":"game_isgameover","block":"is game over","blockGap":"8","jsDoc":"Indicates if the game is over and displaying the game over sequence.","_def":{"parts":[{"kind":"label","text":"is game over","style":[]}],"parameters":[]}},"parameters":[],"pyQName":"game.is_game_over"},"game.isPaused":{"kind":-3,"retType":"boolean","attributes":{"weight":6,"help":"game/is-paused","blockId":"game_ispaused","block":"is paused","blockGap":"8","jsDoc":"Indicates if the game rendering is paused to allow other animations","_def":{"parts":[{"kind":"label","text":"is paused","style":[]}],"parameters":[]}},"parameters":[],"pyQName":"game.is_paused"},"game.pause":{"kind":-3,"attributes":{"blockId":"game_pause","block":"pause","advanced":true,"blockGap":"8","help":"game/pause","jsDoc":"Pauses the game rendering engine to allow other animations","_def":{"parts":[{"kind":"label","text":"pause","style":[]}],"parameters":[]}},"parameters":[]},"game.resume":{"kind":-3,"attributes":{"blockId":"game_resume","block":"resume","advanced":true,"blockGap":"8","help":"game/resume","jsDoc":"Resumes the game rendering engine","_def":{"parts":[{"kind":"label","text":"resume","style":[]}],"parameters":[]}},"parameters":[]},"game.LedSprite":{"kind":8,"retType":"game.LedSprite","attributes":{"jsDoc":"A game sprite rendered as a single LED"},"extendsTypes":[]},"game.LedSprite.__constructor":{"kind":-3,"parameters":[{"name":"x"},{"name":"y"}],"isInstance":true},"game.LedSprite.move":{"kind":-1,"attributes":{"paramDefl":{"leds":"1"},"weight":50,"help":"game/move","blockId":"game_move_sprite","block":"%sprite|move by %leds","blockGap":"8","parts":"ledmatrix","paramHelp":{"this":"the sprite to move","leds":"number of leds to move, eg: 1, -1"},"jsDoc":"Move a certain number of LEDs in the current direction","_def":{"parts":[{"kind":"param","name":"sprite","ref":false},{"kind":"break"},{"kind":"label","text":"move by ","style":[]},{"kind":"param","name":"leds","ref":false}],"parameters":[{"kind":"param","name":"sprite","ref":false},{"kind":"param","name":"leds","ref":false}]}},"parameters":[{"name":"leds","description":"number of leds to move, eg: 1, -1","default":"1"}],"isInstance":true},"game.LedSprite.goTo":{"kind":-1,"attributes":{"parts":"ledmatrix","paramHelp":{"this":"TODO","x":"TODO","y":"TODO"},"jsDoc":"Go to this position on the screen"},"parameters":[{"name":"x","description":"TODO"},{"name":"y","description":"TODO"}],"isInstance":true,"pyQName":"game.LedSprite.go_to"},"game.LedSprite.ifOnEdgeBounce":{"kind":-1,"attributes":{"weight":18,"help":"game/if-on-edge-bounce","blockId":"game_sprite_bounce","block":"%sprite|if on edge, bounce","parts":"ledmatrix","paramHelp":{"this":"the sprite to check for bounce"},"jsDoc":"If touching the edge of the stage and facing towards it, then turn away.","_def":{"parts":[{"kind":"param","name":"sprite","ref":false},{"kind":"break"},{"kind":"label","text":"if on edge, bounce","style":[]}],"parameters":[{"kind":"param","name":"sprite","ref":false}]}},"parameters":[],"isInstance":true,"pyQName":"game.LedSprite.if_on_edge_bounce"},"game.LedSprite.turn":{"kind":-1,"attributes":{"paramDefl":{"degrees":"45"},"weight":49,"help":"game/turn","blockId":"game_turn_sprite","block":"%sprite|turn %direction|by (°) %degrees","paramHelp":{"this":"the sprite to trun","direction":"left or right","degrees":"angle in degrees to turn, eg: 45, 90, 180, 135"},"jsDoc":"Turn the sprite","_def":{"parts":[{"kind":"param","name":"sprite","ref":false},{"kind":"break"},{"kind":"label","text":"turn ","style":[]},{"kind":"param","name":"direction","ref":false},{"kind":"break"},{"kind":"label","text":"by (°) ","style":[]},{"kind":"param","name":"degrees","ref":false}],"parameters":[{"kind":"param","name":"sprite","ref":false},{"kind":"param","name":"direction","ref":false},{"kind":"param","name":"degrees","ref":false}]}},"parameters":[{"name":"direction","description":"left or right","type":"Direction","isEnum":true},{"name":"degrees","description":"angle in degrees to turn, eg: 45, 90, 180, 135","default":"45"}],"isInstance":true},"game.LedSprite.turnRight":{"kind":-1,"attributes":{"paramHelp":{"this":"the sprite to turn","degrees":"TODO"},"jsDoc":"Turn to the right (clockwise)"},"parameters":[{"name":"degrees","description":"TODO"}],"isInstance":true,"pyQName":"game.LedSprite.turn_right"},"game.LedSprite.turnLeft":{"kind":-1,"attributes":{"paramHelp":{"this":"the sprite to turn","degrees":"TODO"},"jsDoc":"Turn to the left (counter-clockwise)"},"parameters":[{"name":"degrees","description":"TODO"}],"isInstance":true,"pyQName":"game.LedSprite.turn_left"},"game.LedSprite.set":{"kind":-1,"attributes":{"weight":29,"help":"game/set","blockId":"game_sprite_set_property","block":"%sprite|set %property|to %value","blockGap":"8","paramHelp":{"property":"the name of the property to change","the":"updated value"},"jsDoc":"Sets a property of the sprite","_def":{"parts":[{"kind":"param","name":"sprite","ref":false},{"kind":"break"},{"kind":"label","text":"set ","style":[]},{"kind":"param","name":"property","ref":false},{"kind":"break"},{"kind":"label","text":"to ","style":[]},{"kind":"param","name":"value","ref":false}],"parameters":[{"kind":"param","name":"sprite","ref":false},{"kind":"param","name":"property","ref":false},{"kind":"param","name":"value","ref":false}]}},"parameters":[{"name":"property","description":"the name of the property to change","type":"LedSpriteProperty","isEnum":true},{"name":"value"}],"isInstance":true},"game.LedSprite.change":{"kind":-1,"attributes":{"paramDefl":{"value":"1"},"weight":30,"help":"game/change","blockId":"game_sprite_change_xy","block":"%sprite|change %property|by %value","blockGap":"8","paramHelp":{"property":"the name of the property to change","value":"amount of change, eg: 1"},"jsDoc":"Changes a property of the sprite","_def":{"parts":[{"kind":"param","name":"sprite","ref":false},{"kind":"break"},{"kind":"label","text":"change ","style":[]},{"kind":"param","name":"property","ref":false},{"kind":"break"},{"kind":"label","text":"by ","style":[]},{"kind":"param","name":"value","ref":false}],"parameters":[{"kind":"param","name":"sprite","ref":false},{"kind":"param","name":"property","ref":false},{"kind":"param","name":"value","ref":false}]}},"parameters":[{"name":"property","description":"the name of the property to change","type":"LedSpriteProperty","isEnum":true},{"name":"value","description":"amount of change, eg: 1","default":"1"}],"isInstance":true},"game.LedSprite.get":{"kind":-1,"retType":"number","attributes":{"weight":28,"help":"game/get","blockId":"game_sprite_property","block":"%sprite|%property","paramHelp":{"property":"the name of the property to change"},"jsDoc":"Gets a property of the sprite","_def":{"parts":[{"kind":"param","name":"sprite","ref":false},{"kind":"break"},{"kind":"param","name":"property","ref":false}],"parameters":[{"kind":"param","name":"sprite","ref":false},{"kind":"param","name":"property","ref":false}]}},"parameters":[{"name":"property","description":"the name of the property to change","type":"LedSpriteProperty","isEnum":true}],"isInstance":true},"game.LedSprite.setDirection":{"kind":-1,"attributes":{"parts":"ledmatrix","paramHelp":{"this":"the sprite to set direction for","degrees":"new direction in degrees"},"jsDoc":"Set the direction of the current sprite, rounded to the nearest multiple of 45"},"parameters":[{"name":"degrees","description":"new direction in degrees"}],"isInstance":true,"pyQName":"game.LedSprite.set_direction"},"game.LedSprite.x":{"kind":-1,"retType":"number","attributes":{"paramHelp":{"this":"TODO"},"jsDoc":"Reports the ``x`` position of a sprite on the LED screen"},"parameters":[],"isInstance":true},"game.LedSprite.y":{"kind":-1,"retType":"number","attributes":{"paramHelp":{"this":"TODO"},"jsDoc":"Reports the ``y`` position of a sprite on the LED screen"},"parameters":[],"isInstance":true},"game.LedSprite.direction":{"kind":-1,"retType":"number","attributes":{"paramHelp":{"this":"TODO"},"jsDoc":"Reports the current direction of a sprite"},"parameters":[],"isInstance":true},"game.LedSprite.setX":{"kind":-1,"attributes":{"paramHelp":{"this":"TODO","x":"TODO"},"jsDoc":"Set the ``x`` position of a sprite"},"parameters":[{"name":"x","description":"TODO"}],"isInstance":true,"pyQName":"game.LedSprite.set_x"},"game.LedSprite.setY":{"kind":-1,"attributes":{"paramHelp":{"this":"TODO","y":"TODO"},"jsDoc":"Set the ``y`` position of a sprite"},"parameters":[{"name":"y","description":"TODO"}],"isInstance":true,"pyQName":"game.LedSprite.set_y"},"game.LedSprite.changeYBy":{"kind":-1,"attributes":{"paramHelp":{"this":"TODO","y":"TODO"},"jsDoc":"Changes the ``y`` position by the given amount"},"parameters":[{"name":"y","description":"TODO"}],"isInstance":true,"pyQName":"game.LedSprite.change_yby"},"game.LedSprite.changeXBy":{"kind":-1,"attributes":{"paramHelp":{"this":"TODO","x":"TODO"},"jsDoc":"Changes the ``x`` position by the given amount"},"parameters":[{"name":"x","description":"TODO"}],"isInstance":true,"pyQName":"game.LedSprite.change_xby"},"game.LedSprite.isTouching":{"kind":-1,"retType":"boolean","attributes":{"weight":20,"help":"game/is-touching","blockId":"game_sprite_touching_sprite","block":"is %sprite|touching %other","blockGap":"8","paramHelp":{"this":"the sprite to check overlap or touch","other":"the other sprite to check overlap or touch"},"jsDoc":"Reports true if sprite has the same position as specified sprite","_def":{"parts":[{"kind":"label","text":"is ","style":[]},{"kind":"param","name":"sprite","ref":false},{"kind":"break"},{"kind":"label","text":"touching ","style":[]},{"kind":"param","name":"other","ref":false}],"parameters":[{"kind":"param","name":"sprite","ref":false},{"kind":"param","name":"other","ref":false}]}},"parameters":[{"name":"other","description":"the other sprite to check overlap or touch","type":"game.LedSprite"}],"isInstance":true,"pyQName":"game.LedSprite.is_touching"},"game.LedSprite.isTouchingEdge":{"kind":-1,"retType":"boolean","attributes":{"weight":19,"help":"game/is-touching-edge","blockId":"game_sprite_touching_edge","block":"is %sprite|touching edge","blockGap":"8","paramHelp":{"this":"the sprite to check for an edge contact"},"jsDoc":"Reports true if sprite is touching an edge","_def":{"parts":[{"kind":"label","text":"is ","style":[]},{"kind":"param","name":"sprite","ref":false},{"kind":"break"},{"kind":"label","text":"touching edge","style":[]}],"parameters":[{"kind":"param","name":"sprite","ref":false}]}},"parameters":[],"isInstance":true,"pyQName":"game.LedSprite.is_touching_edge"},"game.LedSprite.on":{"kind":-1,"attributes":{"paramHelp":{"this":"the sprite"},"jsDoc":"Turns on the sprite (on by default)"},"parameters":[],"isInstance":true},"game.LedSprite.off":{"kind":-1,"attributes":{"paramHelp":{"this":"the sprite"},"jsDoc":"Turns off the sprite (on by default)"},"parameters":[],"isInstance":true},"game.LedSprite.setBrightness":{"kind":-1,"attributes":{"paramDefl":{"brightness":"255."},"parts":"ledmatrix","paramHelp":{"this":"the sprite","brightness":"the brightness from 0 (off) to 255 (on), eg: 255."},"jsDoc":"Set the ``brightness`` of a sprite"},"parameters":[{"name":"brightness","description":"the brightness from 0 (off) to 255 (on), eg: 255.","default":"255."}],"isInstance":true,"pyQName":"game.LedSprite.set_brightness"},"game.LedSprite.brightness":{"kind":-1,"retType":"number","attributes":{"parts":"ledmatrix","paramHelp":{"this":"the sprite"},"jsDoc":"Reports the ``brightness` of a sprite on the LED screen"},"parameters":[],"isInstance":true},"game.LedSprite.changeBrightnessBy":{"kind":-1,"attributes":{"paramHelp":{"this":"the sprite","value":"the value to change brightness"},"jsDoc":"Changes the ``y`` position by the given amount"},"parameters":[{"name":"value","description":"the value to change brightness"}],"isInstance":true,"pyQName":"game.LedSprite.change_brightness_by"},"game.LedSprite.changeDirectionBy":{"kind":-1,"attributes":{"paramHelp":{"this":"TODO","angle":"TODO"},"jsDoc":"Changes the ``direction`` position by the given amount by turning right"},"parameters":[{"name":"angle","description":"TODO"}],"isInstance":true,"pyQName":"game.LedSprite.change_direction_by"},"game.LedSprite.delete":{"kind":-1,"attributes":{"weight":59,"blockGap":"8","help":"game/delete","blockId":"game_delete_sprite","block":"delete %this(sprite)","paramHelp":{"this":"sprite to delete"},"jsDoc":"Deletes the sprite from the game engine. The sprite will no longer appear on the screen or interact with other sprites.","_def":{"parts":[{"kind":"label","text":"delete ","style":[]},{"kind":"param","name":"this","ref":false,"varName":"sprite"}],"parameters":[{"kind":"param","name":"this","ref":false,"varName":"sprite"}]}},"parameters":[],"isInstance":true},"game.LedSprite.isDeleted":{"kind":-1,"retType":"boolean","attributes":{"weight":58,"help":"game/is-deleted","blockId":"game_sprite_is_deleted","block":"is %sprite|deleted","jsDoc":"Reports whether the sprite has been deleted from the game engine.","_def":{"parts":[{"kind":"label","text":"is ","style":[]},{"kind":"param","name":"sprite","ref":false},{"kind":"break"},{"kind":"label","text":"deleted","style":[]}],"parameters":[{"kind":"param","name":"sprite","ref":false}]}},"parameters":[],"isInstance":true,"pyQName":"game.LedSprite.is_deleted"},"game.LedSprite.setBlink":{"kind":-1,"attributes":{"paramHelp":{"sprite":"TODO","ms":"TODO"},"jsDoc":"Sets the blink duration interval in millisecond."},"parameters":[{"name":"ms","description":"TODO"}],"isInstance":true,"pyQName":"game.LedSprite.set_blink"},"game.LedSprite.changeBlinkBy":{"kind":-1,"attributes":{"paramHelp":{"this":"TODO","ms":"TODO"},"jsDoc":"Changes the ``blink`` duration by the given amount of millisecons"},"parameters":[{"name":"ms","description":"TODO"}],"isInstance":true,"pyQName":"game.LedSprite.change_blink_by"},"game.LedSprite.blink":{"kind":-1,"retType":"number","attributes":{"paramHelp":{"this":"TODO"},"jsDoc":"Reports the ``blink`` duration of a sprite"},"parameters":[],"isInstance":true},"game.invalidSprite":{"kind":-3,"retType":"game.LedSprite","attributes":{"weight":0,"jsDoc":"Gets an invalid sprite; used to initialize locals."},"parameters":[],"pyQName":"game.invalid_sprite"},"led.point":{"kind":-3,"retType":"boolean","attributes":{"help":"led/point","weight":76,"blockId":"device_point","block":"point|x %x|y %y","parts":"ledmatrix","paramMin":{"x":"0","y":"0"},"paramMax":{"x":"4","y":"4"},"paramFieldEditorOptions":{"x":{"precision":"1"},"y":{"precision":"1"}},"paramHelp":{"x":"the horizontal coordinate of the LED","y":"the vertical coordinate of the LED"},"jsDoc":"Get the on/off state of the specified LED using x, y coordinates. (0,0) is upper left.","_def":{"parts":[{"kind":"label","text":"point","style":[]},{"kind":"break"},{"kind":"label","text":"x ","style":[]},{"kind":"param","name":"x","ref":false},{"kind":"break"},{"kind":"label","text":"y ","style":[]},{"kind":"param","name":"y","ref":false}],"parameters":[{"kind":"param","name":"x","ref":false},{"kind":"param","name":"y","ref":false}]}},"parameters":[{"name":"x","description":"the horizontal coordinate of the LED","options":{"min":{"value":"0"},"max":{"value":"4"}}},{"name":"y","description":"the vertical coordinate of the LED","options":{"min":{"value":"0"},"max":{"value":"4"}}}]},"led.barGraphToConsole":{"kind":4,"retType":"boolean","attributes":{"jsDoc":"Controls where plotbargraph prints to the console"},"pyQName":"led.bar_graph_to_console"},"led.plotBarGraph":{"kind":-3,"attributes":{"paramDefl":{"valueToConsole":"true","high":"0"},"help":"led/plot-bar-graph","weight":20,"blockId":"device_plot_bar_graph","block":"plot bar graph of $value up to $high|| serial write $valueToConsole","icon":"","blockExternalInputs":"true","parts":"ledmatrix","_shadowOverrides":{"valueToConsole":"toggleOnOff"},"explicitDefaults":["valueToConsole"],"inlineInputMode":"external","paramHelp":{"value":"current value to plot","high":"maximum value. If 0, maximum value adjusted automatically, eg: 0","valueToConsole":"if true, prints value to the serial port"},"jsDoc":"Displays a vertical bar graph based on the `value` and `high` value.\nIf `high` is 0, the chart gets adjusted automatically.","_def":{"parts":[{"kind":"label","text":"plot bar graph of ","style":[]},{"kind":"param","name":"value","ref":true},{"kind":"label","text":" up to ","style":[]},{"kind":"param","name":"high","ref":true}],"parameters":[{"kind":"param","name":"value","ref":true},{"kind":"param","name":"high","ref":true}]},"_expandedDef":{"parts":[{"kind":"label","text":" serial write ","style":[]},{"kind":"param","name":"valueToConsole","shadowBlockId":"toggleOnOff","ref":true}],"parameters":[{"kind":"param","name":"valueToConsole","shadowBlockId":"toggleOnOff","ref":true}]}},"parameters":[{"name":"value","description":"current value to plot"},{"name":"high","description":"maximum value. If 0, maximum value adjusted automatically, eg: 0","default":"0"},{"name":"valueToConsole","description":"if true, prints value to the serial port","type":"boolean","initializer":"true","default":"true"}],"pyQName":"led.plot_bar_graph"},"led.toggle":{"kind":-3,"attributes":{"help":"led/toggle","weight":77,"blockId":"device_led_toggle","block":"toggle|x %x|y %y","icon":"","blockGap":"8","parts":"ledmatrix","paramMin":{"x":"0","y":"0"},"paramMax":{"x":"4","y":"4"},"paramFieldEditorOptions":{"x":{"precision":"1"},"y":{"precision":"1"}},"paramHelp":{"x":"pixel column","y":"pixel row"},"jsDoc":"Toggles a particular pixel","_def":{"parts":[{"kind":"label","text":"toggle","style":[]},{"kind":"break"},{"kind":"label","text":"x ","style":[]},{"kind":"param","name":"x","ref":false},{"kind":"break"},{"kind":"label","text":"y ","style":[]},{"kind":"param","name":"y","ref":false}],"parameters":[{"kind":"param","name":"x","ref":false},{"kind":"param","name":"y","ref":false}]}},"parameters":[{"name":"x","description":"pixel column","options":{"min":{"value":"0"},"max":{"value":"4"}}},{"name":"y","description":"pixel row","options":{"min":{"value":"0"},"max":{"value":"4"}}}]},"led.plotAll":{"kind":-3,"attributes":{"help":"led/plot-all","parts":"ledmatrix","jsDoc":"Turns all LEDS on"},"parameters":[],"pyQName":"led.plot_all"},"led.toggleAll":{"kind":-3,"attributes":{"help":"led/toggle-all","parts":"ledmatrix","jsDoc":"Inverts the current LED display"},"parameters":[],"pyQName":"led.toggle_all"},"led.fadeIn":{"kind":-3,"attributes":{"help":"led/fade-in","parts":"ledmatrix","paramHelp":{"ms":"fade time in milliseconds"},"jsDoc":"Fades in the screen display."},"parameters":[{"name":"ms","description":"fade time in milliseconds","initializer":"700"}],"pyQName":"led.fade_in"},"led.fadeOut":{"kind":-3,"attributes":{"help":"led/fade-out","parts":"ledmatrix","paramHelp":{"ms":"fade time in milliseconds"},"jsDoc":"Fades out the screen brightness."},"parameters":[{"name":"ms","description":"fade time in milliseconds","initializer":"700"}],"pyQName":"led.fade_out"},"Note":{"kind":6,"retType":"Note","extendsTypes":["Note","Number"]},"Note.C":{"retType":"Note.C","attributes":{"blockIdentity":"music.noteFrequency","enumval":"262"},"extendsTypes":["Note.C","Number"]},"Note.CSharp":{"retType":"Note.CSharp","attributes":{"block":"C#","blockIdentity":"music.noteFrequency","enumval":"277","_def":{"parts":[{"kind":"label","text":"C#","style":[]}],"parameters":[]}},"extendsTypes":["Note.CSharp","Number"],"pyQName":"Note.CSHARP"},"Note.D":{"retType":"Note.D","attributes":{"blockIdentity":"music.noteFrequency","enumval":"294"},"extendsTypes":["Note.D","Number"]},"Note.Eb":{"retType":"Note.Eb","attributes":{"blockIdentity":"music.noteFrequency","enumval":"311"},"extendsTypes":["Note.Eb","Number"],"pyQName":"Note.EB"},"Note.E":{"retType":"Note.E","attributes":{"blockIdentity":"music.noteFrequency","enumval":"330"},"extendsTypes":["Note.E","Number"]},"Note.F":{"retType":"Note.F","attributes":{"blockIdentity":"music.noteFrequency","enumval":"349"},"extendsTypes":["Note.F","Number"]},"Note.FSharp":{"retType":"Note.FSharp","attributes":{"block":"F#","blockIdentity":"music.noteFrequency","enumval":"370","_def":{"parts":[{"kind":"label","text":"F#","style":[]}],"parameters":[]}},"extendsTypes":["Note.FSharp","Number"],"pyQName":"Note.FSHARP"},"Note.G":{"retType":"Note.G","attributes":{"blockIdentity":"music.noteFrequency","enumval":"392"},"extendsTypes":["Note.G","Number"]},"Note.GSharp":{"retType":"Note.GSharp","attributes":{"block":"G#","blockIdentity":"music.noteFrequency","enumval":"415","_def":{"parts":[{"kind":"label","text":"G#","style":[]}],"parameters":[]}},"extendsTypes":["Note.GSharp","Number"],"pyQName":"Note.GSHARP"},"Note.A":{"retType":"Note.A","attributes":{"blockIdentity":"music.noteFrequency","enumval":"440"},"extendsTypes":["Note.A","Number"]},"Note.Bb":{"retType":"Note.Bb","attributes":{"blockIdentity":"music.noteFrequency","enumval":"466"},"extendsTypes":["Note.Bb","Number"],"pyQName":"Note.BB"},"Note.B":{"retType":"Note.B","attributes":{"blockIdentity":"music.noteFrequency","enumval":"494"},"extendsTypes":["Note.B","Number"]},"Note.C3":{"retType":"Note.C3","attributes":{"blockIdentity":"music.noteFrequency","enumval":"131"},"extendsTypes":["Note.C3","Number"]},"Note.CSharp3":{"retType":"Note.CSharp3","attributes":{"block":"C#3","blockIdentity":"music.noteFrequency","enumval":"139","_def":{"parts":[{"kind":"label","text":"C#3","style":[]}],"parameters":[]}},"extendsTypes":["Note.CSharp3","Number"],"pyQName":"Note.CSHARP3"},"Note.D3":{"retType":"Note.D3","attributes":{"blockIdentity":"music.noteFrequency","enumval":"147"},"extendsTypes":["Note.D3","Number"]},"Note.Eb3":{"retType":"Note.Eb3","attributes":{"blockIdentity":"music.noteFrequency","enumval":"156"},"extendsTypes":["Note.Eb3","Number"],"pyQName":"Note.EB3"},"Note.E3":{"retType":"Note.E3","attributes":{"blockIdentity":"music.noteFrequency","enumval":"165"},"extendsTypes":["Note.E3","Number"]},"Note.F3":{"retType":"Note.F3","attributes":{"blockIdentity":"music.noteFrequency","enumval":"175"},"extendsTypes":["Note.F3","Number"]},"Note.FSharp3":{"retType":"Note.FSharp3","attributes":{"block":"F#3","blockIdentity":"music.noteFrequency","enumval":"185","_def":{"parts":[{"kind":"label","text":"F#3","style":[]}],"parameters":[]}},"extendsTypes":["Note.FSharp3","Number"],"pyQName":"Note.FSHARP3"},"Note.G3":{"retType":"Note.G3","attributes":{"blockIdentity":"music.noteFrequency","enumval":"196"},"extendsTypes":["Note.G3","Number"]},"Note.GSharp3":{"retType":"Note.GSharp3","attributes":{"block":"G#3","blockIdentity":"music.noteFrequency","enumval":"208","_def":{"parts":[{"kind":"label","text":"G#3","style":[]}],"parameters":[]}},"extendsTypes":["Note.GSharp3","Number"],"pyQName":"Note.GSHARP3"},"Note.A3":{"retType":"Note.A3","attributes":{"blockIdentity":"music.noteFrequency","enumval":"220"},"extendsTypes":["Note.A3","Number"]},"Note.Bb3":{"retType":"Note.Bb3","attributes":{"blockIdentity":"music.noteFrequency","enumval":"233"},"extendsTypes":["Note.Bb3","Number"],"pyQName":"Note.BB3"},"Note.B3":{"retType":"Note.B3","attributes":{"blockIdentity":"music.noteFrequency","enumval":"247"},"extendsTypes":["Note.B3","Number"]},"Note.C4":{"retType":"Note.C","attributes":{"blockIdentity":"music.noteFrequency","enumval":"262"},"extendsTypes":["Note.C4","Number"]},"Note.CSharp4":{"retType":"Note.CSharp","attributes":{"block":"C#4","blockIdentity":"music.noteFrequency","enumval":"277","_def":{"parts":[{"kind":"label","text":"C#4","style":[]}],"parameters":[]}},"extendsTypes":["Note.CSharp4","Number"],"pyQName":"Note.CSHARP4"},"Note.D4":{"retType":"Note.D","attributes":{"blockIdentity":"music.noteFrequency","enumval":"294"},"extendsTypes":["Note.D4","Number"]},"Note.Eb4":{"retType":"Note.Eb","attributes":{"blockIdentity":"music.noteFrequency","enumval":"311"},"extendsTypes":["Note.Eb4","Number"],"pyQName":"Note.EB4"},"Note.E4":{"retType":"Note.E","attributes":{"blockIdentity":"music.noteFrequency","enumval":"330"},"extendsTypes":["Note.E4","Number"]},"Note.F4":{"retType":"Note.F","attributes":{"blockIdentity":"music.noteFrequency","enumval":"349"},"extendsTypes":["Note.F4","Number"]},"Note.FSharp4":{"retType":"Note.FSharp","attributes":{"block":"F#4","blockIdentity":"music.noteFrequency","enumval":"370","_def":{"parts":[{"kind":"label","text":"F#4","style":[]}],"parameters":[]}},"extendsTypes":["Note.FSharp4","Number"],"pyQName":"Note.FSHARP4"},"Note.G4":{"retType":"Note.G","attributes":{"blockIdentity":"music.noteFrequency","enumval":"392"},"extendsTypes":["Note.G4","Number"]},"Note.GSharp4":{"retType":"Note.GSharp","attributes":{"block":"G#4","blockIdentity":"music.noteFrequency","enumval":"415","_def":{"parts":[{"kind":"label","text":"G#4","style":[]}],"parameters":[]}},"extendsTypes":["Note.GSharp4","Number"],"pyQName":"Note.GSHARP4"},"Note.A4":{"retType":"Note.A","attributes":{"blockIdentity":"music.noteFrequency","enumval":"440"},"extendsTypes":["Note.A4","Number"]},"Note.Bb4":{"retType":"Note.Bb","attributes":{"blockIdentity":"music.noteFrequency","enumval":"466"},"extendsTypes":["Note.Bb4","Number"],"pyQName":"Note.BB4"},"Note.B4":{"retType":"Note.B","attributes":{"blockIdentity":"music.noteFrequency","enumval":"494"},"extendsTypes":["Note.B4","Number"]},"Note.C5":{"retType":"Note.C5","attributes":{"blockIdentity":"music.noteFrequency","enumval":"523"},"extendsTypes":["Note.C5","Number"]},"Note.CSharp5":{"retType":"Note.CSharp5","attributes":{"block":"C#5","blockIdentity":"music.noteFrequency","enumval":"555","_def":{"parts":[{"kind":"label","text":"C#5","style":[]}],"parameters":[]}},"extendsTypes":["Note.CSharp5","Number"],"pyQName":"Note.CSHARP5"},"Note.D5":{"retType":"Note.D5","attributes":{"blockIdentity":"music.noteFrequency","enumval":"587"},"extendsTypes":["Note.D5","Number"]},"Note.Eb5":{"retType":"Note.Eb5","attributes":{"blockIdentity":"music.noteFrequency","enumval":"622"},"extendsTypes":["Note.Eb5","Number"],"pyQName":"Note.EB5"},"Note.E5":{"retType":"Note.E5","attributes":{"blockIdentity":"music.noteFrequency","enumval":"659"},"extendsTypes":["Note.E5","Number"]},"Note.F5":{"retType":"Note.F5","attributes":{"blockIdentity":"music.noteFrequency","enumval":"698"},"extendsTypes":["Note.F5","Number"]},"Note.FSharp5":{"retType":"Note.FSharp5","attributes":{"block":"F#5","blockIdentity":"music.noteFrequency","enumval":"740","_def":{"parts":[{"kind":"label","text":"F#5","style":[]}],"parameters":[]}},"extendsTypes":["Note.FSharp5","Number"],"pyQName":"Note.FSHARP5"},"Note.G5":{"retType":"Note.G5","attributes":{"blockIdentity":"music.noteFrequency","enumval":"784"},"extendsTypes":["Note.G5","Number"]},"Note.GSharp5":{"retType":"Note.GSharp5","attributes":{"block":"G#5","blockIdentity":"music.noteFrequency","enumval":"831","_def":{"parts":[{"kind":"label","text":"G#5","style":[]}],"parameters":[]}},"extendsTypes":["Note.GSharp5","Number"],"pyQName":"Note.GSHARP5"},"Note.A5":{"retType":"Note.A5","attributes":{"blockIdentity":"music.noteFrequency","enumval":"880"},"extendsTypes":["Note.A5","Number"]},"Note.Bb5":{"retType":"Note.Bb5","attributes":{"blockIdentity":"music.noteFrequency","enumval":"932"},"extendsTypes":["Note.Bb5","Number"],"pyQName":"Note.BB5"},"Note.B5":{"retType":"Note.B5","attributes":{"blockIdentity":"music.noteFrequency","enumval":"988"},"extendsTypes":["Note.B5","Number"]},"BeatFraction":{"kind":6,"retType":"BeatFraction","extendsTypes":["BeatFraction","Number"]},"BeatFraction.Whole":{"retType":"BeatFraction.Whole","attributes":{"block":"1","_def":{"parts":[{"kind":"label","text":"1","style":[]}],"parameters":[]}},"extendsTypes":["BeatFraction.Whole","Number"],"pyQName":"BeatFraction.WHOLE"},"BeatFraction.Half":{"retType":"BeatFraction.Half","attributes":{"block":"1/2","_def":{"parts":[{"kind":"label","text":"1/2","style":[]}],"parameters":[]}},"extendsTypes":["BeatFraction.Half","Number"],"pyQName":"BeatFraction.HALF"},"BeatFraction.Quarter":{"retType":"BeatFraction.Quarter","attributes":{"block":"1/4","_def":{"parts":[{"kind":"label","text":"1/4","style":[]}],"parameters":[]}},"extendsTypes":["BeatFraction.Quarter","Number"],"pyQName":"BeatFraction.QUARTER"},"BeatFraction.Eighth":{"retType":"BeatFraction.Eighth","attributes":{"block":"1/8","_def":{"parts":[{"kind":"label","text":"1/8","style":[]}],"parameters":[]}},"extendsTypes":["BeatFraction.Eighth","Number"],"pyQName":"BeatFraction.EIGHTH"},"BeatFraction.Sixteenth":{"retType":"BeatFraction.Sixteenth","attributes":{"block":"1/16","_def":{"parts":[{"kind":"label","text":"1/16","style":[]}],"parameters":[]}},"extendsTypes":["BeatFraction.Sixteenth","Number"],"pyQName":"BeatFraction.SIXTEENTH"},"BeatFraction.Double":{"retType":"BeatFraction.Double","attributes":{"block":"2","_def":{"parts":[{"kind":"label","text":"2","style":[]}],"parameters":[]}},"extendsTypes":["BeatFraction.Double","Number"],"pyQName":"BeatFraction.DOUBLE"},"BeatFraction.Breve":{"retType":"BeatFraction.Breve","attributes":{"block":"4","_def":{"parts":[{"kind":"label","text":"4","style":[]}],"parameters":[]}},"extendsTypes":["BeatFraction.Breve","Number"],"pyQName":"BeatFraction.BREVE"},"MelodyOptions":{"kind":6,"retType":"MelodyOptions","extendsTypes":["MelodyOptions","Number"]},"MelodyOptions.Once":{"retType":"MelodyOptions.Once","attributes":{"block":"once","_def":{"parts":[{"kind":"label","text":"once","style":[]}],"parameters":[]}},"extendsTypes":["MelodyOptions.Once","Number"],"pyQName":"MelodyOptions.ONCE"},"MelodyOptions.Forever":{"retType":"MelodyOptions.Forever","attributes":{"block":"forever","_def":{"parts":[{"kind":"label","text":"forever","style":[]}],"parameters":[]}},"extendsTypes":["MelodyOptions.Forever","Number"],"pyQName":"MelodyOptions.FOREVER"},"MelodyOptions.OnceInBackground":{"retType":"MelodyOptions.OnceInBackground","attributes":{"block":"once in background","_def":{"parts":[{"kind":"label","text":"once in background","style":[]}],"parameters":[]}},"extendsTypes":["MelodyOptions.OnceInBackground","Number"],"pyQName":"MelodyOptions.ONCE_IN_BACKGROUND"},"MelodyOptions.ForeverInBackground":{"retType":"MelodyOptions.ForeverInBackground","attributes":{"block":"forever in background","_def":{"parts":[{"kind":"label","text":"forever in background","style":[]}],"parameters":[]}},"extendsTypes":["MelodyOptions.ForeverInBackground","Number"],"pyQName":"MelodyOptions.FOREVER_IN_BACKGROUND"},"MelodyStopOptions":{"kind":6,"retType":"MelodyStopOptions","extendsTypes":["MelodyStopOptions","Number"]},"MelodyStopOptions.All":{"retType":"MelodyStopOptions","attributes":{"block":"all","_def":{"parts":[{"kind":"label","text":"all","style":[]}],"parameters":[]}},"extendsTypes":["MelodyStopOptions.All","Number"],"pyQName":"MelodyStopOptions.ALL"},"MelodyStopOptions.Foreground":{"retType":"MelodyStopOptions","attributes":{"block":"foreground","_def":{"parts":[{"kind":"label","text":"foreground","style":[]}],"parameters":[]}},"extendsTypes":["MelodyStopOptions.Foreground","Number"],"pyQName":"MelodyStopOptions.FOREGROUND"},"MelodyStopOptions.Background":{"retType":"MelodyStopOptions","attributes":{"block":"background","_def":{"parts":[{"kind":"label","text":"background","style":[]}],"parameters":[]}},"extendsTypes":["MelodyStopOptions.Background","Number"],"pyQName":"MelodyStopOptions.BACKGROUND"},"MusicEvent":{"kind":6,"retType":"MusicEvent","extendsTypes":["MusicEvent","Number"]},"MusicEvent.MelodyNotePlayed":{"retType":"MusicEvent","attributes":{"block":"melody note played","_def":{"parts":[{"kind":"label","text":"melody note played","style":[]}],"parameters":[]}},"extendsTypes":["MusicEvent.MelodyNotePlayed","Number"],"pyQName":"MusicEvent.MELODY_NOTE_PLAYED"},"MusicEvent.MelodyStarted":{"retType":"MusicEvent","attributes":{"block":"melody started","_def":{"parts":[{"kind":"label","text":"melody started","style":[]}],"parameters":[]}},"extendsTypes":["MusicEvent.MelodyStarted","Number"],"pyQName":"MusicEvent.MELODY_STARTED"},"MusicEvent.MelodyEnded":{"retType":"MusicEvent","attributes":{"block":"melody ended","_def":{"parts":[{"kind":"label","text":"melody ended","style":[]}],"parameters":[]}},"extendsTypes":["MusicEvent.MelodyEnded","Number"],"pyQName":"MusicEvent.MELODY_ENDED"},"MusicEvent.MelodyRepeated":{"retType":"MusicEvent","attributes":{"block":"melody repeated","_def":{"parts":[{"kind":"label","text":"melody repeated","style":[]}],"parameters":[]}},"extendsTypes":["MusicEvent.MelodyRepeated","Number"],"pyQName":"MusicEvent.MELODY_REPEATED"},"MusicEvent.BackgroundMelodyNotePlayed":{"retType":"MusicEvent","attributes":{"block":"background melody note played","_def":{"parts":[{"kind":"label","text":"background melody note played","style":[]}],"parameters":[]}},"extendsTypes":["MusicEvent.BackgroundMelodyNotePlayed","Number"],"pyQName":"MusicEvent.BACKGROUND_MELODY_NOTE_PLAYED"},"MusicEvent.BackgroundMelodyStarted":{"retType":"MusicEvent","attributes":{"block":"background melody started","_def":{"parts":[{"kind":"label","text":"background melody started","style":[]}],"parameters":[]}},"extendsTypes":["MusicEvent.BackgroundMelodyStarted","Number"],"pyQName":"MusicEvent.BACKGROUND_MELODY_STARTED"},"MusicEvent.BackgroundMelodyEnded":{"retType":"MusicEvent","attributes":{"block":"background melody ended","_def":{"parts":[{"kind":"label","text":"background melody ended","style":[]}],"parameters":[]}},"extendsTypes":["MusicEvent.BackgroundMelodyEnded","Number"],"pyQName":"MusicEvent.BACKGROUND_MELODY_ENDED"},"MusicEvent.BackgroundMelodyRepeated":{"retType":"MusicEvent","attributes":{"block":"background melody repeated","_def":{"parts":[{"kind":"label","text":"background melody repeated","style":[]}],"parameters":[]}},"extendsTypes":["MusicEvent.BackgroundMelodyRepeated","Number"],"pyQName":"MusicEvent.BACKGROUND_MELODY_REPEATED"},"MusicEvent.BackgroundMelodyPaused":{"retType":"MusicEvent","attributes":{"block":"background melody paused","_def":{"parts":[{"kind":"label","text":"background melody paused","style":[]}],"parameters":[]}},"extendsTypes":["MusicEvent.BackgroundMelodyPaused","Number"],"pyQName":"MusicEvent.BACKGROUND_MELODY_PAUSED"},"MusicEvent.BackgroundMelodyResumed":{"retType":"MusicEvent","attributes":{"block":"background melody resumed","_def":{"parts":[{"kind":"label","text":"background melody resumed","style":[]}],"parameters":[]}},"extendsTypes":["MusicEvent.BackgroundMelodyResumed","Number"],"pyQName":"MusicEvent.BACKGROUND_MELODY_RESUMED"},"music.playTone":{"kind":-3,"attributes":{"paramDefl":{"frequency":"Note.C"},"help":"music/play-tone","weight":90,"blockId":"device_play_note","block":"play|tone %note=device_note|for %duration=device_beat","blockGap":"8","parts":"headphone","useEnumVal":"1","group":"Tone","deprecated":"1","paramHelp":{"frequency":"pitch of the tone to play in Hertz (Hz), eg: Note.C","ms":"tone duration in milliseconds (ms)"},"jsDoc":"Plays a tone through pin ``P0`` for the given duration.","_def":{"parts":[{"kind":"label","text":"play","style":[]},{"kind":"break"},{"kind":"label","text":"tone ","style":[]},{"kind":"param","name":"note","shadowBlockId":"device_note","ref":false},{"kind":"break"},{"kind":"label","text":"for ","style":[]},{"kind":"param","name":"duration","shadowBlockId":"device_beat","ref":false}],"parameters":[{"kind":"param","name":"note","shadowBlockId":"device_note","ref":false},{"kind":"param","name":"duration","shadowBlockId":"device_beat","ref":false}]}},"parameters":[{"name":"frequency","description":"pitch of the tone to play in Hertz (Hz), eg: Note.C","default":"Note.C"},{"name":"ms","description":"tone duration in milliseconds (ms)"}],"pyQName":"music.play_tone"},"music.ringTone":{"kind":-3,"attributes":{"paramDefl":{"frequency":"Note.C"},"help":"music/ring-tone","weight":80,"blockId":"device_ring","block":"ring tone (Hz)|%note=device_note","blockGap":"8","parts":"headphone","useEnumVal":"1","group":"Tone","paramHelp":{"frequency":"pitch of the tone to play in Hertz (Hz), eg: Note.C"},"jsDoc":"Plays a tone through pin ``P0``.","_def":{"parts":[{"kind":"label","text":"ring tone (Hz)","style":[]},{"kind":"break"},{"kind":"param","name":"note","shadowBlockId":"device_note","ref":false}],"parameters":[{"kind":"param","name":"note","shadowBlockId":"device_note","ref":false}]}},"parameters":[{"name":"frequency","description":"pitch of the tone to play in Hertz (Hz), eg: Note.C","default":"Note.C"}],"pyQName":"music.ring_tone"},"music.rest":{"kind":-3,"attributes":{"help":"music/rest","weight":79,"blockId":"device_rest","block":"rest for |%duration=device_beat","parts":"headphone","group":"Tone","paramHelp":{"ms":"rest duration in milliseconds (ms)"},"jsDoc":"Rests (plays nothing) for a specified time through pin ``P0``.","_def":{"parts":[{"kind":"label","text":"rest for ","style":[]},{"kind":"break"},{"kind":"param","name":"duration","shadowBlockId":"device_beat","ref":false}],"parameters":[{"kind":"param","name":"duration","shadowBlockId":"device_beat","ref":false}]}},"parameters":[{"name":"ms","description":"rest duration in milliseconds (ms)"}]},"music.noteFrequency":{"kind":-3,"retType":"number","attributes":{"paramDefl":{"name":"262"},"weight":50,"help":"music/note-frequency","blockId":"device_note","block":"%name","shim":"TD_ID","color":"#FFFFFF","colorSecondary":"#FFFFFF","paramFieldEditor":{"name":"note"},"explicitDefaults":["name"],"paramFieldEditorOptions":{"name":{"decompileLiterals":"true"}},"useEnumVal":"1","group":"Tone","blockGap":"8","paramHelp":{"name":"the note name"},"jsDoc":"Gets the frequency of a note.","_def":{"parts":[{"kind":"param","name":"name","ref":false}],"parameters":[{"kind":"param","name":"name","ref":false}]}},"parameters":[{"name":"name","description":"the note name","type":"Note","initializer":"262","default":"262","isEnum":true}],"pyQName":"music.note_frequency"},"music.beat":{"kind":-3,"retType":"number","attributes":{"help":"music/beat","weight":49,"blockId":"device_beat","block":"%fraction|beat","group":"Tempo","blockGap":"8","jsDoc":"Returns the duration of a beat in milli-seconds","_def":{"parts":[{"kind":"param","name":"fraction","ref":false},{"kind":"break"},{"kind":"label","text":"beat","style":[]}],"parameters":[{"kind":"param","name":"fraction","ref":false}]}},"parameters":[{"name":"fraction","type":"BeatFraction","initializer":"undefined","isEnum":true}]},"music.tempo":{"kind":-3,"retType":"number","attributes":{"help":"music/tempo","weight":40,"blockId":"device_tempo","block":"tempo (bpm)","blockGap":"8","group":"Tempo","jsDoc":"Returns the tempo in beats per minute. Tempo is the speed (bpm = beats per minute) at which notes play. The larger the tempo value, the faster the notes will play.","_def":{"parts":[{"kind":"label","text":"tempo (bpm)","style":[]}],"parameters":[]}},"parameters":[]},"music.changeTempoBy":{"kind":-3,"attributes":{"paramDefl":{"bpm":"20"},"help":"music/change-tempo-by","weight":100,"blockId":"device_change_tempo","block":"change tempo by (bpm)|%value","blockGap":"8","group":"Tempo","paramHelp":{"bpm":"The change in beats per minute to the tempo, eg: 20"},"jsDoc":"Change the tempo by the specified amount","_def":{"parts":[{"kind":"label","text":"change tempo by (bpm)","style":[]},{"kind":"break"},{"kind":"param","name":"value","ref":false}],"parameters":[{"kind":"param","name":"value","ref":false}]}},"parameters":[{"name":"bpm","description":"The change in beats per minute to the tempo, eg: 20","default":"20"}],"pyQName":"music.change_tempo_by"},"music.setTempo":{"kind":-3,"attributes":{"paramDefl":{"bpm":"120"},"help":"music/set-tempo","weight":99,"blockId":"device_set_tempo","block":"set tempo to (bpm)|%value","paramMin":{"bpm":"40"},"paramMax":{"bpm":"500"},"group":"Tempo","paramHelp":{"bpm":"The new tempo in beats per minute, eg: 120"},"jsDoc":"Sets the tempo to the specified amount","_def":{"parts":[{"kind":"label","text":"set tempo to (bpm)","style":[]},{"kind":"break"},{"kind":"param","name":"value","ref":false}],"parameters":[{"kind":"param","name":"value","ref":false}]}},"parameters":[{"name":"bpm","description":"The new tempo in beats per minute, eg: 120","default":"120","options":{"min":{"value":"40"},"max":{"value":"500"}}}],"pyQName":"music.set_tempo"},"music.builtInMelody":{"kind":-3,"retType":"string[]","attributes":{"paramDefl":{"name":"Note.C"},"weight":50,"help":"music/built-in-melody","blockId":"device_builtin_melody","block":"%melody","blockHidden":true,"group":"Melody Advanced","deprecated":"1","paramHelp":{"name":"the note name, eg: Note.C"},"jsDoc":"Gets the melody array of a built-in melody.","_def":{"parts":[{"kind":"param","name":"melody","ref":false}],"parameters":[{"kind":"param","name":"melody","ref":false}]}},"parameters":[{"name":"melody","type":"Melodies","isEnum":true}],"pyQName":"music.built_in_melody"},"music.builtInPlayableMelody":{"kind":-3,"retType":"music.StringArrayPlayable","attributes":{"weight":60,"help":"music/built-in-playable-melody","blockId":"device_builtin_melody_playable","block":"melody $melody","toolboxParent":"music_playable_play_default_bkg","toolboxParentArgument":"toPlay","duplicateShadowOnDrag":true,"group":"Melody Advanced","paramHelp":{"melody":"the melody name"},"jsDoc":"Gets the melody array of a built-in melody.","_def":{"parts":[{"kind":"label","text":"melody ","style":[]},{"kind":"param","name":"melody","ref":true}],"parameters":[{"kind":"param","name":"melody","ref":true}]}},"parameters":[{"name":"melody","description":"the melody name","type":"Melodies","isEnum":true}],"pyQName":"music.built_in_playable_melody"},"music.onEvent":{"kind":-3,"attributes":{"blockId":"melody_on_event","block":"music on %value","help":"music/on-event","weight":59,"blockGap":"32","group":"Melody Advanced","jsDoc":"Registers code to run on various melody events","_def":{"parts":[{"kind":"label","text":"music on ","style":[]},{"kind":"param","name":"value","ref":false}],"parameters":[{"kind":"param","name":"value","ref":false}]}},"parameters":[{"name":"value","type":"MusicEvent","isEnum":true},{"name":"handler","type":"() => void","handlerParameters":[]}],"pyQName":"music.on_event"},"music.beginMelody":{"kind":-3,"attributes":{"hidden":"1","deprecated":"1","parts":"headphone","group":"Melody Advanced","jsDoc":"Use startMelody instead"},"parameters":[{"name":"melodyArray","type":"string[]"},{"name":"options","type":"MelodyOptions","initializer":"1","isEnum":true}],"pyQName":"music.begin_melody"},"music.startMelody":{"kind":-3,"attributes":{"help":"music/begin-melody","weight":60,"blockGap":"16","blockId":"device_start_melody","block":"start melody %melody=device_builtin_melody| repeating %options","parts":"headphone","group":"Melody Advanced","deprecated":"1","paramHelp":{"melodyArray":"the melody array to play","options":"melody options, once / forever, in the foreground / background"},"jsDoc":"Starts playing a melody.\nNotes are expressed as a string of characters with this format: NOTE[octave][:duration]","_def":{"parts":[{"kind":"label","text":"start melody ","style":[]},{"kind":"param","name":"melody","shadowBlockId":"device_builtin_melody","ref":false},{"kind":"break"},{"kind":"label","text":" repeating ","style":[]},{"kind":"param","name":"options","ref":false}],"parameters":[{"kind":"param","name":"melody","shadowBlockId":"device_builtin_melody","ref":false},{"kind":"param","name":"options","ref":false}]}},"parameters":[{"name":"melodyArray","description":"the melody array to play","type":"string[]"},{"name":"options","description":"melody options, once / forever, in the foreground / background","type":"MelodyOptions","initializer":"1","isEnum":true}],"pyQName":"music.start_melody"},"music.playMelody":{"kind":-3,"attributes":{"paramDefl":{"tempo":"120"},"block":"play melody $melody at tempo $tempo|(bpm)","blockId":"playMelody","weight":85,"blockGap":"8","help":"music/play-melody","_shadowOverrides":{"melody":"melody_editor"},"paramMin":{"tempo":"40"},"paramMax":{"tempo":"500"},"explicitDefaults":["tempo"],"parts":"headphone","group":"Melody","deprecated":"1","paramHelp":{"melody":"string of up to eight notes [C D E F G A B C5] or rests [-] separated by spaces, which will be played one at a time, ex: \"E D G F B A C5 B \"","tempo":"number in beats per minute (bpm), dictating how long each note will play for"},"jsDoc":"Play a melody from the melody editor.","_def":{"parts":[{"kind":"label","text":"play melody ","style":[]},{"kind":"param","name":"melody","shadowBlockId":"melody_editor","ref":true},{"kind":"label","text":" at tempo ","style":[]},{"kind":"param","name":"tempo","ref":true},{"kind":"break"},{"kind":"label","text":"(bpm)","style":[]}],"parameters":[{"kind":"param","name":"melody","shadowBlockId":"melody_editor","ref":true},{"kind":"param","name":"tempo","ref":true}]}},"parameters":[{"name":"melody","description":"string of up to eight notes [C D E F G A B C5] or rests [-] separated by spaces, which will be played one at a time, ex: \"E D G F B A C5 B \"","type":"string"},{"name":"tempo","description":"number in beats per minute (bpm), dictating how long each note will play for","initializer":"120","default":"120","options":{"min":{"value":"40"},"max":{"value":"500"}}}],"pyQName":"music.play_melody"},"music.startMelodyInternal":{"kind":-3,"parameters":[{"name":"melodyArray","type":"string[]"},{"name":"options","type":"MelodyOptions","isEnum":true}],"pyQName":"music.start_melody_internal"},"music.waitForMelodyEnd":{"kind":-3,"parameters":[],"pyQName":"music.wait_for_melody_end"},"music.getMelodyNotes":{"kind":-3,"retType":"string[]","parameters":[{"name":"melody","type":"string"}],"pyQName":"music.get_melody_notes"},"music.melodyEditor":{"kind":-3,"retType":"string","attributes":{"block":"$melody","blockId":"melody_editor","blockHidden":true,"weight":85,"blockGap":"8","duplicateShadowOnDrag":true,"paramFieldEditor":{"melody":"melody"},"paramFieldEditorOptions":{"melody":{"decompileLiterals":"true","decompileIndirectFixedInstances":"true","onParentBlock":"true"}},"shim":"TD_ID","group":"Melody","paramHelp":{"melody":""},"jsDoc":"Create a melody with the melody editor.","_def":{"parts":[{"kind":"param","name":"melody","ref":true}],"parameters":[{"kind":"param","name":"melody","ref":true}]}},"parameters":[{"name":"melody","type":"string"}],"pyQName":"music.melody_editor"},"music.stopMelody":{"kind":-3,"attributes":{"help":"music/stop-melody","weight":59,"blockGap":"16","blockId":"device_stop_melody","block":"stop melody $options","parts":"headphone","group":"Melody Advanced","paramHelp":{"options":"which melody to stop"},"jsDoc":"Stops the melodies","_def":{"parts":[{"kind":"label","text":"stop melody ","style":[]},{"kind":"param","name":"options","ref":true}],"parameters":[{"kind":"param","name":"options","ref":true}]}},"parameters":[{"name":"options","description":"which melody to stop","type":"MelodyStopOptions","isEnum":true}],"pyQName":"music.stop_melody"},"music._onStopSound":{"kind":-3,"parameters":[{"name":"handler","type":"() => void","handlerParameters":[]}],"pyQName":"music._on_stop_sound"},"music.stopAllSounds":{"kind":-3,"attributes":{"help":"music/stop-all-sounds","blockId":"music_stop_all_sounds","block":"stop all sounds","weight":10,"group":"Volume","jsDoc":"Stop all sounds and melodies currently playing.","_def":{"parts":[{"kind":"label","text":"stop all sounds","style":[]}],"parameters":[]}},"parameters":[],"pyQName":"music.stop_all_sounds"},"music.setPlayTone":{"kind":-3,"attributes":{"help":"music/set-play-tone","advanced":true,"group":"Tone","jsDoc":"Sets a custom playTone function for playing melodies"},"parameters":[{"name":"f","type":"(frequency: number, duration: number) => void","handlerParameters":[{"name":"frequency","type":"number"},{"name":"duration","type":"number"}]}],"pyQName":"music.set_play_tone"},"music.getFrequencyForNote":{"kind":-3,"retType":"number","attributes":{"paramHelp":{"note":"The offset of the note within the octave"},"jsDoc":"Converts an octave and note offset into an integer frequency.\nReturns 0 if the note is out of range.\n* @param octave    The octave of the note (1 - 8)\n\n@returns         A frequency in HZ or 0 if out of range"},"parameters":[{"name":"octave"},{"name":"note","description":"The offset of the note within the octave"}],"pyQName":"music.get_frequency_for_note"},"music._bufferToMelody":{"kind":-3,"retType":"string[]","parameters":[{"name":"melody","type":"Buffer"}],"pyQName":"music._buffer_to_melody"},"Melodies":{"kind":6,"retType":"Melodies","extendsTypes":["Melodies","Number"]},"Melodies.Dadadadum":{"retType":"Melodies.Dadadadum","attributes":{"block":"dadadum","blockIdentity":"music.builtInMelody","_def":{"parts":[{"kind":"label","text":"dadadum","style":[]}],"parameters":[]}},"extendsTypes":["Melodies.Dadadadum","Number"],"pyQName":"Melodies.DADADADUM"},"Melodies.Entertainer":{"retType":"Melodies.Entertainer","attributes":{"block":"entertainer","blockIdentity":"music.builtInMelody","_def":{"parts":[{"kind":"label","text":"entertainer","style":[]}],"parameters":[]}},"extendsTypes":["Melodies.Entertainer","Number"],"pyQName":"Melodies.ENTERTAINER"},"Melodies.Prelude":{"retType":"Melodies.Prelude","attributes":{"block":"prelude","blockIdentity":"music.builtInMelody","_def":{"parts":[{"kind":"label","text":"prelude","style":[]}],"parameters":[]}},"extendsTypes":["Melodies.Prelude","Number"],"pyQName":"Melodies.PRELUDE"},"Melodies.Ode":{"retType":"Melodies.Ode","attributes":{"block":"ode","blockIdentity":"music.builtInMelody","_def":{"parts":[{"kind":"label","text":"ode","style":[]}],"parameters":[]}},"extendsTypes":["Melodies.Ode","Number"],"pyQName":"Melodies.ODE"},"Melodies.Nyan":{"retType":"Melodies.Nyan","attributes":{"block":"nyan","blockIdentity":"music.builtInMelody","_def":{"parts":[{"kind":"label","text":"nyan","style":[]}],"parameters":[]}},"extendsTypes":["Melodies.Nyan","Number"],"pyQName":"Melodies.NYAN"},"Melodies.Ringtone":{"retType":"Melodies.Ringtone","attributes":{"block":"ringtone","blockIdentity":"music.builtInMelody","_def":{"parts":[{"kind":"label","text":"ringtone","style":[]}],"parameters":[]}},"extendsTypes":["Melodies.Ringtone","Number"],"pyQName":"Melodies.RINGTONE"},"Melodies.Funk":{"retType":"Melodies.Funk","attributes":{"block":"funk","blockIdentity":"music.builtInMelody","_def":{"parts":[{"kind":"label","text":"funk","style":[]}],"parameters":[]}},"extendsTypes":["Melodies.Funk","Number"],"pyQName":"Melodies.FUNK"},"Melodies.Blues":{"retType":"Melodies.Blues","attributes":{"block":"blues","blockIdentity":"music.builtInMelody","_def":{"parts":[{"kind":"label","text":"blues","style":[]}],"parameters":[]}},"extendsTypes":["Melodies.Blues","Number"],"pyQName":"Melodies.BLUES"},"Melodies.Birthday":{"retType":"Melodies.Birthday","attributes":{"block":"birthday","blockIdentity":"music.builtInMelody","_def":{"parts":[{"kind":"label","text":"birthday","style":[]}],"parameters":[]}},"extendsTypes":["Melodies.Birthday","Number"],"pyQName":"Melodies.BIRTHDAY"},"Melodies.Wedding":{"retType":"Melodies.Wedding","attributes":{"block":"wedding","blockIdentity":"music.builtInMelody","_def":{"parts":[{"kind":"label","text":"wedding","style":[]}],"parameters":[]}},"extendsTypes":["Melodies.Wedding","Number"],"pyQName":"Melodies.WEDDING"},"Melodies.Funeral":{"retType":"Melodies.Funeral","attributes":{"block":"funeral","blockIdentity":"music.builtInMelody","_def":{"parts":[{"kind":"label","text":"funeral","style":[]}],"parameters":[]}},"extendsTypes":["Melodies.Funeral","Number"],"pyQName":"Melodies.FUNERAL"},"Melodies.Punchline":{"retType":"Melodies.Punchline","attributes":{"block":"punchline","blockIdentity":"music.builtInMelody","_def":{"parts":[{"kind":"label","text":"punchline","style":[]}],"parameters":[]}},"extendsTypes":["Melodies.Punchline","Number"],"pyQName":"Melodies.PUNCHLINE"},"Melodies.Baddy":{"retType":"Melodies.Baddy","attributes":{"block":"baddy","blockIdentity":"music.builtInMelody","_def":{"parts":[{"kind":"label","text":"baddy","style":[]}],"parameters":[]}},"extendsTypes":["Melodies.Baddy","Number"],"pyQName":"Melodies.BADDY"},"Melodies.Chase":{"retType":"Melodies.Chase","attributes":{"block":"chase","blockIdentity":"music.builtInMelody","_def":{"parts":[{"kind":"label","text":"chase","style":[]}],"parameters":[]}},"extendsTypes":["Melodies.Chase","Number"],"pyQName":"Melodies.CHASE"},"Melodies.BaDing":{"retType":"Melodies.BaDing","attributes":{"block":"ba ding","blockIdentity":"music.builtInMelody","_def":{"parts":[{"kind":"label","text":"ba ding","style":[]}],"parameters":[]}},"extendsTypes":["Melodies.BaDing","Number"],"pyQName":"Melodies.BA_DING"},"Melodies.Wawawawaa":{"retType":"Melodies.Wawawawaa","attributes":{"block":"wawawawaa","blockIdentity":"music.builtInMelody","_def":{"parts":[{"kind":"label","text":"wawawawaa","style":[]}],"parameters":[]}},"extendsTypes":["Melodies.Wawawawaa","Number"],"pyQName":"Melodies.WAWAWAWAA"},"Melodies.JumpUp":{"retType":"Melodies.JumpUp","attributes":{"block":"jump up","blockIdentity":"music.builtInMelody","_def":{"parts":[{"kind":"label","text":"jump up","style":[]}],"parameters":[]}},"extendsTypes":["Melodies.JumpUp","Number"],"pyQName":"Melodies.JUMP_UP"},"Melodies.JumpDown":{"retType":"Melodies.JumpDown","attributes":{"block":"jump down","blockIdentity":"music.builtInMelody","_def":{"parts":[{"kind":"label","text":"jump down","style":[]}],"parameters":[]}},"extendsTypes":["Melodies.JumpDown","Number"],"pyQName":"Melodies.JUMP_DOWN"},"Melodies.PowerUp":{"retType":"Melodies.PowerUp","attributes":{"block":"power up","blockIdentity":"music.builtInMelody","_def":{"parts":[{"kind":"label","text":"power up","style":[]}],"parameters":[]}},"extendsTypes":["Melodies.PowerUp","Number"],"pyQName":"Melodies.POWER_UP"},"Melodies.PowerDown":{"retType":"Melodies.PowerDown","attributes":{"block":"power down","blockIdentity":"music.builtInMelody","_def":{"parts":[{"kind":"label","text":"power down","style":[]}],"parameters":[]}},"extendsTypes":["Melodies.PowerDown","Number"],"pyQName":"Melodies.POWER_DOWN"},"music.getMelody":{"kind":-3,"retType":"string[]","parameters":[{"name":"melody","type":"Melodies","isEnum":true}],"pyQName":"music.get_melody"},"music._getMelodyBuffer":{"kind":-3,"retType":"Buffer","parameters":[{"name":"melody","type":"Melodies","isEnum":true}],"pyQName":"music._get_melody_buffer"},"pins._digitalPin":{"kind":-3,"retType":"number","attributes":{"help":"pins/digital-pin","shim":"TD_ID","blockId":"digital_pin","block":"digital pin $pin","paramFieldEditor":{"pin":"pinpicker"},"paramFieldEditorOptions":{"pin":{"columns":"4","tooltips":"false"}},"group":"Pins","weight":17,"blockGap":"8","advanced":true,"decompilerShadowAlias":"digital_pin_shadow","jsDoc":"Returns the value of a C++ runtime constant","_def":{"parts":[{"kind":"label","text":"digital pin ","style":[]},{"kind":"param","name":"pin","ref":true}],"parameters":[{"kind":"param","name":"pin","ref":true}]}},"parameters":[{"name":"pin","type":"DigitalPin","isEnum":true}],"pyQName":"pins._digital_pin"},"pins._analogPin":{"kind":-3,"retType":"number","attributes":{"help":"pins/analog-pin","shim":"TD_ID","blockId":"analog_pin","block":"analog pin $pin","paramFieldEditor":{"pin":"pinpicker"},"paramFieldEditorOptions":{"pin":{"columns":"4","tooltips":"false"}},"group":"Pins","weight":16,"blockGap":"8","advanced":true,"decompilerShadowAlias":"analog_pin_shadow","jsDoc":"Returns the value of a C++ runtime constant","_def":{"parts":[{"kind":"label","text":"analog pin ","style":[]},{"kind":"param","name":"pin","ref":true}],"parameters":[{"kind":"param","name":"pin","ref":true}]}},"parameters":[{"name":"pin","type":"AnalogPin","isEnum":true}],"pyQName":"pins._analog_pin"},"pins._digitalPinShadow":{"kind":-3,"retType":"number","attributes":{"help":"pins/digital-pin","shim":"TD_ID","blockId":"digital_pin_shadow","block":"$pin","paramFieldEditor":{"pin":"pinpicker"},"paramFieldEditorOptions":{"pin":{"columns":"4","tooltips":"false"}},"blockHidden":true,"jsDoc":"Returns the value of a C++ runtime constant","_def":{"parts":[{"kind":"param","name":"pin","ref":true}],"parameters":[{"kind":"param","name":"pin","ref":true}]}},"parameters":[{"name":"pin","type":"DigitalPin","isEnum":true}],"pyQName":"pins._digital_pin_shadow"},"pins._analogPinShadow":{"kind":-3,"retType":"number","attributes":{"help":"pins/analog-pin","shim":"TD_ID","blockId":"analog_pin_shadow","block":"$pin","paramFieldEditor":{"pin":"pinpicker"},"paramFieldEditorOptions":{"pin":{"columns":"4","tooltips":"false"}},"blockHidden":true,"jsDoc":"Returns the value of a C++ runtime constant","_def":{"parts":[{"kind":"param","name":"pin","ref":true}],"parameters":[{"kind":"param","name":"pin","ref":true}]}},"parameters":[{"name":"pin","type":"AnalogPin","isEnum":true}],"pyQName":"pins._analog_pin_shadow"},"pins._analogReadWritePinShadow":{"kind":-3,"retType":"number","attributes":{"help":"pins/analog-pin","shim":"TD_ID","blockId":"analog_read_write_pin_shadow","block":"$pin","paramFieldEditor":{"pin":"pinpicker"},"paramFieldEditorOptions":{"pin":{"columns":"4","tooltips":"false"}},"blockHidden":true,"jsDoc":"Returns the value of a C++ runtime constant","_def":{"parts":[{"kind":"param","name":"pin","ref":true}],"parameters":[{"kind":"param","name":"pin","ref":true}]}},"parameters":[{"name":"pin","type":"AnalogReadWritePin","isEnum":true}],"pyQName":"pins._analog_read_write_pin_shadow"},"pins.map":{"kind":-3,"retType":"number","attributes":{"paramDefl":{"fromHigh":"1023","toHigh":"4"},"help":"pins/map","weight":23,"blockId":"pin_map","block":"map %value|from low %fromLow|from high %fromHigh|to low %toLow|to high %toHigh","paramHelp":{"value":"value to map in ranges","fromLow":"the lower bound of the value's current range","fromHigh":"the upper bound of the value's current range, eg: 1023","toLow":"the lower bound of the value's target range","toHigh":"the upper bound of the value's target range, eg: 4"},"jsDoc":"Map a number from one range to another. That is, a value of ``from low`` would get mapped to ``to low``, a value of ``from high`` to ``to high``, values in-between to values in-between, etc.","_def":{"parts":[{"kind":"label","text":"map ","style":[]},{"kind":"param","name":"value","ref":false},{"kind":"break"},{"kind":"label","text":"from low ","style":[]},{"kind":"param","name":"fromLow","ref":false},{"kind":"break"},{"kind":"label","text":"from high ","style":[]},{"kind":"param","name":"fromHigh","ref":false},{"kind":"break"},{"kind":"label","text":"to low ","style":[]},{"kind":"param","name":"toLow","ref":false},{"kind":"break"},{"kind":"label","text":"to high ","style":[]},{"kind":"param","name":"toHigh","ref":false}],"parameters":[{"kind":"param","name":"value","ref":false},{"kind":"param","name":"fromLow","ref":false},{"kind":"param","name":"fromHigh","ref":false},{"kind":"param","name":"toLow","ref":false},{"kind":"param","name":"toHigh","ref":false}]}},"parameters":[{"name":"value","description":"value to map in ranges"},{"name":"fromLow","description":"the lower bound of the value's current range"},{"name":"fromHigh","description":"the upper bound of the value's current range, eg: 1023","default":"1023"},{"name":"toLow","description":"the lower bound of the value's target range"},{"name":"toHigh","description":"the upper bound of the value's target range, eg: 4","default":"4"}]},"pins.i2cReadNumber":{"kind":-3,"retType":"number","attributes":{"help":"pins/i2c-read-number","blockGap":"8","advanced":true,"blockId":"pins_i2c_readnumber","block":"i2c read number|at address %address|of format %format|repeated %repeat","weight":45,"group":"I2C","jsDoc":"Read one number from 7-bit I2C address.","_def":{"parts":[{"kind":"label","text":"i2c read number","style":[]},{"kind":"break"},{"kind":"label","text":"at address ","style":[]},{"kind":"param","name":"address","ref":false},{"kind":"break"},{"kind":"label","text":"of format ","style":[]},{"kind":"param","name":"format","ref":false},{"kind":"break"},{"kind":"label","text":"repeated ","style":[]},{"kind":"param","name":"repeat","ref":false}],"parameters":[{"kind":"param","name":"address","ref":false},{"kind":"param","name":"format","ref":false},{"kind":"param","name":"repeat","ref":false}]}},"parameters":[{"name":"address"},{"name":"format","type":"NumberFormat","isEnum":true},{"name":"repeated","type":"boolean","initializer":"undefined"}],"pyQName":"pins.i2c_read_number"},"pins.i2cWriteNumber":{"kind":-3,"attributes":{"help":"pins/i2c-write-number","blockGap":"8","advanced":true,"blockId":"i2c_writenumber","block":"i2c write number|at address %address|with value %value|of format %format|repeated %repeat","weight":44,"group":"I2C","jsDoc":"Write one number to a 7-bit I2C address.","_def":{"parts":[{"kind":"label","text":"i2c write number","style":[]},{"kind":"break"},{"kind":"label","text":"at address ","style":[]},{"kind":"param","name":"address","ref":false},{"kind":"break"},{"kind":"label","text":"with value ","style":[]},{"kind":"param","name":"value","ref":false},{"kind":"break"},{"kind":"label","text":"of format ","style":[]},{"kind":"param","name":"format","ref":false},{"kind":"break"},{"kind":"label","text":"repeated ","style":[]},{"kind":"param","name":"repeat","ref":false}],"parameters":[{"kind":"param","name":"address","ref":false},{"kind":"param","name":"value","ref":false},{"kind":"param","name":"format","ref":false},{"kind":"param","name":"repeat","ref":false}]}},"parameters":[{"name":"address"},{"name":"value"},{"name":"format","type":"NumberFormat","isEnum":true},{"name":"repeated","type":"boolean","initializer":"undefined"}],"pyQName":"pins.i2c_write_number"},"Delimiters":{"kind":6,"retType":"Delimiters","extendsTypes":["Delimiters","Number"]},"Delimiters.NewLine":{"retType":"Delimiters.NewLine","attributes":{"block":"new line (\n)","_def":{"parts":[{"kind":"label","text":"new line (\n)","style":[]}],"parameters":[]}},"extendsTypes":["Delimiters.NewLine","Number"],"pyQName":"Delimiters.NEW_LINE"},"Delimiters.Comma":{"retType":"Delimiters.Comma","attributes":{"block":",","_def":{"parts":[{"kind":"label","text":",","style":[]}],"parameters":[]}},"extendsTypes":["Delimiters.Comma","Number"],"pyQName":"Delimiters.COMMA"},"Delimiters.Dollar":{"retType":"Delimiters.Dollar","attributes":{"block":"$","_def":{"parts":[{"kind":"param","name":"","ref":true}],"parameters":[{"kind":"param","name":"","ref":true}]}},"extendsTypes":["Delimiters.Dollar","Number"],"pyQName":"Delimiters.DOLLAR"},"Delimiters.Colon":{"retType":"Delimiters.Colon","attributes":{"block":":","_def":{"parts":[{"kind":"label","text":":","style":[]}],"parameters":[]}},"extendsTypes":["Delimiters.Colon","Number"],"pyQName":"Delimiters.COLON"},"Delimiters.Fullstop":{"retType":"Delimiters.Fullstop","attributes":{"block":".","_def":{"parts":[{"kind":"label","text":".","style":[]}],"parameters":[]}},"extendsTypes":["Delimiters.Fullstop","Number"],"pyQName":"Delimiters.FULLSTOP"},"Delimiters.Hash":{"retType":"Delimiters.Hash","attributes":{"block":"#","_def":{"parts":[{"kind":"label","text":"#","style":[]}],"parameters":[]}},"extendsTypes":["Delimiters.Hash","Number"],"pyQName":"Delimiters.HASH"},"Delimiters.CarriageReturn":{"retType":"Delimiters.CarriageReturn","attributes":{"block":"carriage return (\r)","_def":{"parts":[{"kind":"label","text":"carriage return (\r)","style":[]}],"parameters":[]}},"extendsTypes":["Delimiters.CarriageReturn","Number"],"pyQName":"Delimiters.CARRIAGE_RETURN"},"Delimiters.Space":{"retType":"Delimiters.Space","attributes":{"block":"space","_def":{"parts":[{"kind":"label","text":"space","style":[]}],"parameters":[]}},"extendsTypes":["Delimiters.Space","Number"],"pyQName":"Delimiters.SPACE"},"Delimiters.Tab":{"retType":"Delimiters.Tab","attributes":{"block":"tab (\t)","_def":{"parts":[{"kind":"label","text":"tab (\t)","style":[]}],"parameters":[]}},"extendsTypes":["Delimiters.Tab","Number"],"pyQName":"Delimiters.TAB"},"Delimiters.Pipe":{"retType":"Delimiters.Pipe","attributes":{"block":"|","_def":{"parts":[{"kind":"break"}],"parameters":[]}},"extendsTypes":["Delimiters.Pipe","Number"],"pyQName":"Delimiters.PIPE"},"Delimiters.SemiColon":{"retType":"Delimiters.SemiColon","attributes":{"block":";","_def":{"parts":[{"kind":"label","text":";","style":[]}],"parameters":[]}},"extendsTypes":["Delimiters.SemiColon","Number"],"pyQName":"Delimiters.SEMI_COLON"},"serial.NEW_LINE":{"kind":4,"retType":"string","attributes":{"jsDoc":"The string used to mark a new line, default is \\r\\n"}},"serial.NEW_LINE_DELIMITER":{"kind":4,"retType":"Delimiters"},"serial.writeLine":{"kind":-3,"attributes":{"weight":90,"help":"serial/write-line","blockGap":"8","blockId":"serial_writeline","block":"serial|write line %text","paramShadowOptions":{"text":{"toString":"true"}},"paramHelp":{"value":"to send over serial"},"jsDoc":"Print a line of text to the serial port","_def":{"parts":[{"kind":"label","text":"serial","style":[]},{"kind":"break"},{"kind":"label","text":"write line ","style":[]},{"kind":"param","name":"text","ref":false}],"parameters":[{"kind":"param","name":"text","ref":false}]}},"parameters":[{"name":"text","type":"string","options":{"fieldEditorOptions":{"value":{"toString":"true"}}}}],"pyQName":"serial.write_line"},"serial.setWriteLinePadding":{"kind":-3,"attributes":{"paramDefl":{"length":"0"},"weight":1,"help":"serial/set-write-line-padding","blockId":"serialWriteNewLinePadding","block":"serial set write line padding to $length","advanced":true,"paramMin":{"length":"0"},"paramMax":{"length":"128"},"paramHelp":{"length":"the number of bytes alignment, eg: 0"},"jsDoc":"Sets the padding length for lines sent with \"write line\".","_def":{"parts":[{"kind":"label","text":"serial set write line padding to ","style":[]},{"kind":"param","name":"length","ref":true}],"parameters":[{"kind":"param","name":"length","ref":true}]}},"parameters":[{"name":"length","description":"the number of bytes alignment, eg: 0","default":"0","options":{"min":{"value":"0"},"max":{"value":"128"}}}],"pyQName":"serial.set_write_line_padding"},"serial.writeNumber":{"kind":-3,"attributes":{"help":"serial/write-number","weight":89,"blockGap":"8","blockId":"serial_writenumber","block":"serial|write number %value","jsDoc":"Print a numeric value to the serial port","_def":{"parts":[{"kind":"label","text":"serial","style":[]},{"kind":"break"},{"kind":"label","text":"write number ","style":[]},{"kind":"param","name":"value","ref":false}],"parameters":[{"kind":"param","name":"value","ref":false}]}},"parameters":[{"name":"value"}],"pyQName":"serial.write_number"},"serial.writeNumbers":{"kind":-3,"attributes":{"help":"serial/write-numbers","weight":86,"blockId":"serial_writenumbers","block":"serial|write numbers %values","jsDoc":"Print an array of numeric values as CSV to the serial port","_def":{"parts":[{"kind":"label","text":"serial","style":[]},{"kind":"break"},{"kind":"label","text":"write numbers ","style":[]},{"kind":"param","name":"values","ref":false}],"parameters":[{"kind":"param","name":"values","ref":false}]}},"parameters":[{"name":"values","type":"number[]"}],"pyQName":"serial.write_numbers"},"serial.writeValue":{"kind":-3,"attributes":{"paramDefl":{"name":"x"},"weight":88,"blockGap":"8","help":"serial/write-value","blockId":"serial_writevalue","block":"serial|write value %name|= %value","paramHelp":{"name":"name of the value stream, eg: x","value":"to write"},"jsDoc":"Write a name:value pair as a line to the serial port.","_def":{"parts":[{"kind":"label","text":"serial","style":[]},{"kind":"break"},{"kind":"label","text":"write value ","style":[]},{"kind":"param","name":"name","ref":false},{"kind":"break"},{"kind":"label","text":"= ","style":[]},{"kind":"param","name":"value","ref":false}],"parameters":[{"kind":"param","name":"name","ref":false},{"kind":"param","name":"value","ref":false}]}},"parameters":[{"name":"name","description":"name of the value stream, eg: x","type":"string","default":"x"},{"name":"value","description":"to write"}],"pyQName":"serial.write_value"},"serial.readLine":{"kind":-3,"retType":"string","attributes":{"help":"serial/read-line","blockId":"serial_read_line","block":"serial|read line","weight":20,"blockGap":"8","jsDoc":"Read a line of text from the serial port.","_def":{"parts":[{"kind":"label","text":"serial","style":[]},{"kind":"break"},{"kind":"label","text":"read line","style":[]}],"parameters":[]}},"parameters":[],"pyQName":"serial.read_line"},"serial.delimiters":{"kind":-3,"retType":"string","attributes":{"blockId":"serial_delimiter_conv","block":"%del","weight":1,"blockHidden":true,"jsDoc":"Return the corresponding delimiter string","_def":{"parts":[{"kind":"param","name":"del","ref":false}],"parameters":[{"kind":"param","name":"del","ref":false}]}},"parameters":[{"name":"del","type":"Delimiters","isEnum":true}]},"pins.sizeOf":{"kind":-3,"retType":"number","attributes":{"deprecated":"1"},"parameters":[{"name":"format","type":"NumberFormat","isEnum":true}],"pyQName":"pins.size_of"},"pins.createBufferFromArray":{"kind":-3,"retType":"Buffer","attributes":{"deprecated":"1"},"parameters":[{"name":"bytes","type":"number[]"}],"pyQName":"bytes"},"pins.packedSize":{"kind":-3,"retType":"number","attributes":{"deprecated":"1"},"parameters":[{"name":"format","type":"string"}],"pyQName":"pins.packed_size"},"pins.packBuffer":{"kind":-3,"retType":"Buffer","attributes":{"deprecated":"1"},"parameters":[{"name":"format","type":"string"},{"name":"nums","type":"number[]"}],"pyQName":"pins.pack_buffer"},"pins.packIntoBuffer":{"kind":-3,"attributes":{"deprecated":"1"},"parameters":[{"name":"format","type":"string"},{"name":"buf","type":"Buffer"},{"name":"offset"},{"name":"nums","type":"number[]"}],"pyQName":"pins.pack_into_buffer"},"pins.unpackBuffer":{"kind":-3,"retType":"number[]","attributes":{"deprecated":"1"},"parameters":[{"name":"format","type":"string"},{"name":"buf","type":"Buffer"},{"name":"offset","initializer":"0"}],"pyQName":"pins.unpack_buffer"},"pins.concatBuffers":{"kind":-3,"retType":"Buffer","attributes":{"deprecated":"1"},"parameters":[{"name":"bufs","type":"Buffer[]"}],"pyQName":"pins.concat_buffers"},"msgpack":{"kind":5,"retType":""},"msgpack.unpackNumberArray":{"kind":-3,"retType":"number[]","attributes":{"jsDoc":"Unpacks a buffer into a number array."},"parameters":[{"name":"buf","type":"Buffer"},{"name":"offset","initializer":"0"}],"pyQName":"msgpack.unpack_number_array"},"msgpack.packNumberArray":{"kind":-3,"retType":"Buffer","attributes":{"paramHelp":{"nums":"the numbers to be packed"},"jsDoc":"Pack a number array into a buffer."},"parameters":[{"name":"nums","description":"the numbers to be packed","type":"number[]"}],"pyQName":"msgpack.pack_number_array"},"helpers.bufferConcat":{"kind":-3,"retType":"Buffer","parameters":[{"name":"a","type":"Buffer"},{"name":"b","type":"Buffer"}],"pyQName":"helpers.buffer_concat"},"helpers.bufferEquals":{"kind":-3,"retType":"boolean","parameters":[{"name":"l","type":"Buffer"},{"name":"r","type":"Buffer"}],"pyQName":"helpers.buffer_equals"},"helpers.bufferIndexOf":{"kind":-3,"retType":"number","parameters":[{"name":"a","type":"Buffer"},{"name":"b","type":"Buffer"}],"pyQName":"helpers.buffer_index_of"},"helpers.bufferUnpack":{"kind":-3,"retType":"number[]","parameters":[{"name":"buf","type":"Buffer"},{"name":"format","type":"string"},{"name":"offset","initializer":"undefined"}],"pyQName":"helpers.buffer_unpack"},"helpers.bufferPackAt":{"kind":-3,"parameters":[{"name":"buf","type":"Buffer"},{"name":"offset"},{"name":"format","type":"string"},{"name":"nums","type":"number[]"}],"pyQName":"helpers.buffer_pack_at"},"helpers.bufferChunked":{"kind":-3,"retType":"Buffer[]","parameters":[{"name":"buf","type":"Buffer"},{"name":"maxBytes"}],"pyQName":"helpers.buffer_chunked"},"helpers.bufferToArray":{"kind":-3,"retType":"number[]","parameters":[{"name":"buf","type":"Buffer"},{"name":"format","type":"NumberFormat","isEnum":true}],"pyQName":"helpers.buffer_to_array"},"helpers._b64":{"kind":4,"retType":"\"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/\""},"helpers.bufferToBase64":{"kind":-3,"retType":"string","parameters":[{"name":"buf","type":"Buffer"}],"pyQName":"helpers.buffer_to_base64"},"Buffer.concat":{"kind":-3,"retType":"Buffer","attributes":{"helper":"bufferConcat","jsDoc":"Return concatenation of current buffer and the given buffer\n\nConcatenates all buffers in the list"},"parameters":[{"name":"buffers","type":"Buffer[]"}]},"Buffer.indexOf":{"kind":-1,"retType":"number","attributes":{"helper":"bufferIndexOf","jsDoc":"Return position of other buffer in current buffer"},"parameters":[{"name":"other","type":"Buffer"}],"isInstance":true,"pyQName":"Buffer.index_of"},"Buffer.unpack":{"kind":-1,"retType":"number[]","attributes":{"helper":"bufferUnpack","jsDoc":"Reads numbers from the buffer according to the format"},"parameters":[{"name":"format","type":"string"},{"name":"offset","initializer":"undefined"}],"isInstance":true},"Buffer.packAt":{"kind":-1,"attributes":{"helper":"bufferPackAt","jsDoc":"Writes numbers to the buffer according to the format"},"parameters":[{"name":"offset"},{"name":"format","type":"string"},{"name":"nums","type":"number[]"}],"isInstance":true,"pyQName":"Buffer.pack_at"},"Buffer.equals":{"kind":-1,"retType":"boolean","attributes":{"helper":"bufferEquals","jsDoc":"Returns true if this and the other buffer hold the same data"},"parameters":[{"name":"other","type":"Buffer"}],"isInstance":true},"Buffer.chunked":{"kind":-1,"retType":"Buffer[]","attributes":{"helper":"bufferChunked","jsDoc":"Splits buffer into parts no larger than specified"},"parameters":[{"name":"maxSize"}],"isInstance":true},"Buffer.toArray":{"kind":-1,"retType":"number[]","attributes":{"helper":"bufferToArray","jsDoc":"Read contents of buffer as an array in specified format"},"parameters":[{"name":"format","type":"NumberFormat","isEnum":true}],"isInstance":true,"pyQName":"Buffer.to_array"},"Buffer.toBase64":{"kind":-1,"retType":"string","attributes":{"helper":"bufferToBase64","jsDoc":"Convert buffer to ASCII base64 encoding."},"parameters":[],"isInstance":true,"pyQName":"Buffer.to_base64"},"Buffer@type":{"kind":9,"retType":"Buffer","attributes":{"indexerGet":"BufferMethods::getByte","indexerSet":"BufferMethods::setByte"},"extendsTypes":[],"pyQName":"Buffer"},"Buffer.create":{"kind":-3,"retType":"Buffer","attributes":{"paramHelp":{"size":"number of bytes in the buffer"},"jsDoc":"Allocate a new buffer."},"parameters":[{"name":"size","description":"number of bytes in the buffer"}]},"Buffer.fromHex":{"kind":-3,"retType":"Buffer","attributes":{"jsDoc":"Create a new buffer, decoding a hex string"},"parameters":[{"name":"hex","type":"string"}],"pyQName":"Buffer.from_hex"},"Buffer.fromBase64":{"kind":-3,"retType":"Buffer","attributes":{"jsDoc":"Create a new buffer, decoding a Base64 string"},"parameters":[{"name":"b64","type":"string"}],"pyQName":"Buffer.from_base64"},"Buffer.fromUTF8":{"kind":-3,"retType":"Buffer","attributes":{"paramHelp":{"str":"the string to put in the buffer"},"jsDoc":"Create a new buffer from an UTF8-encoded string"},"parameters":[{"name":"str","description":"the string to put in the buffer","type":"string"}],"pyQName":"Buffer.from_utf8"},"Buffer.chunkedFromUTF8":{"kind":-3,"retType":"Buffer[]","parameters":[{"name":"str","type":"string"},{"name":"maxBytes"}],"pyQName":"Buffer.chunked_from_utf8"},"Buffer.fromArray":{"kind":-3,"retType":"Buffer","attributes":{"paramHelp":{"bytes":"data to initialize with"},"jsDoc":"Create a new buffer initialized to bytes from given array."},"parameters":[{"name":"bytes","description":"data to initialize with","type":"number[]"}],"pyQName":"Buffer.from_array"},"Buffer.packedSize":{"kind":-3,"retType":"number","parameters":[{"name":"format","type":"string"}],"pyQName":"Buffer.packed_size"},"Buffer.pack":{"kind":-3,"retType":"Buffer","parameters":[{"name":"format","type":"string"},{"name":"nums","type":"number[]"}]},"Buffer.__packUnpackCore":{"kind":-3,"retType":"number","parameters":[{"name":"format","type":"string"},{"name":"nums","type":"number[]"},{"name":"buf","type":"Buffer"},{"name":"isPack","type":"boolean"},{"name":"off","initializer":"0"}]},"Buffer.sizeOfNumberFormat":{"kind":-3,"retType":"number","attributes":{"jsDoc":"Get the size in bytes of specified number format."},"parameters":[{"name":"format","type":"NumberFormat","isEnum":true}],"pyQName":"Buffer.size_of_number_format"},"JSON":{"kind":5,"retType":""},"JSON.parseIntRadix":{"kind":-3,"retType":"number","parameters":[{"name":"s","type":"string"},{"name":"base","initializer":"undefined"}],"pyQName":"JSON.parse_int_radix"},"JSON.stringify":{"kind":-3,"retType":"string","attributes":{"paramHelp":{"value":"A JavaScript value, usually an object or array, to be converted.","replacer":"Not supported; use null.","indent":"Adds indentation, white space, and line break characters to the return-value JSON text to make it easier to read."},"jsDoc":"Converts a JavaScript value to a JavaScript Object Notation (JSON) string."},"parameters":[{"name":"value","description":"A JavaScript value, usually an object or array, to be converted.","type":"any"},{"name":"replacer","description":"Not supported; use null.","type":"any","initializer":"null"},{"name":"indent","description":"Adds indentation, white space, and line break characters to the return-value JSON text to make it easier to read.","initializer":"0"}]},"JSON.parse":{"kind":-3,"retType":"any","attributes":{"paramHelp":{"text":"A valid JSON string."},"jsDoc":"Converts a JavaScript Object Notation (JSON) string into an object."},"parameters":[{"name":"s","type":"string"}]},"control.__queuePollEvent":{"kind":-3,"parameters":[{"name":"timeOut"},{"name":"condition","type":"() => boolean","handlerParameters":[]},{"name":"handler","type":"() => void","handlerParameters":[]}]},"pauseUntil":{"kind":-3,"attributes":{"blockId":"pxt_pause_until","paramHelp":{"condition":"condition to test for","timeOut":"if positive, maximum duration to wait for in milliseconds"},"jsDoc":"Busy wait for a condition to be true"},"parameters":[{"name":"condition","description":"condition to test for","type":"() => boolean","handlerParameters":[]},{"name":"timeOut","description":"if positive, maximum duration to wait for in milliseconds","initializer":"undefined"}],"pyQName":"pause_until"},"control.simmessages":{"kind":5,"retType":""},"control.simmessages.CONTROL_MESSAGE_EVT_ID":{"kind":4,"retType":"number"},"control.simmessages.CONTROL_MESSAGE_RECEIVED":{"kind":4,"retType":"number"},"control.simmessages.send":{"kind":-3,"parameters":[{"name":"channel","type":"string"},{"name":"message","type":"Buffer"},{"name":"parentOnly","type":"boolean","initializer":"undefined"}]},"control.simmessages.onReceived":{"kind":-3,"attributes":{"jsDoc":"Registers the handler for a message on a given channel"},"parameters":[{"name":"channel","type":"string"},{"name":"handler","type":"(msg: Buffer) => void","handlerParameters":[{"name":"msg","type":"Buffer"}]}],"pyQName":"control.simmessages.on_received"},"Fx8":{"kind":-3,"retType":"Fx8","parameters":[{"name":"v"}],"pyQName":"fx8"},"Fx8._dummyFx8":{"kind":2,"retType":"string","isInstance":true,"pyQName":"fx8._dummy_fx8"},"Fx8@type":{"kind":9,"retType":"Fx8","extendsTypes":[],"pyQName":"Fx8"},"Fx":{"kind":5,"retType":""},"Fx.zeroFx8":{"kind":4,"retType":"Fx8","pyQName":"Fx.zero_fx8"},"Fx.oneHalfFx8":{"kind":4,"retType":"Fx8","pyQName":"Fx.one_half_fx8"},"Fx.oneFx8":{"kind":4,"retType":"Fx8","pyQName":"Fx.one_fx8"},"Fx.twoFx8":{"kind":4,"retType":"Fx8","pyQName":"Fx.two_fx8"},"Fx.neg":{"kind":-3,"retType":"Fx8","parameters":[{"name":"a","type":"Fx8"}]},"Fx.toIntShifted":{"kind":-3,"retType":"number","parameters":[{"name":"a","type":"Fx8"},{"name":"n"}],"pyQName":"Fx.to_int_shifted"},"Fx.add":{"kind":-3,"retType":"Fx8","parameters":[{"name":"a","type":"Fx8"},{"name":"b","type":"Fx8"}]},"Fx.iadd":{"kind":-3,"retType":"Fx8","parameters":[{"name":"a"},{"name":"b","type":"Fx8"}]},"Fx.sub":{"kind":-3,"retType":"Fx8","parameters":[{"name":"a","type":"Fx8"},{"name":"b","type":"Fx8"}]},"Fx.mul":{"kind":-3,"retType":"Fx8","parameters":[{"name":"a","type":"Fx8"},{"name":"b","type":"Fx8"}]},"Fx.imul":{"kind":-3,"retType":"Fx8","parameters":[{"name":"a","type":"Fx8"},{"name":"b"}]},"Fx.div":{"kind":-3,"retType":"Fx8","parameters":[{"name":"a","type":"Fx8"},{"name":"b","type":"Fx8"}]},"Fx.idiv":{"kind":-3,"retType":"Fx8","parameters":[{"name":"a","type":"Fx8"},{"name":"b"}]},"Fx.compare":{"kind":-3,"retType":"number","parameters":[{"name":"a","type":"Fx8"},{"name":"b","type":"Fx8"}]},"Fx.abs":{"kind":-3,"retType":"Fx8","parameters":[{"name":"a","type":"Fx8"}]},"Fx.min":{"kind":-3,"retType":"Fx8","parameters":[{"name":"a","type":"Fx8"},{"name":"b","type":"Fx8"}]},"Fx.max":{"kind":-3,"retType":"Fx8","parameters":[{"name":"a","type":"Fx8"},{"name":"b","type":"Fx8"}]},"Fx.floor":{"kind":-3,"retType":"Fx8","parameters":[{"name":"v","type":"Fx8"}]},"Fx.ceil":{"kind":-3,"retType":"Fx8","parameters":[{"name":"v","type":"Fx8"}]},"Fx.leftShift":{"kind":-3,"retType":"Fx8","parameters":[{"name":"a","type":"Fx8"},{"name":"n"}],"pyQName":"Fx.left_shift"},"Fx.rightShift":{"kind":-3,"retType":"Fx8","parameters":[{"name":"a","type":"Fx8"},{"name":"n"}],"pyQName":"Fx.right_shift"},"Fx.toInt":{"kind":-3,"retType":"number","parameters":[{"name":"v","type":"Fx8"}],"pyQName":"Fx.to_int"},"Fx.toFloat":{"kind":-3,"retType":"number","parameters":[{"name":"v","type":"Fx8"}],"pyQName":"Fx.to_float"},"hex":{"kind":-3,"retType":"Buffer","attributes":{"shim":"@hex","jsDoc":"Tagged hex literal converter"},"parameters":[{"name":"lits","type":"any"},{"name":"args","type":"any[]"}]},"loops":{"kind":5,"retType":""},"loops.everyInterval":{"kind":-3,"attributes":{"weight":45,"blockAllowMultiple":"1","_shadowOverrides":{"interval":"longTimePicker"},"afterOnStart":true,"help":"loops/every-interval","blockId":"every_interval","block":"every $interval ms","paramHelp":{"interval":"time (in ms) to wait between each iteration of the action.","body":"code to execute"},"jsDoc":"Repeats the code forever in the background.\nAfter each iteration, allows other codes to run for a set duration\nso that it runs on a timer","_def":{"parts":[{"kind":"label","text":"every ","style":[]},{"kind":"param","name":"interval","shadowBlockId":"longTimePicker","ref":true},{"kind":"label","text":" ms","style":[]}],"parameters":[{"kind":"param","name":"interval","shadowBlockId":"longTimePicker","ref":true}]}},"parameters":[{"name":"interval","description":"time (in ms) to wait between each iteration of the action."},{"name":"a","type":"() => void","handlerParameters":[]}],"pyQName":"loops.every_interval"},"loops.__timePicker":{"kind":-3,"retType":"number","attributes":{"paramDefl":{"ms":"500"},"blockId":"longTimePicker","block":"%ms","blockHidden":true,"shim":"TD_ID","colorSecondary":"#FFFFFF","paramFieldEditor":{"ms":"numberdropdown"},"paramFieldEditorOptions":{"ms":{"decompileLiterals":"true","data":"[[\"100 ms\", 100], [\"200 ms\", 200], [\"500 ms\", 500], [\"1 second\", 1000], [\"1 minute\", 60000], [\"1 hour\", 3600000]]"}},"paramHelp":{"ms":"time duration in milliseconds, eg: 500, 1000"},"jsDoc":"Get the time field editor","_def":{"parts":[{"kind":"param","name":"ms","ref":false}],"parameters":[{"kind":"param","name":"ms","ref":false}]}},"parameters":[{"name":"ms","description":"time duration in milliseconds, eg: 500, 1000","default":"500"}]},"SoundExpression":{"kind":8,"retType":"SoundExpression","attributes":{"fixedInstances":"true","blockNamespace":"music","group":"micro:bit (V2)","jsDoc":"A sound expression."},"extendsTypes":["SoundExpression","music.Playable"]},"SoundExpression.__constructor":{"kind":-3,"parameters":[{"name":"notes","type":"string"}],"isInstance":true},"SoundExpression._play":{"kind":-1,"parameters":[{"name":"mode","type":"music.PlaybackMode","isEnum":true}],"isInstance":true},"SoundExpression.play":{"kind":-1,"attributes":{"block":"play sound $this","weight":80,"blockGap":"8","help":"music/play","group":"micro:bit (V2)","parts":"builtinspeaker","deprecated":"1","jsDoc":"Starts to play a sound expression.","_def":{"parts":[{"kind":"label","text":"play sound ","style":[]},{"kind":"param","name":"this","ref":true}],"parameters":[{"kind":"param","name":"this","ref":true}]}},"parameters":[],"isInstance":true},"SoundExpression.playUntilDone":{"kind":-1,"attributes":{"block":"play sound $this until done","weight":81,"blockGap":"8","help":"music/play-until-done","group":"micro:bit (V2)","parts":"builtinspeaker","deprecated":"1","jsDoc":"Plays a sound expression until finished","_def":{"parts":[{"kind":"label","text":"play sound ","style":[]},{"kind":"param","name":"this","ref":true},{"kind":"label","text":" until done","style":[]}],"parameters":[{"kind":"param","name":"this","ref":true}]}},"parameters":[],"isInstance":true,"pyQName":"SoundExpression.play_until_done"},"SoundExpression.getNotes":{"kind":-1,"retType":"string","parameters":[],"isInstance":true,"pyQName":"SoundExpression.get_notes"},"WaveShape":{"kind":6,"retType":"WaveShape","extendsTypes":["WaveShape","Number"]},"WaveShape.Sine":{"retType":"WaveShape.Sine","attributes":{"block":"sine","_def":{"parts":[{"kind":"label","text":"sine","style":[]}],"parameters":[]}},"extendsTypes":["WaveShape.Sine","Number"],"pyQName":"WaveShape.SINE"},"WaveShape.Sawtooth":{"retType":"WaveShape.Sawtooth","attributes":{"block":"sawtooth","_def":{"parts":[{"kind":"label","text":"sawtooth","style":[]}],"parameters":[]}},"extendsTypes":["WaveShape.Sawtooth","Number"],"pyQName":"WaveShape.SAWTOOTH"},"WaveShape.Triangle":{"retType":"WaveShape.Triangle","attributes":{"block":"triangle","_def":{"parts":[{"kind":"label","text":"triangle","style":[]}],"parameters":[]}},"extendsTypes":["WaveShape.Triangle","Number"],"pyQName":"WaveShape.TRIANGLE"},"WaveShape.Square":{"retType":"WaveShape.Square","attributes":{"block":"square","_def":{"parts":[{"kind":"label","text":"square","style":[]}],"parameters":[]}},"extendsTypes":["WaveShape.Square","Number"],"pyQName":"WaveShape.SQUARE"},"WaveShape.Noise":{"retType":"WaveShape.Noise","attributes":{"block":"noise","_def":{"parts":[{"kind":"label","text":"noise","style":[]}],"parameters":[]}},"extendsTypes":["WaveShape.Noise","Number"],"pyQName":"WaveShape.NOISE"},"InterpolationCurve":{"kind":6,"retType":"InterpolationCurve","extendsTypes":["InterpolationCurve","Number"]},"InterpolationCurve.Linear":{"retType":"InterpolationCurve.Linear","attributes":{"block":"linear","_def":{"parts":[{"kind":"label","text":"linear","style":[]}],"parameters":[]}},"extendsTypes":["InterpolationCurve.Linear","Number"],"pyQName":"InterpolationCurve.LINEAR"},"InterpolationCurve.Curve":{"retType":"InterpolationCurve.Curve","attributes":{"block":"curve","_def":{"parts":[{"kind":"label","text":"curve","style":[]}],"parameters":[]}},"extendsTypes":["InterpolationCurve.Curve","Number"],"pyQName":"InterpolationCurve.CURVE"},"InterpolationCurve.Logarithmic":{"retType":"InterpolationCurve.Logarithmic","attributes":{"block":"logarithmic","_def":{"parts":[{"kind":"label","text":"logarithmic","style":[]}],"parameters":[]}},"extendsTypes":["InterpolationCurve.Logarithmic","Number"],"pyQName":"InterpolationCurve.LOGARITHMIC"},"SoundExpressionEffect":{"kind":6,"retType":"SoundExpressionEffect","extendsTypes":["SoundExpressionEffect","Number"]},"SoundExpressionEffect.None":{"retType":"SoundExpressionEffect.None","attributes":{"block":"none","_def":{"parts":[{"kind":"label","text":"none","style":[]}],"parameters":[]}},"extendsTypes":["SoundExpressionEffect.None","Number"],"pyQName":"SoundExpressionEffect.NONE"},"SoundExpressionEffect.Vibrato":{"retType":"SoundExpressionEffect.Vibrato","attributes":{"block":"vibrato","_def":{"parts":[{"kind":"label","text":"vibrato","style":[]}],"parameters":[]}},"extendsTypes":["SoundExpressionEffect.Vibrato","Number"],"pyQName":"SoundExpressionEffect.VIBRATO"},"SoundExpressionEffect.Tremolo":{"retType":"SoundExpressionEffect.Tremolo","attributes":{"block":"tremolo","_def":{"parts":[{"kind":"label","text":"tremolo","style":[]}],"parameters":[]}},"extendsTypes":["SoundExpressionEffect.Tremolo","Number"],"pyQName":"SoundExpressionEffect.TREMOLO"},"SoundExpressionEffect.Warble":{"retType":"SoundExpressionEffect.Warble","attributes":{"block":"warble","_def":{"parts":[{"kind":"label","text":"warble","style":[]}],"parameters":[]}},"extendsTypes":["SoundExpressionEffect.Warble","Number"],"pyQName":"SoundExpressionEffect.WARBLE"},"SoundExpressionPlayMode":{"kind":6,"retType":"SoundExpressionPlayMode","extendsTypes":["SoundExpressionPlayMode","Number"]},"SoundExpressionPlayMode.UntilDone":{"retType":"SoundExpressionPlayMode.UntilDone","attributes":{"block":"until done","_def":{"parts":[{"kind":"label","text":"until done","style":[]}],"parameters":[]}},"extendsTypes":["SoundExpressionPlayMode.UntilDone","Number"],"pyQName":"SoundExpressionPlayMode.UNTIL_DONE"},"SoundExpressionPlayMode.InBackground":{"retType":"SoundExpressionPlayMode.InBackground","attributes":{"block":"in background","_def":{"parts":[{"kind":"label","text":"in background","style":[]}],"parameters":[]}},"extendsTypes":["SoundExpressionPlayMode.InBackground","Number"],"pyQName":"SoundExpressionPlayMode.IN_BACKGROUND"},"soundExpression":{"kind":5,"retType":""},"soundExpression.giggle":{"kind":4,"retType":"SoundExpression","attributes":{"fixedInstance":"true","whenUsed":"true","block":"{id:soundexpression}giggle","_def":{"parts":[{"kind":"label","text":"{id:soundexpression}giggle","style":[]}],"parameters":[]}}},"soundExpression.happy":{"kind":4,"retType":"SoundExpression","attributes":{"fixedInstance":"true","whenUsed":"true","block":"{id:soundexpression}happy","_def":{"parts":[{"kind":"label","text":"{id:soundexpression}happy","style":[]}],"parameters":[]}}},"soundExpression.hello":{"kind":4,"retType":"SoundExpression","attributes":{"fixedInstance":"true","whenUsed":"true","block":"{id:soundexpression}hello","_def":{"parts":[{"kind":"label","text":"{id:soundexpression}hello","style":[]}],"parameters":[]}}},"soundExpression.mysterious":{"kind":4,"retType":"SoundExpression","attributes":{"fixedInstance":"true","whenUsed":"true","block":"{id:soundexpression}mysterious","_def":{"parts":[{"kind":"label","text":"{id:soundexpression}mysterious","style":[]}],"parameters":[]}}},"soundExpression.sad":{"kind":4,"retType":"SoundExpression","attributes":{"fixedInstance":"true","whenUsed":"true","block":"{id:soundexpression}sad","_def":{"parts":[{"kind":"label","text":"{id:soundexpression}sad","style":[]}],"parameters":[]}}},"soundExpression.slide":{"kind":4,"retType":"SoundExpression","attributes":{"fixedInstance":"true","whenUsed":"true","block":"{id:soundexpression}slide","_def":{"parts":[{"kind":"label","text":"{id:soundexpression}slide","style":[]}],"parameters":[]}}},"soundExpression.soaring":{"kind":4,"retType":"SoundExpression","attributes":{"fixedInstance":"true","whenUsed":"true","block":"{id:soundexpression}soaring","_def":{"parts":[{"kind":"label","text":"{id:soundexpression}soaring","style":[]}],"parameters":[]}}},"soundExpression.spring":{"kind":4,"retType":"SoundExpression","attributes":{"fixedInstance":"true","whenUsed":"true","block":"{id:soundexpression}spring","_def":{"parts":[{"kind":"label","text":"{id:soundexpression}spring","style":[]}],"parameters":[]}}},"soundExpression.twinkle":{"kind":4,"retType":"SoundExpression","attributes":{"fixedInstance":"true","whenUsed":"true","block":"{id:soundexpression}twinkle","_def":{"parts":[{"kind":"label","text":"{id:soundexpression}twinkle","style":[]}],"parameters":[]}}},"soundExpression.yawn":{"kind":4,"retType":"SoundExpression","attributes":{"fixedInstance":"true","whenUsed":"true","block":"{id:soundexpression}yawn","_def":{"parts":[{"kind":"label","text":"{id:soundexpression}yawn","style":[]}],"parameters":[]}}},"soundExpression.InterpolationEffect":{"kind":6,"retType":"soundExpression.InterpolationEffect","extendsTypes":["soundExpression.InterpolationEffect","Number"]},"soundExpression.InterpolationEffect.None":{"retType":"soundExpression.InterpolationEffect.None","extendsTypes":["soundExpression.InterpolationEffect.None","Number"],"pyQName":"soundExpression.InterpolationEffect.NONE"},"soundExpression.InterpolationEffect.Linear":{"retType":"soundExpression.InterpolationEffect.Linear","extendsTypes":["soundExpression.InterpolationEffect.Linear","Number"],"pyQName":"soundExpression.InterpolationEffect.LINEAR"},"soundExpression.InterpolationEffect.Curve":{"retType":"soundExpression.InterpolationEffect.Curve","extendsTypes":["soundExpression.InterpolationEffect.Curve","Number"],"pyQName":"soundExpression.InterpolationEffect.CURVE"},"soundExpression.InterpolationEffect.ExponentialRising":{"retType":"soundExpression.InterpolationEffect.ExponentialRising","extendsTypes":["soundExpression.InterpolationEffect.ExponentialRising","Number"],"pyQName":"soundExpression.InterpolationEffect.EXPONENTIAL_RISING"},"soundExpression.InterpolationEffect.ExponentialFalling":{"retType":"soundExpression.InterpolationEffect.ExponentialFalling","extendsTypes":["soundExpression.InterpolationEffect.ExponentialFalling","Number"],"pyQName":"soundExpression.InterpolationEffect.EXPONENTIAL_FALLING"},"soundExpression.InterpolationEffect.ArpeggioRisingMajor":{"retType":"soundExpression.InterpolationEffect.ArpeggioRisingMajor","extendsTypes":["soundExpression.InterpolationEffect.ArpeggioRisingMajor","Number"],"pyQName":"soundExpression.InterpolationEffect.ARPEGGIO_RISING_MAJOR"},"soundExpression.InterpolationEffect.ArpeggioRisingMinor":{"retType":"soundExpression.InterpolationEffect.ArpeggioRisingMinor","extendsTypes":["soundExpression.InterpolationEffect.ArpeggioRisingMinor","Number"],"pyQName":"soundExpression.InterpolationEffect.ARPEGGIO_RISING_MINOR"},"soundExpression.InterpolationEffect.ArpeggioRisingDiminished":{"retType":"soundExpression.InterpolationEffect.ArpeggioRisingDiminished","extendsTypes":["soundExpression.InterpolationEffect.ArpeggioRisingDiminished","Number"],"pyQName":"soundExpression.InterpolationEffect.ARPEGGIO_RISING_DIMINISHED"},"soundExpression.InterpolationEffect.ArpeggioRisingChromatic":{"retType":"soundExpression.InterpolationEffect.ArpeggioRisingChromatic","extendsTypes":["soundExpression.InterpolationEffect.ArpeggioRisingChromatic","Number"],"pyQName":"soundExpression.InterpolationEffect.ARPEGGIO_RISING_CHROMATIC"},"soundExpression.InterpolationEffect.ArpeggioRisingWholeTone":{"retType":"soundExpression.InterpolationEffect.ArpeggioRisingWholeTone","extendsTypes":["soundExpression.InterpolationEffect.ArpeggioRisingWholeTone","Number"],"pyQName":"soundExpression.InterpolationEffect.ARPEGGIO_RISING_WHOLE_TONE"},"soundExpression.InterpolationEffect.ArpeggioFallingMajor":{"retType":"soundExpression.InterpolationEffect.ArpeggioFallingMajor","extendsTypes":["soundExpression.InterpolationEffect.ArpeggioFallingMajor","Number"],"pyQName":"soundExpression.InterpolationEffect.ARPEGGIO_FALLING_MAJOR"},"soundExpression.InterpolationEffect.ArpeggioFallingMinor":{"retType":"soundExpression.InterpolationEffect.ArpeggioFallingMinor","extendsTypes":["soundExpression.InterpolationEffect.ArpeggioFallingMinor","Number"],"pyQName":"soundExpression.InterpolationEffect.ARPEGGIO_FALLING_MINOR"},"soundExpression.InterpolationEffect.ArpeggioFallingDiminished":{"retType":"soundExpression.InterpolationEffect.ArpeggioFallingDiminished","extendsTypes":["soundExpression.InterpolationEffect.ArpeggioFallingDiminished","Number"],"pyQName":"soundExpression.InterpolationEffect.ARPEGGIO_FALLING_DIMINISHED"},"soundExpression.InterpolationEffect.ArpeggioFallingChromatic":{"retType":"soundExpression.InterpolationEffect.ArpeggioFallingChromatic","extendsTypes":["soundExpression.InterpolationEffect.ArpeggioFallingChromatic","Number"],"pyQName":"soundExpression.InterpolationEffect.ARPEGGIO_FALLING_CHROMATIC"},"soundExpression.InterpolationEffect.ArpeggioFallingWholeTone":{"retType":"soundExpression.InterpolationEffect.ArpeggioFallingWholeTone","extendsTypes":["soundExpression.InterpolationEffect.ArpeggioFallingWholeTone","Number"],"pyQName":"soundExpression.InterpolationEffect.ARPEGGIO_FALLING_WHOLE_TONE"},"soundExpression.InterpolationEffect.Logarithmic":{"retType":"soundExpression.InterpolationEffect.Logarithmic","extendsTypes":["soundExpression.InterpolationEffect.Logarithmic","Number"],"pyQName":"soundExpression.InterpolationEffect.LOGARITHMIC"},"soundExpression.Sound":{"kind":8,"retType":"soundExpression.Sound","extendsTypes":[]},"soundExpression.Sound.src":{"kind":2,"retType":"string","isInstance":true},"soundExpression.Sound.__constructor":{"kind":-3,"parameters":[],"isInstance":true},"soundExpression.Sound.wave":{"kind":-2,"retType":"WaveShape","isInstance":true,"isReadOnly":true},"soundExpression.Sound.wave@set":{"kind":-2,"retType":"WaveShape","isInstance":true},"soundExpression.Sound.volume":{"kind":-2,"retType":"number","isInstance":true,"isReadOnly":true},"soundExpression.Sound.volume@set":{"kind":-2,"retType":"number","isInstance":true},"soundExpression.Sound.frequency":{"kind":-2,"retType":"number","isInstance":true,"isReadOnly":true},"soundExpression.Sound.frequency@set":{"kind":-2,"retType":"number","isInstance":true},"soundExpression.Sound.duration":{"kind":-2,"retType":"number","isInstance":true,"isReadOnly":true},"soundExpression.Sound.duration@set":{"kind":-2,"retType":"number","isInstance":true},"soundExpression.Sound.shape":{"kind":-2,"retType":"soundExpression.InterpolationEffect","isInstance":true,"isReadOnly":true},"soundExpression.Sound.shape@set":{"kind":-2,"retType":"soundExpression.InterpolationEffect","isInstance":true},"soundExpression.Sound.endFrequency":{"kind":-2,"retType":"number","isInstance":true,"isReadOnly":true,"pyQName":"soundExpression.Sound.end_frequency"},"soundExpression.Sound.endFrequency@set":{"kind":-2,"retType":"number","isInstance":true,"pyQName":"soundExpression.Sound.end_frequency@set"},"soundExpression.Sound.endVolume":{"kind":-2,"retType":"number","isInstance":true,"isReadOnly":true,"pyQName":"soundExpression.Sound.end_volume"},"soundExpression.Sound.endVolume@set":{"kind":-2,"retType":"number","isInstance":true,"pyQName":"soundExpression.Sound.end_volume@set"},"soundExpression.Sound.steps":{"kind":-2,"retType":"number","isInstance":true,"isReadOnly":true},"soundExpression.Sound.steps@set":{"kind":-2,"retType":"number","isInstance":true},"soundExpression.Sound.fx":{"kind":-2,"retType":"SoundExpressionEffect","isInstance":true,"isReadOnly":true},"soundExpression.Sound.fx@set":{"kind":-2,"retType":"SoundExpressionEffect","isInstance":true},"soundExpression.Sound.fxParam":{"kind":-2,"retType":"number","isInstance":true,"isReadOnly":true,"pyQName":"soundExpression.Sound.fx_param"},"soundExpression.Sound.fxParam@set":{"kind":-2,"retType":"number","isInstance":true,"pyQName":"soundExpression.Sound.fx_param@set"},"soundExpression.Sound.fxnSteps":{"kind":-2,"retType":"number","isInstance":true,"isReadOnly":true,"pyQName":"soundExpression.Sound.fxn_steps"},"soundExpression.Sound.fxnSteps@set":{"kind":-2,"retType":"number","isInstance":true,"pyQName":"soundExpression.Sound.fxn_steps@set"},"soundExpression.Sound.frequencyRandomness":{"kind":-2,"retType":"number","isInstance":true,"isReadOnly":true,"pyQName":"soundExpression.Sound.frequency_randomness"},"soundExpression.Sound.frequencyRandomness@set":{"kind":-2,"retType":"number","isInstance":true,"pyQName":"soundExpression.Sound.frequency_randomness@set"},"soundExpression.Sound.endFrequencyRandomness":{"kind":-2,"retType":"number","isInstance":true,"isReadOnly":true,"pyQName":"soundExpression.Sound.end_frequency_randomness"},"soundExpression.Sound.endFrequencyRandomness@set":{"kind":-2,"retType":"number","isInstance":true,"pyQName":"soundExpression.Sound.end_frequency_randomness@set"},"soundExpression.Sound.volumeRandomness":{"kind":-2,"retType":"number","isInstance":true,"isReadOnly":true,"pyQName":"soundExpression.Sound.volume_randomness"},"soundExpression.Sound.volumeRandomness@set":{"kind":-2,"retType":"number","isInstance":true,"pyQName":"soundExpression.Sound.volume_randomness@set"},"soundExpression.Sound.endVolumeRandomness":{"kind":-2,"retType":"number","isInstance":true,"isReadOnly":true,"pyQName":"soundExpression.Sound.end_volume_randomness"},"soundExpression.Sound.endVolumeRandomness@set":{"kind":-2,"retType":"number","isInstance":true,"pyQName":"soundExpression.Sound.end_volume_randomness@set"},"soundExpression.Sound.durationRandomness":{"kind":-2,"retType":"number","isInstance":true,"isReadOnly":true,"pyQName":"soundExpression.Sound.duration_randomness"},"soundExpression.Sound.durationRandomness@set":{"kind":-2,"retType":"number","isInstance":true,"pyQName":"soundExpression.Sound.duration_randomness@set"},"soundExpression.Sound.fxParamRandomness":{"kind":-2,"retType":"number","isInstance":true,"isReadOnly":true,"pyQName":"soundExpression.Sound.fx_param_randomness"},"soundExpression.Sound.fxParamRandomness@set":{"kind":-2,"retType":"number","isInstance":true,"pyQName":"soundExpression.Sound.fx_param_randomness@set"},"soundExpression.Sound.fxnStepsRandomness":{"kind":-2,"retType":"number","isInstance":true,"isReadOnly":true,"pyQName":"soundExpression.Sound.fxn_steps_randomness"},"soundExpression.Sound.fxnStepsRandomness@set":{"kind":-2,"retType":"number","isInstance":true,"pyQName":"soundExpression.Sound.fxn_steps_randomness@set"},"soundExpression.Sound.copy":{"kind":-1,"retType":"soundExpression.Sound","parameters":[],"isInstance":true},"soundExpression.playSound":{"kind":-3,"parameters":[{"name":"toPlay","type":"soundExpression.Sound | soundExpression.Sound[]"}],"pyQName":"soundExpression.play_sound"},"music.playSoundEffect":{"kind":-3,"attributes":{"blockId":"soundExpression_playSoundEffect","block":"play sound $sound $mode","_shadowOverrides":{"sound":"soundExpression_createSoundEffect"},"weight":100,"help":"music/play-sound-effect","blockGap":"8","deprecated":"1","group":"micro:bit (V2)","paramHelp":{"sound":"the sound expression string","mode":"the play mode, play until done or in the background"},"jsDoc":"Play a sound effect from a sound expression string.","_def":{"parts":[{"kind":"label","text":"play sound ","style":[]},{"kind":"param","name":"sound","shadowBlockId":"soundExpression_createSoundEffect","ref":true},{"kind":"label","text":" ","style":[]},{"kind":"param","name":"mode","ref":true}],"parameters":[{"kind":"param","name":"sound","shadowBlockId":"soundExpression_createSoundEffect","ref":true},{"kind":"param","name":"mode","ref":true}]}},"parameters":[{"name":"sound","description":"the sound expression string","type":"string"},{"name":"mode","description":"the play mode, play until done or in the background","type":"SoundExpressionPlayMode","isEnum":true}],"pyQName":"music.play_sound_effect"},"music.createSoundEffect":{"kind":-3,"retType":"string","attributes":{"paramDefl":{"waveShape":"WaveShape.Sine","startFrequency":"5000","endFrequency":"0","startVolume":"255","endVolume":"0","duration":"500","effect":"SoundExpressionEffect.None","interpolation":"InterpolationCurve.Linear"},"blockId":"soundExpression_createSoundEffect","help":"music/create-sound-effect","block":"$waveShape|| start frequency $startFrequency end frequency $endFrequency duration $duration start volume $startVolume end volume $endVolume effect $effect interpolation $interpolation","explicitDefaults":["waveShape","startFrequency","endFrequency","startVolume","endVolume","duration","effect","interpolation"],"paramFieldEditor":{"waveShape":"soundeffect"},"paramMin":{"startFrequency":"0","endFrequency":"0","startVolume":"0","endVolume":"0","duration":"1"},"paramMax":{"startFrequency":"5000","endFrequency":"5000","startVolume":"255","endVolume":"255","duration":"9999"},"compileHiddenArguments":true,"inlineInputMode":"variable","inlineInputModeLimit":3,"expandableArgumentBreaks":"3,5","group":"micro:bit (V2)","deprecated":"1","paramHelp":{"waveShape":"waveform of the sound effect","startFrequency":"starting frequency for the sound effect waveform","endFrequency":"ending frequency for the sound effect waveform","startVolume":"starting volume of the sound, or starting amplitude","endVolume":"ending volume of the sound, or ending amplitude","duration":"the amount of time in milliseconds (ms) that sound will play for","effect":"the effect to apply to the waveform or volume","interpolation":"interpolation method for frequency scaling"},"jsDoc":"Create a sound expression from a set of sound effect parameters.","_def":{"parts":[{"kind":"param","name":"waveShape","ref":true}],"parameters":[{"kind":"param","name":"waveShape","ref":true}]},"_expandedDef":{"parts":[{"kind":"label","text":" start frequency ","style":[]},{"kind":"param","name":"startFrequency","ref":true},{"kind":"label","text":" end frequency ","style":[]},{"kind":"param","name":"endFrequency","ref":true},{"kind":"label","text":" duration ","style":[]},{"kind":"param","name":"duration","ref":true},{"kind":"label","text":" start volume ","style":[]},{"kind":"param","name":"startVolume","ref":true},{"kind":"label","text":" end volume ","style":[]},{"kind":"param","name":"endVolume","ref":true},{"kind":"label","text":" effect ","style":[]},{"kind":"param","name":"effect","ref":true},{"kind":"label","text":" interpolation ","style":[]},{"kind":"param","name":"interpolation","ref":true}],"parameters":[{"kind":"param","name":"startFrequency","ref":true},{"kind":"param","name":"endFrequency","ref":true},{"kind":"param","name":"duration","ref":true},{"kind":"param","name":"startVolume","ref":true},{"kind":"param","name":"endVolume","ref":true},{"kind":"param","name":"effect","ref":true},{"kind":"param","name":"interpolation","ref":true}]}},"parameters":[{"name":"waveShape","description":"waveform of the sound effect","type":"WaveShape","initializer":"WaveShape.Sine","default":"WaveShape.Sine","isEnum":true},{"name":"startFrequency","description":"starting frequency for the sound effect waveform","initializer":"5000","default":"5000","options":{"min":{"value":"0"},"max":{"value":"5000"}}},{"name":"endFrequency","description":"ending frequency for the sound effect waveform","initializer":"0","default":"0","options":{"min":{"value":"0"},"max":{"value":"5000"}}},{"name":"startVolume","description":"starting volume of the sound, or starting amplitude","initializer":"255","default":"255","options":{"min":{"value":"0"},"max":{"value":"255"}}},{"name":"endVolume","description":"ending volume of the sound, or ending amplitude","initializer":"0","default":"0","options":{"min":{"value":"0"},"max":{"value":"255"}}},{"name":"duration","description":"the amount of time in milliseconds (ms) that sound will play for","initializer":"500","default":"500","options":{"min":{"value":"1"},"max":{"value":"9999"}}},{"name":"effect","description":"the effect to apply to the waveform or volume","type":"SoundExpressionEffect","initializer":"SoundExpressionEffect.None","default":"SoundExpressionEffect.None","isEnum":true},{"name":"interpolation","description":"interpolation method for frequency scaling","type":"InterpolationCurve","initializer":"InterpolationCurve.Linear","default":"InterpolationCurve.Linear","isEnum":true}],"pyQName":"music.create_sound_effect"},"music.createSoundExpression":{"kind":-3,"retType":"SoundExpression","attributes":{"paramDefl":{"waveShape":"WaveShape.Sine","startFrequency":"5000","endFrequency":"0","startVolume":"255","endVolume":"0","duration":"500","effect":"SoundExpressionEffect.None","interpolation":"InterpolationCurve.Linear"},"blockId":"soundExpression_createSoundExpression","help":"music/create-sound-expression","block":"$waveShape|| start frequency $startFrequency end frequency $endFrequency duration $duration start volume $startVolume end volume $endVolume effect $effect interpolation $interpolation","explicitDefaults":["waveShape","startFrequency","endFrequency","startVolume","endVolume","duration","effect","interpolation"],"paramFieldEditor":{"waveShape":"soundeffect"},"paramMin":{"startFrequency":"0","endFrequency":"0","startVolume":"0","endVolume":"0","duration":"1"},"paramMax":{"startFrequency":"5000","endFrequency":"5000","startVolume":"255","endVolume":"255","duration":"9999"},"compileHiddenArguments":true,"inlineInputMode":"variable","inlineInputModeLimit":3,"expandableArgumentBreaks":"3,5","duplicateWithToolboxParent":"music_playable_play","duplicateWithToolboxParentArgument":"toPlay","duplicateShadowOnDrag":true,"group":"micro:bit (V2)","paramHelp":{"waveShape":"waveform of the sound effect","startFrequency":"starting frequency for the sound effect waveform","endFrequency":"ending frequency for the sound effect waveform","startVolume":"starting volume of the sound, or starting amplitude","endVolume":"ending volume of the sound, or ending amplitude","duration":"the amount of time in milliseconds (ms) that sound will play for","effect":"the effect to apply to the waveform or volume","interpolation":"interpolation method for frequency scaling"},"jsDoc":"Create a sound expression from a set of sound effect parameters.","_def":{"parts":[{"kind":"param","name":"waveShape","ref":true}],"parameters":[{"kind":"param","name":"waveShape","ref":true}]},"_expandedDef":{"parts":[{"kind":"label","text":" start frequency ","style":[]},{"kind":"param","name":"startFrequency","ref":true},{"kind":"label","text":" end frequency ","style":[]},{"kind":"param","name":"endFrequency","ref":true},{"kind":"label","text":" duration ","style":[]},{"kind":"param","name":"duration","ref":true},{"kind":"label","text":" start volume ","style":[]},{"kind":"param","name":"startVolume","ref":true},{"kind":"label","text":" end volume ","style":[]},{"kind":"param","name":"endVolume","ref":true},{"kind":"label","text":" effect ","style":[]},{"kind":"param","name":"effect","ref":true},{"kind":"label","text":" interpolation ","style":[]},{"kind":"param","name":"interpolation","ref":true}],"parameters":[{"kind":"param","name":"startFrequency","ref":true},{"kind":"param","name":"endFrequency","ref":true},{"kind":"param","name":"duration","ref":true},{"kind":"param","name":"startVolume","ref":true},{"kind":"param","name":"endVolume","ref":true},{"kind":"param","name":"effect","ref":true},{"kind":"param","name":"interpolation","ref":true}]}},"parameters":[{"name":"waveShape","description":"waveform of the sound effect","type":"WaveShape","initializer":"WaveShape.Sine","default":"WaveShape.Sine","isEnum":true},{"name":"startFrequency","description":"starting frequency for the sound effect waveform","initializer":"5000","default":"5000","options":{"min":{"value":"0"},"max":{"value":"5000"}}},{"name":"endFrequency","description":"ending frequency for the sound effect waveform","initializer":"0","default":"0","options":{"min":{"value":"0"},"max":{"value":"5000"}}},{"name":"startVolume","description":"starting volume of the sound, or starting amplitude","initializer":"255","default":"255","options":{"min":{"value":"0"},"max":{"value":"255"}}},{"name":"endVolume","description":"ending volume of the sound, or ending amplitude","initializer":"0","default":"0","options":{"min":{"value":"0"},"max":{"value":"255"}}},{"name":"duration","description":"the amount of time in milliseconds (ms) that sound will play for","initializer":"500","default":"500","options":{"min":{"value":"1"},"max":{"value":"9999"}}},{"name":"effect","description":"the effect to apply to the waveform or volume","type":"SoundExpressionEffect","initializer":"SoundExpressionEffect.None","default":"SoundExpressionEffect.None","isEnum":true},{"name":"interpolation","description":"interpolation method for frequency scaling","type":"InterpolationCurve","initializer":"InterpolationCurve.Linear","default":"InterpolationCurve.Linear","isEnum":true}],"pyQName":"music.create_sound_expression"},"music.builtinSoundEffect":{"kind":-3,"retType":"string","attributes":{"blockId":"soundExpression_builtinSoundEffect","block":"$soundExpression","blockGap":"8","group":"micro:bit (V2)","toolboxParent":"soundExpression_playSoundEffect","toolboxParentArgument":"sound","weight":98,"help":"music/builtin-sound-effect","deprecated":"1","paramHelp":{"soundExpression":"a sound expression for a built-in sound effect"},"jsDoc":"Get the sound expression string for a built-in a sound effect.","_def":{"parts":[{"kind":"param","name":"soundExpression","ref":true}],"parameters":[{"kind":"param","name":"soundExpression","ref":true}]}},"parameters":[{"name":"soundExpression","description":"a sound expression for a built-in sound effect","type":"SoundExpression"}],"pyQName":"music.builtin_sound_effect"},"music.builtinPlayableSoundEffect":{"kind":-3,"retType":"SoundExpression","attributes":{"blockId":"soundExpression_builtinPlayableSoundEffect","block":"$soundExpression","blockGap":"8","group":"micro:bit (V2)","toolboxParent":"music_playable_play","toolboxParentArgument":"toPlay","duplicateShadowOnDrag":true,"weight":98,"help":"music/builtin-sound-effect","paramHelp":{"soundExpression":"a sound expression for a built-in sound effect"},"jsDoc":"Get the sound expression string for a built-in sound effect.","_def":{"parts":[{"kind":"param","name":"soundExpression","ref":true}],"parameters":[{"kind":"param","name":"soundExpression","ref":true}]}},"parameters":[{"name":"soundExpression","description":"a sound expression for a built-in sound effect","type":"SoundExpression"}],"pyQName":"music.builtin_playable_sound_effect"},"music.PlaybackMode":{"kind":6,"retType":"music.PlaybackMode","extendsTypes":["music.PlaybackMode","Number"]},"music.PlaybackMode.UntilDone":{"retType":"music.PlaybackMode.UntilDone","attributes":{"block":"until done","_def":{"parts":[{"kind":"label","text":"until done","style":[]}],"parameters":[]}},"extendsTypes":["music.PlaybackMode.UntilDone","Number"],"pyQName":"music.PlaybackMode.UNTIL_DONE"},"music.PlaybackMode.InBackground":{"retType":"music.PlaybackMode.InBackground","attributes":{"block":"in background","_def":{"parts":[{"kind":"label","text":"in background","style":[]}],"parameters":[]}},"extendsTypes":["music.PlaybackMode.InBackground","Number"],"pyQName":"music.PlaybackMode.IN_BACKGROUND"},"music.PlaybackMode.LoopingInBackground":{"retType":"music.PlaybackMode.LoopingInBackground","attributes":{"block":"looping in background","_def":{"parts":[{"kind":"label","text":"looping in background","style":[]}],"parameters":[]}},"extendsTypes":["music.PlaybackMode.LoopingInBackground","Number"],"pyQName":"music.PlaybackMode.LOOPING_IN_BACKGROUND"},"music.Playable":{"kind":8,"retType":"music.Playable","extendsTypes":["music.Playable"]},"music.Playable.stopped":{"kind":2,"retType":"boolean","isInstance":true},"music.Playable.__constructor":{"kind":-3,"parameters":[],"isInstance":true},"music.Playable._play":{"kind":-1,"parameters":[{"name":"playbackMode","type":"music.PlaybackMode","isEnum":true}],"isInstance":true},"music.Playable.loop":{"kind":-1,"parameters":[],"isInstance":true},"music.StringArrayPlayable":{"kind":8,"retType":"music.StringArrayPlayable","extendsTypes":["music.StringArrayPlayable","music.Playable"]},"music.StringArrayPlayable.__constructor":{"kind":-3,"parameters":[{"name":"notes","type":"string[]"},{"name":"tempo"}],"isInstance":true},"music.StringArrayPlayable._play":{"kind":-1,"parameters":[{"name":"playbackMode","type":"music.PlaybackMode","isEnum":true}],"isInstance":true},"music.TonePlayable":{"kind":8,"retType":"music.TonePlayable","extendsTypes":["music.TonePlayable","music.Playable"]},"music.TonePlayable.__constructor":{"kind":-3,"parameters":[{"name":"pitch"},{"name":"duration"}],"isInstance":true},"music.TonePlayable._play":{"kind":-1,"parameters":[{"name":"playbackMode","type":"music.PlaybackMode","isEnum":true}],"isInstance":true},"music.play":{"kind":-3,"attributes":{"blockId":"music_playable_play","block":"play $toPlay $playbackMode","_shadowOverrides":{"toPlay":"music_string_playable"},"group":"Melody","help":"music/play","blockHidden":true,"paramHelp":{"toPlay":"the song or melody to play","playbackMode":"play the song or melody until it's finished or as background task"},"jsDoc":"Play a song, melody, or other sound. The music plays until finished or can play as a\nbackground task.","_def":{"parts":[{"kind":"label","text":"play ","style":[]},{"kind":"param","name":"toPlay","shadowBlockId":"music_string_playable","ref":true},{"kind":"label","text":" ","style":[]},{"kind":"param","name":"playbackMode","ref":true}],"parameters":[{"kind":"param","name":"toPlay","shadowBlockId":"music_string_playable","ref":true},{"kind":"param","name":"playbackMode","ref":true}]}},"parameters":[{"name":"toPlay","description":"the song or melody to play","type":"music.Playable"},{"name":"playbackMode","description":"play the song or melody until it's finished or as background task","type":"music.PlaybackMode","isEnum":true}]},"music._playDefaultBackground":{"kind":-3,"attributes":{"paramDefl":{"playbackMode":"music.PlaybackMode.InBackground"},"blockId":"music_playable_play_default_bkg","block":"play $toPlay $playbackMode","_shadowOverrides":{"toPlay":"music_string_playable"},"explicitDefaults":["playbackMode"],"group":"Melody","help":"music/play","blockHidden":true,"_def":{"parts":[{"kind":"label","text":"play ","style":[]},{"kind":"param","name":"toPlay","shadowBlockId":"music_string_playable","ref":true},{"kind":"label","text":" ","style":[]},{"kind":"param","name":"playbackMode","ref":true}],"parameters":[{"kind":"param","name":"toPlay","shadowBlockId":"music_string_playable","ref":true},{"kind":"param","name":"playbackMode","ref":true}]}},"parameters":[{"name":"toPlay","type":"music.Playable"},{"name":"playbackMode","type":"music.PlaybackMode","initializer":"music.PlaybackMode.InBackground","default":"music.PlaybackMode.InBackground","isEnum":true}],"pyQName":"music._play_default_background"},"music.stringPlayable":{"kind":-3,"retType":"music.Playable","attributes":{"paramDefl":{"bpm":"120"},"blockId":"music_string_playable","block":"melody $melody at tempo $bpm|(bpm)","weight":85,"blockGap":"8","help":"music/string-playable","group":"Melody","toolboxParent":"music_playable_play","toolboxParentArgument":"toPlay","duplicateShadowOnDrag":true,"_shadowOverrides":{"melody":"melody_editor"},"paramMin":{"bpm":"40"},"paramMax":{"bpm":"500"},"explicitDefaults":["bpm"],"paramHelp":{"melody":"string of up to eight notes [C D E F G A B C5] or rests [-] separated by spaces, which will be played one at a time, ex: \"E D G F B A C5 B \"","bpm":"number in beats per minute dictating how long each note will play"},"jsDoc":"Play a melody from the melody editor","_def":{"parts":[{"kind":"label","text":"melody ","style":[]},{"kind":"param","name":"melody","shadowBlockId":"melody_editor","ref":true},{"kind":"label","text":" at tempo ","style":[]},{"kind":"param","name":"bpm","ref":true},{"kind":"break"},{"kind":"label","text":"(bpm)","style":[]}],"parameters":[{"kind":"param","name":"melody","shadowBlockId":"melody_editor","ref":true},{"kind":"param","name":"bpm","ref":true}]}},"parameters":[{"name":"melody","description":"string of up to eight notes [C D E F G A B C5] or rests [-] separated by spaces, which will be played one at a time, ex: \"E D G F B A C5 B \"","type":"string"},{"name":"bpm","description":"number in beats per minute dictating how long each note will play","initializer":"120","default":"120","options":{"min":{"value":"40"},"max":{"value":"500"}}}],"pyQName":"music.string_playable"},"music.tonePlayable":{"kind":-3,"retType":"music.Playable","attributes":{"blockId":"music_tone_playable","block":"tone $note for $duration","toolboxParent":"music_playable_play","toolboxParentArgument":"toPlay","group":"Tone","weight":85,"duplicateShadowOnDrag":true,"_shadowOverrides":{"note":"device_note","duration":"device_beat"},"parts":"headphone","help":"music/tone-playable","paramHelp":{"note":"pitch of the tone to play in Hertz (Hz).","duration":"tone duration in milliseconds (ms)"},"jsDoc":"Plays a tone through pin ``P0`` for the given duration.","_def":{"parts":[{"kind":"label","text":"tone ","style":[]},{"kind":"param","name":"note","shadowBlockId":"device_note","ref":true},{"kind":"label","text":" for ","style":[]},{"kind":"param","name":"duration","shadowBlockId":"device_beat","ref":true}],"parameters":[{"kind":"param","name":"note","shadowBlockId":"device_note","ref":true},{"kind":"param","name":"duration","shadowBlockId":"device_beat","ref":true}]}},"parameters":[{"name":"note","description":"pitch of the tone to play in Hertz (Hz)."},{"name":"duration","description":"tone duration in milliseconds (ms)"}],"pyQName":"music.tone_playable"},"music._stopPlayables":{"kind":-3,"parameters":[],"pyQName":"music._stop_playables"}}},"sha":"5293736160b7405f27c51da2adbb55d853682875651e2d802f175d4e3cd71c31"},"libs/audio-samples":{"apis":{"byQName":{"samples":{"kind":5,"retType":""},"samples.enable":{"kind":-3,"attributes":{"jsDoc":"Enable audio"},"parameters":[]},"samples.disable":{"kind":-3,"attributes":{"jsDoc":"Disable audio"},"parameters":[]},"samples.setSampleRate":{"kind":-3,"attributes":{"jsDoc":"Set the sample rate"},"parameters":[{"name":"src"},{"name":"sampleRate"}],"pyQName":"samples.set_sample_rate"},"samples.playAsync":{"kind":-3,"attributes":{"jsDoc":"Play a sample"},"parameters":[{"name":"src"},{"name":"buf","type":"Buffer"}],"pyQName":"samples.play_async"}}},"sha":"099065389c86ccd55b24d70e96b8572c4b36e308d41ae10ee0b7c9106d13e449"},"libs/radio":{"apis":{"byQName":{"radio":{"kind":5,"retType":"","attributes":{"color":"#E3008C","weight":96,"icon":"","groups":["Group","Broadcast","Send","Receive"],"jsDoc":"Communicate data using radio packets"}},"radio.off":{"kind":-3,"attributes":{"help":"radio/off","jsDoc":"Disables the radio for use as a multipoint sender/receiver.\nDisabling radio will help conserve battery power when it is not in use."},"parameters":[]},"radio.on":{"kind":-3,"attributes":{"help":"radio/on","jsDoc":"Initialises the radio for use as a multipoint sender/receiver\nOnly useful when the radio.off() is used beforehand."},"parameters":[]},"radio.raiseEvent":{"kind":-3,"attributes":{"blockId":"radioRaiseEvent","block":"radio raise event|from source %src=control_event_source_id|with value %value=control_event_value_id","blockExternalInputs":"1","advanced":true,"weight":1,"help":"radio/raise-event","inlineInputMode":"external","jsDoc":"Sends an event over radio to neigboring devices","_def":{"parts":[{"kind":"label","text":"radio raise event","style":[]},{"kind":"break"},{"kind":"label","text":"from source ","style":[]},{"kind":"param","name":"src","shadowBlockId":"control_event_source_id","ref":false},{"kind":"break"},{"kind":"label","text":"with value ","style":[]},{"kind":"param","name":"value","shadowBlockId":"control_event_value_id","ref":false}],"parameters":[{"kind":"param","name":"src","shadowBlockId":"control_event_source_id","ref":false},{"kind":"param","name":"value","shadowBlockId":"control_event_value_id","ref":false}]}},"parameters":[{"name":"src"},{"name":"value"}],"pyQName":"radio.raise_event"},"radio.readRawPacket":{"kind":-3,"retType":"Buffer","attributes":{"jsDoc":"Internal use only. Takes the next packet from the radio queue and returns its contents + RSSI in a Buffer.\n@returns NULL if no packet available"},"parameters":[],"pyQName":"radio.read_raw_packet"},"radio.sendRawPacket":{"kind":-3,"attributes":{"callingConvention":1,"async":"true","jsDoc":"Internal use only. Sends a raw packet through the radio (assumes RSSI appened to packet)"},"parameters":[{"name":"msg","type":"Buffer"}],"pyQName":"radio.send_raw_packet"},"radio.onDataReceived":{"kind":-3,"attributes":{"help":"radio/on-data-received","weight":0,"blockId":"radio_datagram_received_event","block":"radio on data received","blockGap":"8","deprecated":"true","blockHidden":true,"jsDoc":"Used internally by the library.","_def":{"parts":[{"kind":"label","text":"radio on data received","style":[]}],"parameters":[]}},"parameters":[{"name":"body","type":"() => void","handlerParameters":[]}],"pyQName":"radio.on_data_received"},"radio.setGroup":{"kind":-3,"attributes":{"paramDefl":{"id":"1"},"help":"radio/set-group","weight":100,"blockId":"radio_set_group","block":"radio set group %ID","paramMin":{"id":"0"},"paramMax":{"id":"255"},"group":"Group","paramHelp":{"id":"the group id between ``0`` and ``255``, eg: 1"},"jsDoc":"Sets the group id for radio communications. A micro:bit can only listen to one group ID at any time.","_def":{"parts":[{"kind":"label","text":"radio set group ","style":[]},{"kind":"param","name":"ID","ref":false}],"parameters":[{"kind":"param","name":"ID","ref":false}]}},"parameters":[{"name":"id","description":"the group id between ``0`` and ``255``, eg: 1","default":"1","options":{"min":{"value":"0"},"max":{"value":"255"}}}],"pyQName":"radio.set_group"},"radio.setTransmitPower":{"kind":-3,"attributes":{"paramDefl":{"power":"7"},"help":"radio/set-transmit-power","weight":9,"blockGap":"8","blockId":"radio_set_transmit_power","block":"radio set transmit power %power","paramMin":{"power":"0"},"paramMax":{"power":"7"},"advanced":true,"paramHelp":{"power":"a value in the range 0..7, where 0 is the lowest power and 7 is the highest. eg: 7"},"jsDoc":"Change the output power level of the transmitter to the given value.","_def":{"parts":[{"kind":"label","text":"radio set transmit power ","style":[]},{"kind":"param","name":"power","ref":false}],"parameters":[{"kind":"param","name":"power","ref":false}]}},"parameters":[{"name":"power","description":"a value in the range 0..7, where 0 is the lowest power and 7 is the highest. eg: 7","default":"7","options":{"min":{"value":"0"},"max":{"value":"7"}}}],"pyQName":"radio.set_transmit_power"},"radio.setFrequencyBand":{"kind":-3,"attributes":{"help":"radio/set-frequency-band","weight":8,"blockGap":"8","blockId":"radio_set_frequency_band","block":"radio set frequency band %band","paramMin":{"band":"0"},"paramMax":{"band":"83"},"advanced":true,"paramHelp":{"band":"a frequency band in the range 0 - 83. Each step is 1MHz wide, based at 2400MHz."},"jsDoc":"Change the transmission and reception band of the radio to the given channel","_def":{"parts":[{"kind":"label","text":"radio set frequency band ","style":[]},{"kind":"param","name":"band","ref":false}],"parameters":[{"kind":"param","name":"band","ref":false}]}},"parameters":[{"name":"band","description":"a frequency band in the range 0 - 83. Each step is 1MHz wide, based at 2400MHz.","options":{"min":{"value":"0"},"max":{"value":"83"}}}],"pyQName":"radio.set_frequency_band"},"RadioPacketProperty":{"kind":6,"retType":"RadioPacketProperty","extendsTypes":["RadioPacketProperty","Number"]},"RadioPacketProperty.SignalStrength":{"retType":"RadioPacketProperty.SignalStrength","attributes":{"blockIdentity":"radio._packetProperty","block":"signal strength","_def":{"parts":[{"kind":"label","text":"signal strength","style":[]}],"parameters":[]}},"extendsTypes":["RadioPacketProperty.SignalStrength","Number"],"pyQName":"RadioPacketProperty.SIGNAL_STRENGTH"},"RadioPacketProperty.Time":{"retType":"RadioPacketProperty.Time","attributes":{"blockIdentity":"radio._packetProperty","block":"time","_def":{"parts":[{"kind":"label","text":"time","style":[]}],"parameters":[]}},"extendsTypes":["RadioPacketProperty.Time","Number"],"pyQName":"RadioPacketProperty.TIME"},"RadioPacketProperty.SerialNumber":{"retType":"RadioPacketProperty.SerialNumber","attributes":{"block":"serial number","blockIdentity":"radio._packetProperty","_def":{"parts":[{"kind":"label","text":"serial number","style":[]}],"parameters":[]}},"extendsTypes":["RadioPacketProperty.SerialNumber","Number"],"pyQName":"RadioPacketProperty.SERIAL_NUMBER"},"radio.PACKET_TYPE_NUMBER":{"kind":4,"retType":"number"},"radio.PACKET_TYPE_VALUE":{"kind":4,"retType":"number"},"radio.PACKET_TYPE_STRING":{"kind":4,"retType":"number"},"radio.PACKET_TYPE_BUFFER":{"kind":4,"retType":"number"},"radio.PACKET_TYPE_DOUBLE":{"kind":4,"retType":"number"},"radio.PACKET_TYPE_DOUBLE_VALUE":{"kind":4,"retType":"number"},"radio.lastPacket":{"kind":4,"retType":"radio.RadioPacket","pyQName":"radio.last_packet"},"radio.onReceivedNumber":{"kind":-3,"attributes":{"help":"radio/on-received-number","blockId":"radio_on_number_drag","block":"on radio received","blockGap":"16","useLoc":"radio.onDataPacketReceived","draggableParameters":"reporter","group":"Receive","weight":20,"jsDoc":"Registers code to run when the radio receives a number.","_def":{"parts":[{"kind":"label","text":"on radio received","style":[]}],"parameters":[]}},"parameters":[{"name":"cb","type":"(receivedNumber: number) => void","handlerParameters":[{"name":"receivedNumber","type":"number"}]}],"pyQName":"radio.on_received_number"},"radio.onReceivedValue":{"kind":-3,"attributes":{"help":"radio/on-received-value","blockId":"radio_on_value_drag","block":"on radio received","blockGap":"16","useLoc":"radio.onDataPacketReceived","draggableParameters":"reporter","group":"Receive","weight":19,"jsDoc":"Registers code to run when the radio receives a key value pair.","_def":{"parts":[{"kind":"label","text":"on radio received","style":[]}],"parameters":[]}},"parameters":[{"name":"cb","type":"(name: string, value: number) => void","handlerParameters":[{"name":"name","type":"string"},{"name":"value","type":"number"}]}],"pyQName":"radio.on_received_value"},"radio.onReceivedString":{"kind":-3,"attributes":{"help":"radio/on-received-string","blockId":"radio_on_string_drag","block":"on radio received","blockGap":"16","useLoc":"radio.onDataPacketReceived","draggableParameters":"reporter","group":"Receive","weight":18,"jsDoc":"Registers code to run when the radio receives a string.","_def":{"parts":[{"kind":"label","text":"on radio received","style":[]}],"parameters":[]}},"parameters":[{"name":"cb","type":"(receivedString: string) => void","handlerParameters":[{"name":"receivedString","type":"string"}]}],"pyQName":"radio.on_received_string"},"radio.onReceivedBuffer":{"kind":-3,"attributes":{"help":"radio/on-received-buffer","blockHidden":true,"blockId":"radio_on_buffer_drag","block":"on radio received","blockGap":"16","useLoc":"radio.onDataPacketReceived","draggableParameters":"reporter","jsDoc":"Registers code to run when the radio receives a buffer.","_def":{"parts":[{"kind":"label","text":"on radio received","style":[]}],"parameters":[]}},"parameters":[{"name":"cb","type":"(receivedBuffer: Buffer) => void","handlerParameters":[{"name":"receivedBuffer","type":"Buffer"}]}],"pyQName":"radio.on_received_buffer"},"radio.receivedPacket":{"kind":-3,"retType":"number","attributes":{"help":"radio/received-packet","blockGap":"16","blockId":"radio_received_packet","block":"received packet %type=radio_packet_property","group":"Receive","weight":16,"paramHelp":{"type":"the type of property to retrieve from the last packet"},"jsDoc":"Returns properties of the last radio packet received.","_def":{"parts":[{"kind":"label","text":"received packet ","style":[]},{"kind":"param","name":"type","shadowBlockId":"radio_packet_property","ref":false}],"parameters":[{"kind":"param","name":"type","shadowBlockId":"radio_packet_property","ref":false}]}},"parameters":[{"name":"type","description":"the type of property to retrieve from the last packet"}],"pyQName":"radio.received_packet"},"radio._packetProperty":{"kind":-3,"retType":"number","attributes":{"paramDefl":{"type":"PacketProperty.time"},"blockId":"radio_packet_property","block":"%note","shim":"TD_ID","blockHidden":true,"paramHelp":{"type":"the packet property type, eg: PacketProperty.time"},"jsDoc":"Gets a packet property.","_def":{"parts":[{"kind":"param","name":"note","ref":false}],"parameters":[{"kind":"param","name":"note","ref":false}]}},"parameters":[{"name":"type","description":"the packet property type, eg: PacketProperty.time","type":"RadioPacketProperty","default":"PacketProperty.time","isEnum":true}],"pyQName":"radio._packet_property"},"radio.RadioPacket":{"kind":8,"retType":"radio.RadioPacket","extendsTypes":[]},"radio.RadioPacket.getPacket":{"kind":-1,"retType":"radio.RadioPacket","parameters":[{"name":"data","type":"Buffer"}],"pyQName":"radio.RadioPacket.get_packet"},"radio.RadioPacket.mkPacket":{"kind":-1,"retType":"radio.RadioPacket","parameters":[{"name":"packetType"}],"pyQName":"radio.RadioPacket.mk_packet"},"radio.RadioPacket.signal":{"kind":-2,"retType":"number","isInstance":true,"isReadOnly":true},"radio.RadioPacket.packetType":{"kind":-2,"retType":"number","isInstance":true,"isReadOnly":true,"pyQName":"radio.RadioPacket.packet_type"},"radio.RadioPacket.time":{"kind":-2,"retType":"number","isInstance":true,"isReadOnly":true},"radio.RadioPacket.time@set":{"kind":-2,"retType":"number","isInstance":true},"radio.RadioPacket.serial":{"kind":-2,"retType":"number","isInstance":true,"isReadOnly":true},"radio.RadioPacket.serial@set":{"kind":-2,"retType":"number","isInstance":true},"radio.RadioPacket.stringPayload":{"kind":-2,"retType":"string","isInstance":true,"isReadOnly":true,"pyQName":"radio.RadioPacket.string_payload"},"radio.RadioPacket.stringPayload@set":{"kind":-2,"retType":"string","isInstance":true,"pyQName":"radio.RadioPacket.string_payload@set"},"radio.RadioPacket.numberPayload":{"kind":-2,"retType":"number","isInstance":true,"isReadOnly":true,"pyQName":"radio.RadioPacket.number_payload"},"radio.RadioPacket.numberPayload@set":{"kind":-2,"retType":"number","isInstance":true,"pyQName":"radio.RadioPacket.number_payload@set"},"radio.RadioPacket.bufferPayload":{"kind":-2,"retType":"Buffer","isInstance":true,"isReadOnly":true,"pyQName":"radio.RadioPacket.buffer_payload"},"radio.RadioPacket.bufferPayload@set":{"kind":-2,"retType":"Buffer","isInstance":true,"pyQName":"radio.RadioPacket.buffer_payload@set"},"radio.RadioPacket.hasString":{"kind":-1,"retType":"boolean","parameters":[],"isInstance":true,"pyQName":"radio.RadioPacket.has_string"},"radio.RadioPacket.hasNumber":{"kind":-1,"retType":"boolean","parameters":[],"isInstance":true,"pyQName":"radio.RadioPacket.has_number"},"radio.sendNumber":{"kind":-3,"attributes":{"help":"radio/send-number","weight":60,"blockId":"radio_datagram_send","block":"radio send number %value","blockGap":"8","group":"Send","jsDoc":"Broadcasts a number over radio to any connected micro:bit in the group.","_def":{"parts":[{"kind":"label","text":"radio send number ","style":[]},{"kind":"param","name":"value","ref":false}],"parameters":[{"kind":"param","name":"value","ref":false}]}},"parameters":[{"name":"value"}],"pyQName":"radio.send_number"},"radio.sendValue":{"kind":-3,"attributes":{"paramDefl":{"name":"name"},"help":"radio/send-value","weight":59,"blockId":"radio_datagram_send_value","block":"radio send|value %name|= %value","blockGap":"8","group":"Send","paramHelp":{"name":"the field name (max 8 characters), eg: \"name\"","value":"the numeric value"},"jsDoc":"Broadcasts a name / value pair along with the device serial number\nand running time to any connected micro:bit in the group. The name can\ninclude no more than 8 characters.","_def":{"parts":[{"kind":"label","text":"radio send","style":[]},{"kind":"break"},{"kind":"label","text":"value ","style":[]},{"kind":"param","name":"name","ref":false},{"kind":"break"},{"kind":"label","text":"= ","style":[]},{"kind":"param","name":"value","ref":false}],"parameters":[{"kind":"param","name":"name","ref":false},{"kind":"param","name":"value","ref":false}]}},"parameters":[{"name":"name","description":"the field name (max 8 characters), eg: \"name\"","type":"string","default":"name"},{"name":"value","description":"the numeric value"}],"pyQName":"radio.send_value"},"radio.sendString":{"kind":-3,"attributes":{"help":"radio/send-string","weight":58,"blockId":"radio_datagram_send_string","block":"radio send string %msg","paramShadowOptions":{"msg":{"toString":"true"}},"group":"Send","jsDoc":"Broadcasts a string along with the device serial number\nand running time to any connected micro:bit in the group.","_def":{"parts":[{"kind":"label","text":"radio send string ","style":[]},{"kind":"param","name":"msg","ref":false}],"parameters":[{"kind":"param","name":"msg","ref":false}]}},"parameters":[{"name":"value","type":"string","options":{"fieldEditorOptions":{"value":{"toString":"true"}}}}],"pyQName":"radio.send_string"},"radio.sendBuffer":{"kind":-3,"attributes":{"help":"radio/send-buffer","weight":57,"advanced":true,"jsDoc":"Broadcasts a buffer (up to 19 bytes long) along with the device serial number\nand running time to any connected micro:bit in the group."},"parameters":[{"name":"msg","type":"Buffer"}],"pyQName":"radio.send_buffer"},"radio.setTransmitSerialNumber":{"kind":-3,"attributes":{"paramDefl":{"transmit":"true"},"help":"radio/set-transmit-serial-number","weight":8,"blockGap":"8","blockId":"radio_set_transmit_serial_number","block":"radio set transmit serial number %transmit","advanced":true,"paramHelp":{"transmit":"value indicating if the serial number is transmitted, eg: true"},"jsDoc":"Set the radio to transmit the serial number in each message.","_def":{"parts":[{"kind":"label","text":"radio set transmit serial number ","style":[]},{"kind":"param","name":"transmit","ref":false}],"parameters":[{"kind":"param","name":"transmit","ref":false}]}},"parameters":[{"name":"transmit","description":"value indicating if the serial number is transmitted, eg: true","type":"boolean","default":"true"}],"pyQName":"radio.set_transmit_serial_number"},"radio.Packet":{"kind":8,"retType":"radio.Packet","extendsTypes":[]},"radio.Packet.receivedNumber":{"kind":2,"retType":"number","attributes":{"jsDoc":"The number payload if a number was sent in this packet (via ``sendNumber()`` or ``sendValue()``)\nor 0 if this packet did not contain a number."},"isInstance":true,"pyQName":"radio.Packet.received_number"},"radio.Packet.receivedString":{"kind":2,"retType":"string","attributes":{"jsDoc":"The string payload if a string was sent in this packet (via ``sendString()`` or ``sendValue()``)\nor the empty string if this packet did not contain a string."},"isInstance":true,"pyQName":"radio.Packet.received_string"},"radio.Packet.receivedBuffer":{"kind":2,"retType":"Buffer","attributes":{"jsDoc":"The buffer payload if a buffer was sent in this packet\nor the empty buffer"},"isInstance":true,"pyQName":"radio.Packet.received_buffer"},"radio.Packet.time":{"kind":2,"retType":"number","attributes":{"jsDoc":"The system time of the sender of the packet at the time the packet was sent."},"isInstance":true},"radio.Packet.serial":{"kind":2,"retType":"number","attributes":{"jsDoc":"The serial number of the sender of the packet or 0 if the sender did not sent their serial number."},"isInstance":true},"radio.Packet.signal":{"kind":2,"retType":"number","attributes":{"jsDoc":"The received signal strength indicator (RSSI) of the packet."},"isInstance":true},"radio.onDataPacketReceived":{"kind":-3,"attributes":{"help":"radio/on-data-packet-received","blockHandlerKey":"radioreceived","deprecated":"true","mutate":"objectdestructuring","mutateText":"Packet","mutateDefaults":"receivedNumber;receivedString:name,receivedNumber:value;receivedString","blockId":"radio_on_packet","block":"on radio received","blockGap":"8","jsDoc":"Deprecated. Use onDataReceived() instead\nRegisters code to run when the radio receives a packet. Also takes the\nreceived packet from the radio queue.","_def":{"parts":[{"kind":"label","text":"on radio received","style":[]}],"parameters":[]}},"parameters":[{"name":"cb","type":"(packet: radio.Packet) => void"}],"pyQName":"radio.on_data_packet_received"},"radio.onReceivedNumberDeprecated":{"kind":-3,"attributes":{"help":"radio/on-received-number","blockHandlerKey":"radioreceived","blockId":"radio_on_number","block":"on radio received","blockGap":"16","useLoc":"radio.onDataPacketReceived","deprecated":"1","jsDoc":"Registers code to run when the radio receives a number. Deprecated, use\nonReceivedNumber instead.","_def":{"parts":[{"kind":"label","text":"on radio received","style":[]}],"parameters":[]}},"parameters":[{"name":"cb","type":"(receivedNumber: number) => void","handlerParameters":[{"name":"receivedNumber","type":"number"}]}],"pyQName":"radio.on_received_number_deprecated"},"radio.onReceivedValueDeprecated":{"kind":-3,"attributes":{"help":"radio/on-received-value","blockHandlerKey":"radioreceived","blockId":"radio_on_value","block":"on radio received","blockGap":"16","useLoc":"radio.onDataPacketReceived","deprecated":"1","jsDoc":"Registers code to run when the radio receives a key value pair. Deprecated, use\nonReceivedValue instead.","_def":{"parts":[{"kind":"label","text":"on radio received","style":[]}],"parameters":[]}},"parameters":[{"name":"cb","type":"(name: string, value: number) => void","handlerParameters":[{"name":"name","type":"string"},{"name":"value","type":"number"}]}],"pyQName":"radio.on_received_value_deprecated"},"radio.onReceivedStringDeprecated":{"kind":-3,"attributes":{"help":"radio/on-received-string","blockHandlerKey":"radioreceived","blockId":"radio_on_string","block":"on radio received","blockGap":"16","useLoc":"radio.onDataPacketReceived","deprecated":"1","jsDoc":"Registers code to run when the radio receives a string. Deprecated, use\nonReceivedString instead.","_def":{"parts":[{"kind":"label","text":"on radio received","style":[]}],"parameters":[]}},"parameters":[{"name":"cb","type":"(receivedString: string) => void","handlerParameters":[{"name":"receivedString","type":"string"}]}],"pyQName":"radio.on_received_string_deprecated"},"radio.onReceivedBufferDeprecated":{"kind":-3,"attributes":{"help":"radio/on-received-buffer","blockHandlerKey":"radioreceived","blockHidden":true,"blockId":"radio_on_buffer","block":"on radio received","blockGap":"16","useLoc":"radio.onDataPacketReceived","deprecated":"1","jsDoc":"Registers code to run when the radio receives a buffer. Deprecated, use\nonReceivedBuffer instead.","_def":{"parts":[{"kind":"label","text":"on radio received","style":[]}],"parameters":[]}},"parameters":[{"name":"cb","type":"(receivedBuffer: Buffer) => void","handlerParameters":[{"name":"receivedBuffer","type":"Buffer"}]}],"pyQName":"radio.on_received_buffer_deprecated"},"radio.receivedNumber":{"kind":-3,"retType":"number","attributes":{"help":"radio/received-number","deprecated":"1","jsDoc":"Returns the number payload from the last packet taken from the radio queue\n(via ``receiveNumber``, ``receiveString``, etc) or 0 if that packet did not\ncontain a number."},"parameters":[],"pyQName":"radio.received_number"},"radio.receivedSerial":{"kind":-3,"retType":"number","attributes":{"help":"radio/received-serial","deprecated":"1","jsDoc":"Returns the serial number of the sender micro:bit from the last packet taken\nfrom the radio queue (via ``receiveNumber``, ``receiveString``, etc) or 0 if\nthat packet did not send a serial number."},"parameters":[],"pyQName":"radio.received_serial"},"radio.receivedString":{"kind":-3,"retType":"string","attributes":{"help":"radio/received-string","deprecated":"1","jsDoc":"Returns the string payload from the last packet taken from the radio queue\n(via ``receiveNumber``, ``receiveString``, etc) or the empty string if that\npacket did not contain a string."},"parameters":[],"pyQName":"radio.received_string"},"radio.receivedBuffer":{"kind":-3,"retType":"Buffer","attributes":{"help":"radio/received-buffer","deprecated":"1","jsDoc":"Returns the buffer payload from the last packet taken from the radio queue\n(via ``receiveNumber``, ``receiveString``, etc) or the empty string if that\npacket did not contain a string."},"parameters":[],"pyQName":"radio.received_buffer"},"radio.receivedTime":{"kind":-3,"retType":"number","attributes":{"help":"radio/received-time","deprecated":"1","jsDoc":"Returns the system time of the sender micro:bit at the moment when it sent the\nlast packet taken from the radio queue (via ``receiveNumber``,\n``receiveString``, etc)."},"parameters":[],"pyQName":"radio.received_time"},"radio.receiveNumber":{"kind":-3,"retType":"number","attributes":{"help":"radio/receive-number","weight":46,"blockId":"radio_datagram_receive","block":"radio receive number","blockGap":"8","deprecated":"true","jsDoc":"Reads the next packet from the radio queue and returns the packet's number\npayload or 0 if the packet did not contain a number.","_def":{"parts":[{"kind":"label","text":"radio receive number","style":[]}],"parameters":[]}},"parameters":[],"pyQName":"radio.receive_number"},"radio.receiveString":{"kind":-3,"retType":"string","attributes":{"blockId":"radio_datagram_receive_string","block":"radio receive string","blockGap":"8","weight":44,"help":"radio/receive-string","deprecated":"true","jsDoc":"Reads the next packet from the radio queue and returns the packet's string\npayload or the empty string if the packet did not contain a string.","_def":{"parts":[{"kind":"label","text":"radio receive string","style":[]}],"parameters":[]}},"parameters":[],"pyQName":"radio.receive_string"},"radio.receivedSignalStrength":{"kind":-3,"retType":"number","attributes":{"help":"radio/received-signal-strength","weight":40,"blockId":"radio_datagram_rssi","block":"radio received signal strength","deprecated":"true","blockHidden":true,"jsDoc":"Gets the received signal strength indicator (RSSI) from the last packet taken\nfrom the radio queue (via ``receiveNumber``, ``receiveString``, etc). Not supported in simulator.","_def":{"parts":[{"kind":"label","text":"radio received signal strength","style":[]}],"parameters":[]}},"parameters":[],"pyQName":"radio.received_signal_strength"},"radio.writeValueToSerial":{"kind":-3,"attributes":{"help":"radio/write-value-to-serial","weight":3,"blockId":"radio_write_value_serial","block":"radio write value to serial","deprecated":"true","jsDoc":"Reads the next packet from the radio queue and and writes it to serial\nas JSON.","_def":{"parts":[{"kind":"label","text":"radio write value to serial","style":[]}],"parameters":[]}},"parameters":[],"pyQName":"radio.write_value_to_serial"},"radio.writeReceivedPacketToSerial":{"kind":-3,"attributes":{"help":"radio/write-received-packet-to-serial","weight":3,"blockId":"radio_write_packet_serial","block":"radio write received packet to serial","advanced":true,"deprecated":"true","jsDoc":"Writes the last received packet to serial as JSON. This should be called\nwithin an ``onDataPacketReceived`` callback.","_def":{"parts":[{"kind":"label","text":"radio write received packet to serial","style":[]}],"parameters":[]}},"parameters":[],"pyQName":"radio.write_received_packet_to_serial"}}},"sha":"a77adbc1cadec1e3d1dc34ccc0c39c765d5aafea6b1538a19916684a0dd1075c"},"libs/devices":{"apis":{"byQName":{"bluetooth":{"kind":5,"retType":"","attributes":{"color":"#007EF4","weight":96,"icon":"","jsDoc":"Support for additional Bluetooth services.\n\nSupport for additional Bluetooth services."}},"bluetooth.startAccelerometerService":{"kind":-3,"attributes":{"help":"bluetooth/start-accelerometer-service","blockId":"bluetooth_start_accelerometer_service","block":"bluetooth accelerometer service","parts":"bluetooth","weight":90,"blockGap":"8","jsDoc":"Starts the Bluetooth accelerometer service","_def":{"parts":[{"kind":"label","text":"bluetooth accelerometer service","style":[]}],"parameters":[]}},"parameters":[],"pyQName":"bluetooth.start_accelerometer_service"},"bluetooth.startButtonService":{"kind":-3,"attributes":{"help":"bluetooth/start-button-service","blockId":"bluetooth_start_button_service","block":"bluetooth button service","blockGap":"8","parts":"bluetooth","weight":89,"jsDoc":"Starts the Bluetooth button service","_def":{"parts":[{"kind":"label","text":"bluetooth button service","style":[]}],"parameters":[]}},"parameters":[],"pyQName":"bluetooth.start_button_service"},"bluetooth.startIOPinService":{"kind":-3,"attributes":{"help":"bluetooth/start-io-pin-service","blockId":"bluetooth_start_io_pin_service","block":"bluetooth io pin service","blockGap":"8","parts":"bluetooth","weight":88,"jsDoc":"Starts the Bluetooth IO pin service.","_def":{"parts":[{"kind":"label","text":"bluetooth io pin service","style":[]}],"parameters":[]}},"parameters":[],"pyQName":"bluetooth.start_io_pin_service"},"bluetooth.startLEDService":{"kind":-3,"attributes":{"help":"bluetooth/start-led-service","blockId":"bluetooth_start_led_service","block":"bluetooth led service","blockGap":"8","parts":"bluetooth","weight":87,"jsDoc":"Starts the Bluetooth LED service","_def":{"parts":[{"kind":"label","text":"bluetooth led service","style":[]}],"parameters":[]}},"parameters":[],"pyQName":"bluetooth.start_led_service"},"bluetooth.startTemperatureService":{"kind":-3,"attributes":{"help":"bluetooth/start-temperature-service","blockId":"bluetooth_start_temperature_service","block":"bluetooth temperature service","blockGap":"8","parts":"bluetooth","weight":86,"jsDoc":"Starts the Bluetooth temperature service","_def":{"parts":[{"kind":"label","text":"bluetooth temperature service","style":[]}],"parameters":[]}},"parameters":[],"pyQName":"bluetooth.start_temperature_service"},"bluetooth.startMagnetometerService":{"kind":-3,"attributes":{"help":"bluetooth/start-magnetometer-service","blockId":"bluetooth_start_magnetometer_service","block":"bluetooth magnetometer service","parts":"bluetooth","weight":85,"jsDoc":"Starts the Bluetooth magnetometer service","_def":{"parts":[{"kind":"label","text":"bluetooth magnetometer service","style":[]}],"parameters":[]}},"parameters":[],"pyQName":"bluetooth.start_magnetometer_service"},"bluetooth.startUartService":{"kind":-3,"attributes":{"help":"bluetooth/start-uart-service","blockId":"bluetooth_start_uart_service","block":"bluetooth uart service","parts":"bluetooth","advanced":true,"jsDoc":"Starts the Bluetooth UART service","_def":{"parts":[{"kind":"label","text":"bluetooth uart service","style":[]}],"parameters":[]}},"parameters":[],"pyQName":"bluetooth.start_uart_service"},"bluetooth.uartWriteBuffer":{"kind":-3,"attributes":{"jsDoc":"Sends a buffer of data via Bluetooth UART"},"parameters":[{"name":"buffer","type":"Buffer"}],"pyQName":"bluetooth.uart_write_buffer"},"bluetooth.uartReadBuffer":{"kind":-3,"retType":"Buffer","attributes":{"jsDoc":"Reads buffered UART data into a buffer"},"parameters":[],"pyQName":"bluetooth.uart_read_buffer"},"bluetooth.onUartDataReceived":{"kind":-3,"attributes":{"help":"bluetooth/on-uart-data-received","weight":18,"blockId":"bluetooth_on_data_received","block":"bluetooth|on data received %delimiters=serial_delimiter_conv","paramHelp":{"delimiters":"the characters to match received characters against."},"jsDoc":"Registers an event to be fired when one of the delimiter is matched.","_def":{"parts":[{"kind":"label","text":"bluetooth","style":[]},{"kind":"break"},{"kind":"label","text":"on data received ","style":[]},{"kind":"param","name":"delimiters","shadowBlockId":"serial_delimiter_conv","ref":false}],"parameters":[{"kind":"param","name":"delimiters","shadowBlockId":"serial_delimiter_conv","ref":false}]}},"parameters":[{"name":"delimiters","description":"the characters to match received characters against.","type":"string"},{"name":"body","type":"() => void","handlerParameters":[]}],"pyQName":"bluetooth.on_uart_data_received"},"bluetooth.onBluetoothConnected":{"kind":-3,"attributes":{"help":"bluetooth/on-bluetooth-connected","weight":20,"blockId":"bluetooth_on_connected","block":"on bluetooth connected","blockGap":"8","parts":"bluetooth","paramHelp":{"body":"Code to run when a Bluetooth connection is established"},"jsDoc":"Register code to run when the micro:bit is connected to over Bluetooth","_def":{"parts":[{"kind":"label","text":"on bluetooth connected","style":[]}],"parameters":[]}},"parameters":[{"name":"body","description":"Code to run when a Bluetooth connection is established","type":"() => void","handlerParameters":[]}],"pyQName":"bluetooth.on_bluetooth_connected"},"bluetooth.onBluetoothDisconnected":{"kind":-3,"attributes":{"help":"bluetooth/on-bluetooth-disconnected","weight":19,"blockId":"bluetooth_on_disconnected","block":"on bluetooth disconnected","parts":"bluetooth","paramHelp":{"body":"Code to run when a Bluetooth connection is lost"},"jsDoc":"Register code to run when a bluetooth connection to the micro:bit is lost","_def":{"parts":[{"kind":"label","text":"on bluetooth disconnected","style":[]}],"parameters":[]}},"parameters":[{"name":"body","description":"Code to run when a Bluetooth connection is lost","type":"() => void","handlerParameters":[]}],"pyQName":"bluetooth.on_bluetooth_disconnected"},"bluetooth.advertiseUrl":{"kind":-3,"attributes":{"paramDefl":{"url":"https://makecode.com","power":"7"},"blockId":"eddystone_advertise_url","block":"bluetooth advertise url %url|with power %power|connectable %connectable","parts":"bluetooth","weight":11,"blockGap":"8","help":"bluetooth/advertise-url","blockExternalInputs":"1","hidden":"1","deprecated":"1","inlineInputMode":"external","paramHelp":{"url":"the url to transmit. Must be no longer than the supported eddystone url length, eg: \"https://makecode.com\"","power":"power level between 0 and 7, eg: 7","connectable":"true to keep bluetooth connectable for other services, false otherwise."},"jsDoc":"Advertise an Eddystone URL","_def":{"parts":[{"kind":"label","text":"bluetooth advertise url ","style":[]},{"kind":"param","name":"url","ref":false},{"kind":"break"},{"kind":"label","text":"with power ","style":[]},{"kind":"param","name":"power","ref":false},{"kind":"break"},{"kind":"label","text":"connectable ","style":[]},{"kind":"param","name":"connectable","ref":false}],"parameters":[{"kind":"param","name":"url","ref":false},{"kind":"param","name":"power","ref":false},{"kind":"param","name":"connectable","ref":false}]}},"parameters":[{"name":"url","description":"the url to transmit. Must be no longer than the supported eddystone url length, eg: \"https://makecode.com\"","type":"string","default":"https://makecode.com"},{"name":"power","description":"power level between 0 and 7, eg: 7","default":"7"},{"name":"connectable","description":"true to keep bluetooth connectable for other services, false otherwise.","type":"boolean"}],"pyQName":"bluetooth.advertise_url"},"bluetooth.advertiseUidBuffer":{"kind":-3,"attributes":{"paramDefl":{"power":"7"},"parts":"bluetooth","weight":12,"advanced":true,"deprecated":"1","paramHelp":{"nsAndInstance":"16 bytes buffer of namespace (bytes 0-9) and instance (bytes 10-15)","power":"power level between 0 and 7, eg: 7","connectable":"true to keep bluetooth connectable for other services, false otherwise."},"jsDoc":"Advertise an Eddystone UID"},"parameters":[{"name":"nsAndInstance","description":"16 bytes buffer of namespace (bytes 0-9) and instance (bytes 10-15)","type":"Buffer"},{"name":"power","description":"power level between 0 and 7, eg: 7","default":"7"},{"name":"connectable","description":"true to keep bluetooth connectable for other services, false otherwise.","type":"boolean"}],"pyQName":"bluetooth.advertise_uid_buffer"},"bluetooth.setTransmitPower":{"kind":-3,"attributes":{"paramDefl":{"power":"7."},"parts":"bluetooth","weight":5,"help":"bluetooth/set-transmit-power","advanced":true,"blockId":"bluetooth_settransmitpower","block":"bluetooth set transmit power %power","paramHelp":{"power":"power level between 0 (minimal) and 7 (maximum), eg: 7."},"jsDoc":"Sets the bluetooth transmit power between 0 (minimal) and 7 (maximum).","_def":{"parts":[{"kind":"label","text":"bluetooth set transmit power ","style":[]},{"kind":"param","name":"power","ref":false}],"parameters":[{"kind":"param","name":"power","ref":false}]}},"parameters":[{"name":"power","description":"power level between 0 (minimal) and 7 (maximum), eg: 7.","default":"7."}],"pyQName":"bluetooth.set_transmit_power"},"bluetooth.stopAdvertising":{"kind":-3,"attributes":{"blockId":"eddystone_stop_advertising","block":"bluetooth stop advertising","parts":"bluetooth","weight":10,"help":"bluetooth/stop-advertising","advanced":true,"hidden":"1","deprecated":"1","jsDoc":"Stops advertising Eddystone end points","_def":{"parts":[{"kind":"label","text":"bluetooth stop advertising","style":[]}],"parameters":[]}},"parameters":[],"pyQName":"bluetooth.stop_advertising"},"bluetooth.NEW_LINE":{"kind":4,"retType":"string"},"bluetooth.__log":{"kind":-3,"attributes":{"jsDoc":"Internal use"},"parameters":[{"name":"priority"},{"name":"msg","type":"string"}]},"bluetooth.uartWriteString":{"kind":-3,"attributes":{"help":"bluetooth/uart-write-string","weight":80,"blockId":"bluetooth_uart_write","block":"bluetooth uart|write string %data","blockGap":"8","parts":"bluetooth","advanced":true,"jsDoc":"Writes to the Bluetooth UART service buffer. From there the data is transmitted over Bluetooth to a connected device.","_def":{"parts":[{"kind":"label","text":"bluetooth uart","style":[]},{"kind":"break"},{"kind":"label","text":"write string ","style":[]},{"kind":"param","name":"data","ref":false}],"parameters":[{"kind":"param","name":"data","ref":false}]}},"parameters":[{"name":"data","type":"string"}],"pyQName":"bluetooth.uart_write_string"},"bluetooth.uartWriteLine":{"kind":-3,"attributes":{"help":"bluetooth/uart-write-line","weight":79,"blockId":"bluetooth_uart_line","block":"bluetooth uart|write line %data","blockGap":"8","parts":"bluetooth","advanced":true,"jsDoc":"Writes to the Bluetooth UART service buffer. From there the data is transmitted over Bluetooth to a connected device.","_def":{"parts":[{"kind":"label","text":"bluetooth uart","style":[]},{"kind":"break"},{"kind":"label","text":"write line ","style":[]},{"kind":"param","name":"data","ref":false}],"parameters":[{"kind":"param","name":"data","ref":false}]}},"parameters":[{"name":"data","type":"string"}],"pyQName":"bluetooth.uart_write_line"},"bluetooth.uartWriteNumber":{"kind":-3,"attributes":{"help":"bluetooth/uart-write-number","weight":89,"blockGap":"8","advanced":true,"blockId":"bluetooth_uart_writenumber","block":"bluetooth uart|write number %value","jsDoc":"Prints a numeric value to the serial","_def":{"parts":[{"kind":"label","text":"bluetooth uart","style":[]},{"kind":"break"},{"kind":"label","text":"write number ","style":[]},{"kind":"param","name":"value","ref":false}],"parameters":[{"kind":"param","name":"value","ref":false}]}},"parameters":[{"name":"value"}],"pyQName":"bluetooth.uart_write_number"},"bluetooth.uartWriteValue":{"kind":-3,"attributes":{"paramDefl":{"name":"x"},"weight":78,"help":"bluetooth/uart-write-value","advanced":true,"blockId":"bluetooth_uart_writevalue","block":"bluetooth uart|write value %name|= %value","paramHelp":{"name":"name of the value stream, eg: x","value":"to write"},"jsDoc":"Writes a ``name: value`` pair line to the serial.","_def":{"parts":[{"kind":"label","text":"bluetooth uart","style":[]},{"kind":"break"},{"kind":"label","text":"write value ","style":[]},{"kind":"param","name":"name","ref":false},{"kind":"break"},{"kind":"label","text":"= ","style":[]},{"kind":"param","name":"value","ref":false}],"parameters":[{"kind":"param","name":"name","ref":false},{"kind":"param","name":"value","ref":false}]}},"parameters":[{"name":"name","description":"name of the value stream, eg: x","type":"string","default":"x"},{"name":"value","description":"to write"}],"pyQName":"bluetooth.uart_write_value"},"bluetooth.uartReadUntil":{"kind":-3,"retType":"string","attributes":{"help":"bluetooth/uart-read-until","weight":75,"blockId":"bluetooth_uart_read","block":"bluetooth uart|read until %del=serial_delimiter_conv","parts":"bluetooth","advanced":true,"jsDoc":"Reads from the Bluetooth UART service buffer, returning its contents when the specified delimiter character is encountered.","_def":{"parts":[{"kind":"label","text":"bluetooth uart","style":[]},{"kind":"break"},{"kind":"label","text":"read until ","style":[]},{"kind":"param","name":"del","shadowBlockId":"serial_delimiter_conv","ref":false}],"parameters":[{"kind":"param","name":"del","shadowBlockId":"serial_delimiter_conv","ref":false}]}},"parameters":[{"name":"del","type":"string"}],"pyQName":"bluetooth.uart_read_until"},"bluetooth.advertiseUid":{"kind":-3,"attributes":{"paramDefl":{"power":"7"},"blockId":"eddystone_advertise_uid","block":"bluetooth advertise UID|namespace (bytes 6-9)%ns|instance (bytes 2-6)%instance|with power %power|connectable %connectable","parts":"bluetooth","weight":12,"blockGap":"8","help":"bluetooth/advertise-uid","blockExternalInputs":"1","hidden":"1","deprecated":"1","inlineInputMode":"external","paramHelp":{"ns":"4 last bytes of the namespace uid","instance":"4 last bytes of the instance uid","power":"power level between 0 and 7, eg: 7","connectable":"true to keep bluetooth connectable for other services, false otherwise."},"jsDoc":"Advertise an Eddystone UID","_def":{"parts":[{"kind":"label","text":"bluetooth advertise UID","style":[]},{"kind":"break"},{"kind":"label","text":"namespace (bytes 6-9)","style":[]},{"kind":"param","name":"ns","ref":false},{"kind":"break"},{"kind":"label","text":"instance (bytes 2-6)","style":[]},{"kind":"param","name":"instance","ref":false},{"kind":"break"},{"kind":"label","text":"with power ","style":[]},{"kind":"param","name":"power","ref":false},{"kind":"break"},{"kind":"label","text":"connectable ","style":[]},{"kind":"param","name":"connectable","ref":false}],"parameters":[{"kind":"param","name":"ns","ref":false},{"kind":"param","name":"instance","ref":false},{"kind":"param","name":"power","ref":false},{"kind":"param","name":"connectable","ref":false}]}},"parameters":[{"name":"ns","description":"4 last bytes of the namespace uid"},{"name":"instance","description":"4 last bytes of the instance uid"},{"name":"power","description":"power level between 0 and 7, eg: 7","default":"7"},{"name":"connectable","description":"true to keep bluetooth connectable for other services, false otherwise.","type":"boolean"}],"pyQName":"bluetooth.advertise_uid"},"MesCameraEvent":{"kind":6,"retType":"MesCameraEvent","extendsTypes":["MesCameraEvent","Number"]},"MesCameraEvent.TakePhoto":{"retType":"MesCameraEvent.TakePhoto","attributes":{"block":"take photo","_def":{"parts":[{"kind":"label","text":"take photo","style":[]}],"parameters":[]}},"extendsTypes":["MesCameraEvent.TakePhoto","Number"],"pyQName":"MesCameraEvent.TAKE_PHOTO"},"MesCameraEvent.StartVideoCapture":{"retType":"MesCameraEvent.StartVideoCapture","attributes":{"block":"start video capture","_def":{"parts":[{"kind":"label","text":"start video capture","style":[]}],"parameters":[]}},"extendsTypes":["MesCameraEvent.StartVideoCapture","Number"],"pyQName":"MesCameraEvent.START_VIDEO_CAPTURE"},"MesCameraEvent.StopVideoCapture":{"retType":"MesCameraEvent.StopVideoCapture","attributes":{"block":"stop video capture","_def":{"parts":[{"kind":"label","text":"stop video capture","style":[]}],"parameters":[]}},"extendsTypes":["MesCameraEvent.StopVideoCapture","Number"],"pyQName":"MesCameraEvent.STOP_VIDEO_CAPTURE"},"MesCameraEvent.ToggleFrontRear":{"retType":"MesCameraEvent.ToggleFrontRear","attributes":{"block":"toggle front-rear","_def":{"parts":[{"kind":"label","text":"toggle front-rear","style":[]}],"parameters":[]}},"extendsTypes":["MesCameraEvent.ToggleFrontRear","Number"],"pyQName":"MesCameraEvent.TOGGLE_FRONT_REAR"},"MesCameraEvent.LaunchPhotoMode":{"retType":"MesCameraEvent.LaunchPhotoMode","attributes":{"block":"launch photo mode","_def":{"parts":[{"kind":"label","text":"launch photo mode","style":[]}],"parameters":[]}},"extendsTypes":["MesCameraEvent.LaunchPhotoMode","Number"],"pyQName":"MesCameraEvent.LAUNCH_PHOTO_MODE"},"MesCameraEvent.LaunchVideoMode":{"retType":"MesCameraEvent.LaunchVideoMode","attributes":{"block":"launch video mode","_def":{"parts":[{"kind":"label","text":"launch video mode","style":[]}],"parameters":[]}},"extendsTypes":["MesCameraEvent.LaunchVideoMode","Number"],"pyQName":"MesCameraEvent.LAUNCH_VIDEO_MODE"},"MesCameraEvent.StopPhotoMode":{"retType":"MesCameraEvent.StopPhotoMode","attributes":{"block":"stop photo mode","_def":{"parts":[{"kind":"label","text":"stop photo mode","style":[]}],"parameters":[]}},"extendsTypes":["MesCameraEvent.StopPhotoMode","Number"],"pyQName":"MesCameraEvent.STOP_PHOTO_MODE"},"MesCameraEvent.StopVideoMode":{"retType":"MesCameraEvent.StopVideoMode","attributes":{"block":"stop video mode","_def":{"parts":[{"kind":"label","text":"stop video mode","style":[]}],"parameters":[]}},"extendsTypes":["MesCameraEvent.StopVideoMode","Number"],"pyQName":"MesCameraEvent.STOP_VIDEO_MODE"},"MesAlertEvent":{"kind":6,"retType":"MesAlertEvent","extendsTypes":["MesAlertEvent","Number"]},"MesAlertEvent.DisplayToast":{"retType":"MesAlertEvent.DisplayToast","attributes":{"block":"display toast","_def":{"parts":[{"kind":"label","text":"display toast","style":[]}],"parameters":[]}},"extendsTypes":["MesAlertEvent.DisplayToast","Number"],"pyQName":"MesAlertEvent.DISPLAY_TOAST"},"MesAlertEvent.Vibrate":{"retType":"MesAlertEvent.Vibrate","attributes":{"block":"vibrate","_def":{"parts":[{"kind":"label","text":"vibrate","style":[]}],"parameters":[]}},"extendsTypes":["MesAlertEvent.Vibrate","Number"],"pyQName":"MesAlertEvent.VIBRATE"},"MesAlertEvent.PlaySound":{"retType":"MesAlertEvent.PlaySound","attributes":{"block":"play sound","_def":{"parts":[{"kind":"label","text":"play sound","style":[]}],"parameters":[]}},"extendsTypes":["MesAlertEvent.PlaySound","Number"],"pyQName":"MesAlertEvent.PLAY_SOUND"},"MesAlertEvent.PlayRingtone":{"retType":"MesAlertEvent.PlayRingtone","attributes":{"block":"play ring tone","_def":{"parts":[{"kind":"label","text":"play ring tone","style":[]}],"parameters":[]}},"extendsTypes":["MesAlertEvent.PlayRingtone","Number"],"pyQName":"MesAlertEvent.PLAY_RINGTONE"},"MesAlertEvent.FindMyPhone":{"retType":"MesAlertEvent.FindMyPhone","attributes":{"block":"find my phone","_def":{"parts":[{"kind":"label","text":"find my phone","style":[]}],"parameters":[]}},"extendsTypes":["MesAlertEvent.FindMyPhone","Number"],"pyQName":"MesAlertEvent.FIND_MY_PHONE"},"MesAlertEvent.RingAlarm":{"retType":"MesAlertEvent.RingAlarm","attributes":{"block":"ring alarm","_def":{"parts":[{"kind":"label","text":"ring alarm","style":[]}],"parameters":[]}},"extendsTypes":["MesAlertEvent.RingAlarm","Number"],"pyQName":"MesAlertEvent.RING_ALARM"},"MesAlertEvent.RingAlarm2":{"retType":"MesAlertEvent.RingAlarm2","attributes":{"block":"ring alarm 2","_def":{"parts":[{"kind":"label","text":"ring alarm 2","style":[]}],"parameters":[]}},"extendsTypes":["MesAlertEvent.RingAlarm2","Number"],"pyQName":"MesAlertEvent.RING_ALARM2"},"MesAlertEvent.RingAlarm3":{"retType":"MesAlertEvent.RingAlarm3","attributes":{"block":"ring alarm 3","_def":{"parts":[{"kind":"label","text":"ring alarm 3","style":[]}],"parameters":[]}},"extendsTypes":["MesAlertEvent.RingAlarm3","Number"],"pyQName":"MesAlertEvent.RING_ALARM3"},"MesAlertEvent.RingAlarm4":{"retType":"MesAlertEvent.RingAlarm4","attributes":{"block":"ring alarm 4","_def":{"parts":[{"kind":"label","text":"ring alarm 4","style":[]}],"parameters":[]}},"extendsTypes":["MesAlertEvent.RingAlarm4","Number"],"pyQName":"MesAlertEvent.RING_ALARM4"},"MesAlertEvent.RingAlarm5":{"retType":"MesAlertEvent.RingAlarm5","attributes":{"block":"ring alarm 5","_def":{"parts":[{"kind":"label","text":"ring alarm 5","style":[]}],"parameters":[]}},"extendsTypes":["MesAlertEvent.RingAlarm5","Number"],"pyQName":"MesAlertEvent.RING_ALARM5"},"MesAlertEvent.RingAlarm6":{"retType":"MesAlertEvent.RingAlarm6","attributes":{"block":"ring alarm 6","_def":{"parts":[{"kind":"label","text":"ring alarm 6","style":[]}],"parameters":[]}},"extendsTypes":["MesAlertEvent.RingAlarm6","Number"],"pyQName":"MesAlertEvent.RING_ALARM6"},"MesDeviceInfo":{"kind":6,"retType":"MesDeviceInfo","extendsTypes":["MesDeviceInfo","Number"]},"MesDeviceInfo.IncomingCall":{"retType":"MesDeviceInfo.IncomingCall","attributes":{"block":"incoming call","_def":{"parts":[{"kind":"label","text":"incoming call","style":[]}],"parameters":[]}},"extendsTypes":["MesDeviceInfo.IncomingCall","Number"],"pyQName":"MesDeviceInfo.INCOMING_CALL"},"MesDeviceInfo.IncomingMessage":{"retType":"MesDeviceInfo.IncomingMessage","attributes":{"block":"incoming message","_def":{"parts":[{"kind":"label","text":"incoming message","style":[]}],"parameters":[]}},"extendsTypes":["MesDeviceInfo.IncomingMessage","Number"],"pyQName":"MesDeviceInfo.INCOMING_MESSAGE"},"MesDeviceInfo.OrientationLandscape":{"retType":"MesDeviceInfo.OrientationLandscape","attributes":{"block":"orientation landscape","_def":{"parts":[{"kind":"label","text":"orientation landscape","style":[]}],"parameters":[]}},"extendsTypes":["MesDeviceInfo.OrientationLandscape","Number"],"pyQName":"MesDeviceInfo.ORIENTATION_LANDSCAPE"},"MesDeviceInfo.OrientationPortrait":{"retType":"MesDeviceInfo.OrientationPortrait","attributes":{"block":"orientation portrait","_def":{"parts":[{"kind":"label","text":"orientation portrait","style":[]}],"parameters":[]}},"extendsTypes":["MesDeviceInfo.OrientationPortrait","Number"],"pyQName":"MesDeviceInfo.ORIENTATION_PORTRAIT"},"MesDeviceInfo.Shaken":{"retType":"MesDeviceInfo.Shaken","attributes":{"block":"shaken","_def":{"parts":[{"kind":"label","text":"shaken","style":[]}],"parameters":[]}},"extendsTypes":["MesDeviceInfo.Shaken","Number"],"pyQName":"MesDeviceInfo.SHAKEN"},"MesDeviceInfo.DisplayOff":{"retType":"MesDeviceInfo.DisplayOff","attributes":{"block":"display off","_def":{"parts":[{"kind":"label","text":"display off","style":[]}],"parameters":[]}},"extendsTypes":["MesDeviceInfo.DisplayOff","Number"],"pyQName":"MesDeviceInfo.DISPLAY_OFF"},"MesDeviceInfo.DisplayOn":{"retType":"MesDeviceInfo.DisplayOn","attributes":{"block":"display on","_def":{"parts":[{"kind":"label","text":"display on","style":[]}],"parameters":[]}},"extendsTypes":["MesDeviceInfo.DisplayOn","Number"],"pyQName":"MesDeviceInfo.DISPLAY_ON"},"MesRemoteControlEvent":{"kind":6,"retType":"MesRemoteControlEvent","extendsTypes":["MesRemoteControlEvent","Number"]},"MesRemoteControlEvent.play":{"retType":"MesRemoteControlEvent.play","attributes":{"block":"play","_def":{"parts":[{"kind":"label","text":"play","style":[]}],"parameters":[]}},"extendsTypes":["MesRemoteControlEvent.play","Number"],"pyQName":"MesRemoteControlEvent.PLAY"},"MesRemoteControlEvent.pause":{"retType":"MesRemoteControlEvent.pause","attributes":{"block":"pause","_def":{"parts":[{"kind":"label","text":"pause","style":[]}],"parameters":[]}},"extendsTypes":["MesRemoteControlEvent.pause","Number"],"pyQName":"MesRemoteControlEvent.PAUSE"},"MesRemoteControlEvent.stop":{"retType":"MesRemoteControlEvent.stop","attributes":{"block":"stop","_def":{"parts":[{"kind":"label","text":"stop","style":[]}],"parameters":[]}},"extendsTypes":["MesRemoteControlEvent.stop","Number"],"pyQName":"MesRemoteControlEvent.STOP"},"MesRemoteControlEvent.nextTrack":{"retType":"MesRemoteControlEvent.nextTrack","attributes":{"block":"next track","_def":{"parts":[{"kind":"label","text":"next track","style":[]}],"parameters":[]}},"extendsTypes":["MesRemoteControlEvent.nextTrack","Number"],"pyQName":"MesRemoteControlEvent.NEXT_TRACK"},"MesRemoteControlEvent.previousTrack":{"retType":"MesRemoteControlEvent.previousTrack","attributes":{"block":"previous track","_def":{"parts":[{"kind":"label","text":"previous track","style":[]}],"parameters":[]}},"extendsTypes":["MesRemoteControlEvent.previousTrack","Number"],"pyQName":"MesRemoteControlEvent.PREVIOUS_TRACK"},"MesRemoteControlEvent.forward":{"retType":"MesRemoteControlEvent.forward","attributes":{"block":"forward","_def":{"parts":[{"kind":"label","text":"forward","style":[]}],"parameters":[]}},"extendsTypes":["MesRemoteControlEvent.forward","Number"],"pyQName":"MesRemoteControlEvent.FORWARD"},"MesRemoteControlEvent.rewind":{"retType":"MesRemoteControlEvent.rewind","attributes":{"block":"rewind","_def":{"parts":[{"kind":"label","text":"rewind","style":[]}],"parameters":[]}},"extendsTypes":["MesRemoteControlEvent.rewind","Number"],"pyQName":"MesRemoteControlEvent.REWIND"},"MesRemoteControlEvent.volumeUp":{"retType":"MesRemoteControlEvent.volumeUp","attributes":{"block":"volume up","_def":{"parts":[{"kind":"label","text":"volume up","style":[]}],"parameters":[]}},"extendsTypes":["MesRemoteControlEvent.volumeUp","Number"],"pyQName":"MesRemoteControlEvent.VOLUME_UP"},"MesRemoteControlEvent.volumeDown":{"retType":"MesRemoteControlEvent.volumeDown","attributes":{"block":"volume down","_def":{"parts":[{"kind":"label","text":"volume down","style":[]}],"parameters":[]}},"extendsTypes":["MesRemoteControlEvent.volumeDown","Number"],"pyQName":"MesRemoteControlEvent.VOLUME_DOWN"},"devices":{"kind":5,"retType":"","attributes":{"color":"#008272","weight":80,"icon":"","jsDoc":"Control a phone with the BBC micro:bit via Bluetooth."}},"devices.signalStrength":{"kind":-3,"retType":"number","attributes":{"help":"devices/signal-strength","weight":24,"blockId":"devices_signal_strength","block":"signal strength","blockGap":"14","icon":"","jsDoc":"Returns the last signal strength reported by the paired device.","_def":{"parts":[{"kind":"label","text":"signal strength","style":[]}],"parameters":[]}},"parameters":[],"pyQName":"devices.signal_strength"},"devices.onSignalStrengthChanged":{"kind":-3,"attributes":{"weight":23,"help":"devices/on-signal-strength-changed","blockId":"devices_signal_strength_changed_event","block":"on signal strength changed","icon":"","paramHelp":{"body":"Code run when the signal strength changes."},"jsDoc":"Registers code to run when the device notifies about a change of signal strength.","_def":{"parts":[{"kind":"label","text":"on signal strength changed","style":[]}],"parameters":[]}},"parameters":[{"name":"body","description":"Code run when the signal strength changes.","type":"() => void","handlerParameters":[]}],"pyQName":"devices.on_signal_strength_changed"},"devices.tellCameraTo":{"kind":-3,"attributes":{"weight":30,"help":"devices/tell-camera-to","blockId":"devices_camera","icon":"","block":"tell camera to|%property","blockGap":"8","paramHelp":{"event":"event description"},"jsDoc":"Sends a ``camera`` command to the parent device.","_def":{"parts":[{"kind":"label","text":"tell camera to","style":[]},{"kind":"break"},{"kind":"param","name":"property","ref":false}],"parameters":[{"kind":"param","name":"property","ref":false}]}},"parameters":[{"name":"event","description":"event description","type":"MesCameraEvent","isEnum":true}],"pyQName":"devices.tell_camera_to"},"devices.tellRemoteControlTo":{"kind":-3,"attributes":{"weight":29,"help":"devices/tell-remote-control-to","blockId":"devices_remote_control","block":"tell remote control to|%property","blockGap":"14","icon":"","paramHelp":{"event":"event description"},"jsDoc":"Sends a ``remote control`` command to the parent device.","_def":{"parts":[{"kind":"label","text":"tell remote control to","style":[]},{"kind":"break"},{"kind":"param","name":"property","ref":false}],"parameters":[{"kind":"param","name":"property","ref":false}]}},"parameters":[{"name":"event","description":"event description","type":"MesRemoteControlEvent","isEnum":true}],"pyQName":"devices.tell_remote_control_to"},"devices.raiseAlertTo":{"kind":-3,"attributes":{"weight":27,"help":"devices/raise-alert-to","blockId":"devices_alert","block":"raise alert to|%property","icon":"","paramHelp":{"event":"event description"},"jsDoc":"Sends an ``alert`` command to the parent device.","_def":{"parts":[{"kind":"label","text":"raise alert to","style":[]},{"kind":"break"},{"kind":"param","name":"property","ref":false}],"parameters":[{"kind":"param","name":"property","ref":false}]}},"parameters":[{"name":"event","description":"event description","type":"MesAlertEvent","isEnum":true}],"pyQName":"devices.raise_alert_to"},"devices.onNotified":{"kind":-3,"attributes":{"help":"devices/on-notified","weight":26,"blockId":"devices_device_info_event","block":"on notified|%event","icon":"","paramHelp":{"event":"event description","body":"code handler when event is triggered"},"jsDoc":"Registers code to run when the device notifies about a particular event.","_def":{"parts":[{"kind":"label","text":"on notified","style":[]},{"kind":"break"},{"kind":"param","name":"event","ref":false}],"parameters":[{"kind":"param","name":"event","ref":false}]}},"parameters":[{"name":"event","description":"event description","type":"MesDeviceInfo","isEnum":true},{"name":"body","description":"code handler when event is triggered","type":"() => void","handlerParameters":[]}],"pyQName":"devices.on_notified"},"devices.onGamepadButton":{"kind":-3,"attributes":{"help":"devices/on-gamepad-button","weight":25,"blockId":"devices_gamepad_event","block":"on gamepad button|%NAME","icon":"","paramHelp":{"name":"button name","body":"code to run when button is pressed"},"jsDoc":"Register code to run when the micro:bit receives a command from the paired gamepad.","_def":{"parts":[{"kind":"label","text":"on gamepad button","style":[]},{"kind":"break"},{"kind":"param","name":"NAME","ref":false}],"parameters":[{"kind":"param","name":"NAME","ref":false}]}},"parameters":[{"name":"name","description":"button name","type":"MesDpadButtonInfo","isEnum":true},{"name":"body","description":"code to run when button is pressed","type":"() => void","handlerParameters":[]}],"pyQName":"devices.on_gamepad_button"}}},"sha":"85d2dcc4f40af81ba7a70e6920e4641ed86ac63f361a80ae52e5a05bd5ea85b6"},"libs/bluetooth":{"apis":{"byQName":{"bluetooth":{"kind":5,"retType":"","attributes":{"color":"#007EF4","weight":96,"icon":"","jsDoc":"Support for additional Bluetooth services.\n\nSupport for additional Bluetooth services."}},"bluetooth.startAccelerometerService":{"kind":-3,"attributes":{"help":"bluetooth/start-accelerometer-service","blockId":"bluetooth_start_accelerometer_service","block":"bluetooth accelerometer service","parts":"bluetooth","weight":90,"blockGap":"8","jsDoc":"Starts the Bluetooth accelerometer service","_def":{"parts":[{"kind":"label","text":"bluetooth accelerometer service","style":[]}],"parameters":[]}},"parameters":[],"pyQName":"bluetooth.start_accelerometer_service"},"bluetooth.startButtonService":{"kind":-3,"attributes":{"help":"bluetooth/start-button-service","blockId":"bluetooth_start_button_service","block":"bluetooth button service","blockGap":"8","parts":"bluetooth","weight":89,"jsDoc":"Starts the Bluetooth button service","_def":{"parts":[{"kind":"label","text":"bluetooth button service","style":[]}],"parameters":[]}},"parameters":[],"pyQName":"bluetooth.start_button_service"},"bluetooth.startIOPinService":{"kind":-3,"attributes":{"help":"bluetooth/start-io-pin-service","blockId":"bluetooth_start_io_pin_service","block":"bluetooth io pin service","blockGap":"8","parts":"bluetooth","weight":88,"jsDoc":"Starts the Bluetooth IO pin service.","_def":{"parts":[{"kind":"label","text":"bluetooth io pin service","style":[]}],"parameters":[]}},"parameters":[],"pyQName":"bluetooth.start_io_pin_service"},"bluetooth.startLEDService":{"kind":-3,"attributes":{"help":"bluetooth/start-led-service","blockId":"bluetooth_start_led_service","block":"bluetooth led service","blockGap":"8","parts":"bluetooth","weight":87,"jsDoc":"Starts the Bluetooth LED service","_def":{"parts":[{"kind":"label","text":"bluetooth led service","style":[]}],"parameters":[]}},"parameters":[],"pyQName":"bluetooth.start_led_service"},"bluetooth.startTemperatureService":{"kind":-3,"attributes":{"help":"bluetooth/start-temperature-service","blockId":"bluetooth_start_temperature_service","block":"bluetooth temperature service","blockGap":"8","parts":"bluetooth","weight":86,"jsDoc":"Starts the Bluetooth temperature service","_def":{"parts":[{"kind":"label","text":"bluetooth temperature service","style":[]}],"parameters":[]}},"parameters":[],"pyQName":"bluetooth.start_temperature_service"},"bluetooth.startMagnetometerService":{"kind":-3,"attributes":{"help":"bluetooth/start-magnetometer-service","blockId":"bluetooth_start_magnetometer_service","block":"bluetooth magnetometer service","parts":"bluetooth","weight":85,"jsDoc":"Starts the Bluetooth magnetometer service","_def":{"parts":[{"kind":"label","text":"bluetooth magnetometer service","style":[]}],"parameters":[]}},"parameters":[],"pyQName":"bluetooth.start_magnetometer_service"},"bluetooth.startUartService":{"kind":-3,"attributes":{"help":"bluetooth/start-uart-service","blockId":"bluetooth_start_uart_service","block":"bluetooth uart service","parts":"bluetooth","advanced":true,"jsDoc":"Starts the Bluetooth UART service","_def":{"parts":[{"kind":"label","text":"bluetooth uart service","style":[]}],"parameters":[]}},"parameters":[],"pyQName":"bluetooth.start_uart_service"},"bluetooth.uartWriteBuffer":{"kind":-3,"attributes":{"jsDoc":"Sends a buffer of data via Bluetooth UART"},"parameters":[{"name":"buffer","type":"Buffer"}],"pyQName":"bluetooth.uart_write_buffer"},"bluetooth.uartReadBuffer":{"kind":-3,"retType":"Buffer","attributes":{"jsDoc":"Reads buffered UART data into a buffer"},"parameters":[],"pyQName":"bluetooth.uart_read_buffer"},"bluetooth.onUartDataReceived":{"kind":-3,"attributes":{"help":"bluetooth/on-uart-data-received","weight":18,"blockId":"bluetooth_on_data_received","block":"bluetooth|on data received %delimiters=serial_delimiter_conv","paramHelp":{"delimiters":"the characters to match received characters against."},"jsDoc":"Registers an event to be fired when one of the delimiter is matched.","_def":{"parts":[{"kind":"label","text":"bluetooth","style":[]},{"kind":"break"},{"kind":"label","text":"on data received ","style":[]},{"kind":"param","name":"delimiters","shadowBlockId":"serial_delimiter_conv","ref":false}],"parameters":[{"kind":"param","name":"delimiters","shadowBlockId":"serial_delimiter_conv","ref":false}]}},"parameters":[{"name":"delimiters","description":"the characters to match received characters against.","type":"string"},{"name":"body","type":"() => void","handlerParameters":[]}],"pyQName":"bluetooth.on_uart_data_received"},"bluetooth.onBluetoothConnected":{"kind":-3,"attributes":{"help":"bluetooth/on-bluetooth-connected","weight":20,"blockId":"bluetooth_on_connected","block":"on bluetooth connected","blockGap":"8","parts":"bluetooth","paramHelp":{"body":"Code to run when a Bluetooth connection is established"},"jsDoc":"Register code to run when the micro:bit is connected to over Bluetooth","_def":{"parts":[{"kind":"label","text":"on bluetooth connected","style":[]}],"parameters":[]}},"parameters":[{"name":"body","description":"Code to run when a Bluetooth connection is established","type":"() => void","handlerParameters":[]}],"pyQName":"bluetooth.on_bluetooth_connected"},"bluetooth.onBluetoothDisconnected":{"kind":-3,"attributes":{"help":"bluetooth/on-bluetooth-disconnected","weight":19,"blockId":"bluetooth_on_disconnected","block":"on bluetooth disconnected","parts":"bluetooth","paramHelp":{"body":"Code to run when a Bluetooth connection is lost"},"jsDoc":"Register code to run when a bluetooth connection to the micro:bit is lost","_def":{"parts":[{"kind":"label","text":"on bluetooth disconnected","style":[]}],"parameters":[]}},"parameters":[{"name":"body","description":"Code to run when a Bluetooth connection is lost","type":"() => void","handlerParameters":[]}],"pyQName":"bluetooth.on_bluetooth_disconnected"},"bluetooth.advertiseUrl":{"kind":-3,"attributes":{"paramDefl":{"url":"https://makecode.com","power":"7"},"blockId":"eddystone_advertise_url","block":"bluetooth advertise url %url|with power %power|connectable %connectable","parts":"bluetooth","weight":11,"blockGap":"8","help":"bluetooth/advertise-url","blockExternalInputs":"1","hidden":"1","deprecated":"1","inlineInputMode":"external","paramHelp":{"url":"the url to transmit. Must be no longer than the supported eddystone url length, eg: \"https://makecode.com\"","power":"power level between 0 and 7, eg: 7","connectable":"true to keep bluetooth connectable for other services, false otherwise."},"jsDoc":"Advertise an Eddystone URL","_def":{"parts":[{"kind":"label","text":"bluetooth advertise url ","style":[]},{"kind":"param","name":"url","ref":false},{"kind":"break"},{"kind":"label","text":"with power ","style":[]},{"kind":"param","name":"power","ref":false},{"kind":"break"},{"kind":"label","text":"connectable ","style":[]},{"kind":"param","name":"connectable","ref":false}],"parameters":[{"kind":"param","name":"url","ref":false},{"kind":"param","name":"power","ref":false},{"kind":"param","name":"connectable","ref":false}]}},"parameters":[{"name":"url","description":"the url to transmit. Must be no longer than the supported eddystone url length, eg: \"https://makecode.com\"","type":"string","default":"https://makecode.com"},{"name":"power","description":"power level between 0 and 7, eg: 7","default":"7"},{"name":"connectable","description":"true to keep bluetooth connectable for other services, false otherwise.","type":"boolean"}],"pyQName":"bluetooth.advertise_url"},"bluetooth.advertiseUidBuffer":{"kind":-3,"attributes":{"paramDefl":{"power":"7"},"parts":"bluetooth","weight":12,"advanced":true,"deprecated":"1","paramHelp":{"nsAndInstance":"16 bytes buffer of namespace (bytes 0-9) and instance (bytes 10-15)","power":"power level between 0 and 7, eg: 7","connectable":"true to keep bluetooth connectable for other services, false otherwise."},"jsDoc":"Advertise an Eddystone UID"},"parameters":[{"name":"nsAndInstance","description":"16 bytes buffer of namespace (bytes 0-9) and instance (bytes 10-15)","type":"Buffer"},{"name":"power","description":"power level between 0 and 7, eg: 7","default":"7"},{"name":"connectable","description":"true to keep bluetooth connectable for other services, false otherwise.","type":"boolean"}],"pyQName":"bluetooth.advertise_uid_buffer"},"bluetooth.setTransmitPower":{"kind":-3,"attributes":{"paramDefl":{"power":"7."},"parts":"bluetooth","weight":5,"help":"bluetooth/set-transmit-power","advanced":true,"blockId":"bluetooth_settransmitpower","block":"bluetooth set transmit power %power","paramHelp":{"power":"power level between 0 (minimal) and 7 (maximum), eg: 7."},"jsDoc":"Sets the bluetooth transmit power between 0 (minimal) and 7 (maximum).","_def":{"parts":[{"kind":"label","text":"bluetooth set transmit power ","style":[]},{"kind":"param","name":"power","ref":false}],"parameters":[{"kind":"param","name":"power","ref":false}]}},"parameters":[{"name":"power","description":"power level between 0 (minimal) and 7 (maximum), eg: 7.","default":"7."}],"pyQName":"bluetooth.set_transmit_power"},"bluetooth.stopAdvertising":{"kind":-3,"attributes":{"blockId":"eddystone_stop_advertising","block":"bluetooth stop advertising","parts":"bluetooth","weight":10,"help":"bluetooth/stop-advertising","advanced":true,"hidden":"1","deprecated":"1","jsDoc":"Stops advertising Eddystone end points","_def":{"parts":[{"kind":"label","text":"bluetooth stop advertising","style":[]}],"parameters":[]}},"parameters":[],"pyQName":"bluetooth.stop_advertising"},"bluetooth.NEW_LINE":{"kind":4,"retType":"string"},"bluetooth.__log":{"kind":-3,"attributes":{"jsDoc":"Internal use"},"parameters":[{"name":"priority"},{"name":"msg","type":"string"}]},"bluetooth.uartWriteString":{"kind":-3,"attributes":{"help":"bluetooth/uart-write-string","weight":80,"blockId":"bluetooth_uart_write","block":"bluetooth uart|write string %data","blockGap":"8","parts":"bluetooth","advanced":true,"jsDoc":"Writes to the Bluetooth UART service buffer. From there the data is transmitted over Bluetooth to a connected device.","_def":{"parts":[{"kind":"label","text":"bluetooth uart","style":[]},{"kind":"break"},{"kind":"label","text":"write string ","style":[]},{"kind":"param","name":"data","ref":false}],"parameters":[{"kind":"param","name":"data","ref":false}]}},"parameters":[{"name":"data","type":"string"}],"pyQName":"bluetooth.uart_write_string"},"bluetooth.uartWriteLine":{"kind":-3,"attributes":{"help":"bluetooth/uart-write-line","weight":79,"blockId":"bluetooth_uart_line","block":"bluetooth uart|write line %data","blockGap":"8","parts":"bluetooth","advanced":true,"jsDoc":"Writes to the Bluetooth UART service buffer. From there the data is transmitted over Bluetooth to a connected device.","_def":{"parts":[{"kind":"label","text":"bluetooth uart","style":[]},{"kind":"break"},{"kind":"label","text":"write line ","style":[]},{"kind":"param","name":"data","ref":false}],"parameters":[{"kind":"param","name":"data","ref":false}]}},"parameters":[{"name":"data","type":"string"}],"pyQName":"bluetooth.uart_write_line"},"bluetooth.uartWriteNumber":{"kind":-3,"attributes":{"help":"bluetooth/uart-write-number","weight":89,"blockGap":"8","advanced":true,"blockId":"bluetooth_uart_writenumber","block":"bluetooth uart|write number %value","jsDoc":"Prints a numeric value to the serial","_def":{"parts":[{"kind":"label","text":"bluetooth uart","style":[]},{"kind":"break"},{"kind":"label","text":"write number ","style":[]},{"kind":"param","name":"value","ref":false}],"parameters":[{"kind":"param","name":"value","ref":false}]}},"parameters":[{"name":"value"}],"pyQName":"bluetooth.uart_write_number"},"bluetooth.uartWriteValue":{"kind":-3,"attributes":{"paramDefl":{"name":"x"},"weight":78,"help":"bluetooth/uart-write-value","advanced":true,"blockId":"bluetooth_uart_writevalue","block":"bluetooth uart|write value %name|= %value","paramHelp":{"name":"name of the value stream, eg: x","value":"to write"},"jsDoc":"Writes a ``name: value`` pair line to the serial.","_def":{"parts":[{"kind":"label","text":"bluetooth uart","style":[]},{"kind":"break"},{"kind":"label","text":"write value ","style":[]},{"kind":"param","name":"name","ref":false},{"kind":"break"},{"kind":"label","text":"= ","style":[]},{"kind":"param","name":"value","ref":false}],"parameters":[{"kind":"param","name":"name","ref":false},{"kind":"param","name":"value","ref":false}]}},"parameters":[{"name":"name","description":"name of the value stream, eg: x","type":"string","default":"x"},{"name":"value","description":"to write"}],"pyQName":"bluetooth.uart_write_value"},"bluetooth.uartReadUntil":{"kind":-3,"retType":"string","attributes":{"help":"bluetooth/uart-read-until","weight":75,"blockId":"bluetooth_uart_read","block":"bluetooth uart|read until %del=serial_delimiter_conv","parts":"bluetooth","advanced":true,"jsDoc":"Reads from the Bluetooth UART service buffer, returning its contents when the specified delimiter character is encountered.","_def":{"parts":[{"kind":"label","text":"bluetooth uart","style":[]},{"kind":"break"},{"kind":"label","text":"read until ","style":[]},{"kind":"param","name":"del","shadowBlockId":"serial_delimiter_conv","ref":false}],"parameters":[{"kind":"param","name":"del","shadowBlockId":"serial_delimiter_conv","ref":false}]}},"parameters":[{"name":"del","type":"string"}],"pyQName":"bluetooth.uart_read_until"},"bluetooth.advertiseUid":{"kind":-3,"attributes":{"paramDefl":{"power":"7"},"blockId":"eddystone_advertise_uid","block":"bluetooth advertise UID|namespace (bytes 6-9)%ns|instance (bytes 2-6)%instance|with power %power|connectable %connectable","parts":"bluetooth","weight":12,"blockGap":"8","help":"bluetooth/advertise-uid","blockExternalInputs":"1","hidden":"1","deprecated":"1","inlineInputMode":"external","paramHelp":{"ns":"4 last bytes of the namespace uid","instance":"4 last bytes of the instance uid","power":"power level between 0 and 7, eg: 7","connectable":"true to keep bluetooth connectable for other services, false otherwise."},"jsDoc":"Advertise an Eddystone UID","_def":{"parts":[{"kind":"label","text":"bluetooth advertise UID","style":[]},{"kind":"break"},{"kind":"label","text":"namespace (bytes 6-9)","style":[]},{"kind":"param","name":"ns","ref":false},{"kind":"break"},{"kind":"label","text":"instance (bytes 2-6)","style":[]},{"kind":"param","name":"instance","ref":false},{"kind":"break"},{"kind":"label","text":"with power ","style":[]},{"kind":"param","name":"power","ref":false},{"kind":"break"},{"kind":"label","text":"connectable ","style":[]},{"kind":"param","name":"connectable","ref":false}],"parameters":[{"kind":"param","name":"ns","ref":false},{"kind":"param","name":"instance","ref":false},{"kind":"param","name":"power","ref":false},{"kind":"param","name":"connectable","ref":false}]}},"parameters":[{"name":"ns","description":"4 last bytes of the namespace uid"},{"name":"instance","description":"4 last bytes of the instance uid"},{"name":"power","description":"power level between 0 and 7, eg: 7","default":"7"},{"name":"connectable","description":"true to keep bluetooth connectable for other services, false otherwise.","type":"boolean"}],"pyQName":"bluetooth.advertise_uid"}}},"sha":"1f86e2b2c8373aa52df7f5875a5c0aa3ac7126078e0571820dfd525ed9f475c4"},"libs/servo":{"apis":{"byQName":{"servos":{"kind":5,"retType":"","attributes":{"color":"#03AA74","weight":88,"icon":"","blockGap":"8","groups":["Positional","Continuous","Configuration"],"jsDoc":"Control micro servos"}},"servos.Servo":{"kind":8,"retType":"servos.Servo","attributes":{"fixedInstances":"true"},"extendsTypes":["servos.Servo"]},"servos.Servo.__constructor":{"kind":-3,"parameters":[],"isInstance":true},"servos.Servo.setAngle":{"kind":-1,"attributes":{"paramDefl":{"degrees":"90"},"weight":100,"help":"servos/set-angle","blockId":"servoservosetangle","block":"set %servo angle to %degrees=protractorPicker °","explicitDefaults":["degrees"],"paramFieldEditor":{"servo":"gridpicker"},"paramFieldEditorOptions":{"servo":{"width":"220","columns":"2"}},"blockGap":"8","parts":"microservo","trackArgs":[0],"group":"Positional","jsDoc":"Set the servo angle","_def":{"parts":[{"kind":"label","text":"set ","style":[]},{"kind":"param","name":"servo","ref":false},{"kind":"label","text":" angle to ","style":[]},{"kind":"param","name":"degrees","shadowBlockId":"protractorPicker","ref":false},{"kind":"label","text":" °","style":[]}],"parameters":[{"kind":"param","name":"servo","ref":false},{"kind":"param","name":"degrees","shadowBlockId":"protractorPicker","ref":false}]}},"parameters":[{"name":"degrees","initializer":"90","default":"90"}],"isInstance":true,"pyQName":"servos.Servo.set_angle"},"servos.Servo.angle":{"kind":-2,"retType":"number","isInstance":true,"isReadOnly":true},"servos.Servo.run":{"kind":-1,"attributes":{"weight":99,"help":"servos/run","blockId":"servoservorun","block":"continuous %servo run at %speed=speedPicker \\%","paramFieldEditor":{"servo":"gridpicker"},"paramFieldEditorOptions":{"servo":{"width":"220","columns":"2"}},"parts":"microservo","trackArgs":[0],"group":"Continuous","blockGap":"8","paramHelp":{"speed":"the throttle of the motor from -100% to 100%"},"jsDoc":"Set the throttle on a continuous servo","_def":{"parts":[{"kind":"label","text":"continuous ","style":[]},{"kind":"param","name":"servo","ref":false},{"kind":"label","text":" run at ","style":[]},{"kind":"param","name":"speed","shadowBlockId":"speedPicker","ref":false},{"kind":"label","text":" %","style":[]}],"parameters":[{"kind":"param","name":"servo","ref":false},{"kind":"param","name":"speed","shadowBlockId":"speedPicker","ref":false}]}},"parameters":[{"name":"speed","description":"the throttle of the motor from -100% to 100%"}],"isInstance":true},"servos.Servo.setPulse":{"kind":-1,"attributes":{"paramDefl":{"micros":"1500"},"weight":10,"help":"servos/set-pulse","blockId":"servoservosetpulse","block":"set %servo pulse to %micros μs","paramMin":{"micros":"500"},"paramMax":{"micros":"2500"},"explicitDefaults":["micros"],"paramFieldEditor":{"servo":"gridpicker"},"paramFieldEditorOptions":{"servo":{"width":"220","columns":"2"}},"parts":"microservo","trackArgs":[0],"group":"Configuration","blockGap":"8","paramHelp":{"micros":"the width of the pulse in microseconds"},"jsDoc":"Set the pulse width to the servo in microseconds","_def":{"parts":[{"kind":"label","text":"set ","style":[]},{"kind":"param","name":"servo","ref":false},{"kind":"label","text":" pulse to ","style":[]},{"kind":"param","name":"micros","ref":false},{"kind":"label","text":" μs","style":[]}],"parameters":[{"kind":"param","name":"servo","ref":false},{"kind":"param","name":"micros","ref":false}]}},"parameters":[{"name":"micros","description":"the width of the pulse in microseconds","initializer":"1500","default":"1500","options":{"min":{"value":"500"},"max":{"value":"2500"}}}],"isInstance":true,"pyQName":"servos.Servo.set_pulse"},"servos.Servo.stop":{"kind":-1,"attributes":{"weight":10,"help":"servos/stop","blockId":"servoservostop","block":"stop %servo","paramFieldEditor":{"servo":"gridpicker"},"paramFieldEditorOptions":{"servo":{"width":"220","columns":"2"}},"parts":"microservo","trackArgs":[0],"group":"Continuous","blockGap":"8","jsDoc":"Stop sending commands to the servo so that its rotation will stop at the current position.","_def":{"parts":[{"kind":"label","text":"stop ","style":[]},{"kind":"param","name":"servo","ref":false}],"parameters":[{"kind":"param","name":"servo","ref":false}]}},"parameters":[],"isInstance":true},"servos.Servo.minAngle":{"kind":-2,"retType":"number","attributes":{"jsDoc":"Gets the minimum angle for the servo"},"isInstance":true,"isReadOnly":true,"pyQName":"servos.Servo.min_angle"},"servos.Servo.maxAngle":{"kind":-2,"retType":"number","attributes":{"jsDoc":"Gets the maximum angle for the servo"},"isInstance":true,"isReadOnly":true,"pyQName":"servos.Servo.max_angle"},"servos.Servo.setRange":{"kind":-1,"attributes":{"paramDefl":{"maxAngle":"180"},"help":"servos/set-range","blockId":"servosetrange","block":"set %servo range from %minAngle to %maxAngle","paramMin":{"minAngle":"0","maxAngle":"90"},"paramMax":{"minAngle":"90","maxAngle":"180"},"explicitDefaults":["maxAngle"],"paramFieldEditor":{"servo":"gridpicker"},"paramFieldEditorOptions":{"servo":{"width":"220","columns":"2"}},"parts":"microservo","trackArgs":[0],"group":"Configuration","blockGap":"8","paramHelp":{"minAngle":"the minimum angle from 0 to 90","maxAngle":"the maximum angle from 90 to 180"},"jsDoc":"Set the possible rotation range angles for the servo between 0 and 180","_def":{"parts":[{"kind":"label","text":"set ","style":[]},{"kind":"param","name":"servo","ref":false},{"kind":"label","text":" range from ","style":[]},{"kind":"param","name":"minAngle","ref":false},{"kind":"label","text":" to ","style":[]},{"kind":"param","name":"maxAngle","ref":false}],"parameters":[{"kind":"param","name":"servo","ref":false},{"kind":"param","name":"minAngle","ref":false},{"kind":"param","name":"maxAngle","ref":false}]}},"parameters":[{"name":"minAngle","description":"the minimum angle from 0 to 90","options":{"min":{"value":"0"},"max":{"value":"90"}}},{"name":"maxAngle","description":"the maximum angle from 90 to 180","initializer":"180","default":"180","options":{"min":{"value":"90"},"max":{"value":"180"}}}],"isInstance":true,"pyQName":"servos.Servo.set_range"},"servos.Servo.setStopOnNeutral":{"kind":-1,"attributes":{"help":"servos/set-stop-on-neutral","blockId":"servostoponneutral","block":"set %servo stop on neutral %enabled","_shadowOverrides":{"enabled":"toggleOnOff"},"group":"Configuration","blockGap":"8","paramFieldEditor":{"servo":"gridpicker"},"paramFieldEditorOptions":{"servo":{"width":"220","columns":"2"}},"paramHelp":{"on":"true to enable this mode"},"jsDoc":"Set a servo stop mode so it will stop when the rotation angle is in the neutral position, 90 degrees.","_def":{"parts":[{"kind":"label","text":"set ","style":[]},{"kind":"param","name":"servo","ref":false},{"kind":"label","text":" stop on neutral ","style":[]},{"kind":"param","name":"enabled","shadowBlockId":"toggleOnOff","ref":false}],"parameters":[{"kind":"param","name":"servo","ref":false},{"kind":"param","name":"enabled","shadowBlockId":"toggleOnOff","ref":false}]}},"parameters":[{"name":"enabled","type":"boolean"}],"isInstance":true,"pyQName":"servos.Servo.set_stop_on_neutral"},"servos.PinServo":{"kind":8,"retType":"servos.PinServo","extendsTypes":["servos.PinServo","servos.Servo"]},"servos.PinServo.__constructor":{"kind":-3,"parameters":[{"name":"pin","type":"PwmOnlyPin"}],"isInstance":true},"servos.P0":{"kind":4,"retType":"servos.PinServo","attributes":{"block":"servo P0","fixedInstance":"true","whenUsed":"true","_def":{"parts":[{"kind":"label","text":"servo P0","style":[]}],"parameters":[]}}},"servos.P1":{"kind":4,"retType":"servos.PinServo","attributes":{"block":"servo P1","fixedInstance":"true","whenUsed":"true","_def":{"parts":[{"kind":"label","text":"servo P1","style":[]}],"parameters":[]}}},"servos.P2":{"kind":4,"retType":"servos.PinServo","attributes":{"block":"servo P2","fixedInstance":"true","whenUsed":"true","_def":{"parts":[{"kind":"label","text":"servo P2","style":[]}],"parameters":[]}}}}},"sha":"0894ebda461607fa368ec1545deb63de39afed19f25910a7e86e772e1ebb4287"},"libs/radio-broadcast":{"apis":{"byQName":{"radio":{"kind":5,"retType":"","attributes":{"color":"#E3008C","weight":96,"icon":"","groups":["Group","Broadcast","Send","Receive"],"jsDoc":"Communicate data using radio packets"}},"radio.off":{"kind":-3,"attributes":{"help":"radio/off","jsDoc":"Disables the radio for use as a multipoint sender/receiver.\nDisabling radio will help conserve battery power when it is not in use."},"parameters":[]},"radio.on":{"kind":-3,"attributes":{"help":"radio/on","jsDoc":"Initialises the radio for use as a multipoint sender/receiver\nOnly useful when the radio.off() is used beforehand."},"parameters":[]},"radio.raiseEvent":{"kind":-3,"attributes":{"blockId":"radioRaiseEvent","block":"radio raise event|from source %src=control_event_source_id|with value %value=control_event_value_id","blockExternalInputs":"1","advanced":true,"weight":1,"help":"radio/raise-event","inlineInputMode":"external","jsDoc":"Sends an event over radio to neigboring devices","_def":{"parts":[{"kind":"label","text":"radio raise event","style":[]},{"kind":"break"},{"kind":"label","text":"from source ","style":[]},{"kind":"param","name":"src","shadowBlockId":"control_event_source_id","ref":false},{"kind":"break"},{"kind":"label","text":"with value ","style":[]},{"kind":"param","name":"value","shadowBlockId":"control_event_value_id","ref":false}],"parameters":[{"kind":"param","name":"src","shadowBlockId":"control_event_source_id","ref":false},{"kind":"param","name":"value","shadowBlockId":"control_event_value_id","ref":false}]}},"parameters":[{"name":"src"},{"name":"value"}],"pyQName":"radio.raise_event"},"radio.readRawPacket":{"kind":-3,"retType":"Buffer","attributes":{"jsDoc":"Internal use only. Takes the next packet from the radio queue and returns its contents + RSSI in a Buffer.\n@returns NULL if no packet available"},"parameters":[],"pyQName":"radio.read_raw_packet"},"radio.sendRawPacket":{"kind":-3,"attributes":{"callingConvention":1,"async":"true","jsDoc":"Internal use only. Sends a raw packet through the radio (assumes RSSI appened to packet)"},"parameters":[{"name":"msg","type":"Buffer"}],"pyQName":"radio.send_raw_packet"},"radio.onDataReceived":{"kind":-3,"attributes":{"help":"radio/on-data-received","weight":0,"blockId":"radio_datagram_received_event","block":"radio on data received","blockGap":"8","deprecated":"true","blockHidden":true,"jsDoc":"Used internally by the library.","_def":{"parts":[{"kind":"label","text":"radio on data received","style":[]}],"parameters":[]}},"parameters":[{"name":"body","type":"() => void","handlerParameters":[]}],"pyQName":"radio.on_data_received"},"radio.setGroup":{"kind":-3,"attributes":{"paramDefl":{"id":"1"},"help":"radio/set-group","weight":100,"blockId":"radio_set_group","block":"radio set group %ID","paramMin":{"id":"0"},"paramMax":{"id":"255"},"group":"Group","paramHelp":{"id":"the group id between ``0`` and ``255``, eg: 1"},"jsDoc":"Sets the group id for radio communications. A micro:bit can only listen to one group ID at any time.","_def":{"parts":[{"kind":"label","text":"radio set group ","style":[]},{"kind":"param","name":"ID","ref":false}],"parameters":[{"kind":"param","name":"ID","ref":false}]}},"parameters":[{"name":"id","description":"the group id between ``0`` and ``255``, eg: 1","default":"1","options":{"min":{"value":"0"},"max":{"value":"255"}}}],"pyQName":"radio.set_group"},"radio.setTransmitPower":{"kind":-3,"attributes":{"paramDefl":{"power":"7"},"help":"radio/set-transmit-power","weight":9,"blockGap":"8","blockId":"radio_set_transmit_power","block":"radio set transmit power %power","paramMin":{"power":"0"},"paramMax":{"power":"7"},"advanced":true,"paramHelp":{"power":"a value in the range 0..7, where 0 is the lowest power and 7 is the highest. eg: 7"},"jsDoc":"Change the output power level of the transmitter to the given value.","_def":{"parts":[{"kind":"label","text":"radio set transmit power ","style":[]},{"kind":"param","name":"power","ref":false}],"parameters":[{"kind":"param","name":"power","ref":false}]}},"parameters":[{"name":"power","description":"a value in the range 0..7, where 0 is the lowest power and 7 is the highest. eg: 7","default":"7","options":{"min":{"value":"0"},"max":{"value":"7"}}}],"pyQName":"radio.set_transmit_power"},"radio.setFrequencyBand":{"kind":-3,"attributes":{"help":"radio/set-frequency-band","weight":8,"blockGap":"8","blockId":"radio_set_frequency_band","block":"radio set frequency band %band","paramMin":{"band":"0"},"paramMax":{"band":"83"},"advanced":true,"paramHelp":{"band":"a frequency band in the range 0 - 83. Each step is 1MHz wide, based at 2400MHz."},"jsDoc":"Change the transmission and reception band of the radio to the given channel","_def":{"parts":[{"kind":"label","text":"radio set frequency band ","style":[]},{"kind":"param","name":"band","ref":false}],"parameters":[{"kind":"param","name":"band","ref":false}]}},"parameters":[{"name":"band","description":"a frequency band in the range 0 - 83. Each step is 1MHz wide, based at 2400MHz.","options":{"min":{"value":"0"},"max":{"value":"83"}}}],"pyQName":"radio.set_frequency_band"},"RadioPacketProperty":{"kind":6,"retType":"RadioPacketProperty","extendsTypes":["RadioPacketProperty","Number"]},"RadioPacketProperty.SignalStrength":{"retType":"RadioPacketProperty.SignalStrength","attributes":{"blockIdentity":"radio._packetProperty","block":"signal strength","_def":{"parts":[{"kind":"label","text":"signal strength","style":[]}],"parameters":[]}},"extendsTypes":["RadioPacketProperty.SignalStrength","Number"],"pyQName":"RadioPacketProperty.SIGNAL_STRENGTH"},"RadioPacketProperty.Time":{"retType":"RadioPacketProperty.Time","attributes":{"blockIdentity":"radio._packetProperty","block":"time","_def":{"parts":[{"kind":"label","text":"time","style":[]}],"parameters":[]}},"extendsTypes":["RadioPacketProperty.Time","Number"],"pyQName":"RadioPacketProperty.TIME"},"RadioPacketProperty.SerialNumber":{"retType":"RadioPacketProperty.SerialNumber","attributes":{"block":"serial number","blockIdentity":"radio._packetProperty","_def":{"parts":[{"kind":"label","text":"serial number","style":[]}],"parameters":[]}},"extendsTypes":["RadioPacketProperty.SerialNumber","Number"],"pyQName":"RadioPacketProperty.SERIAL_NUMBER"},"radio.PACKET_TYPE_NUMBER":{"kind":4,"retType":"number"},"radio.PACKET_TYPE_VALUE":{"kind":4,"retType":"number"},"radio.PACKET_TYPE_STRING":{"kind":4,"retType":"number"},"radio.PACKET_TYPE_BUFFER":{"kind":4,"retType":"number"},"radio.PACKET_TYPE_DOUBLE":{"kind":4,"retType":"number"},"radio.PACKET_TYPE_DOUBLE_VALUE":{"kind":4,"retType":"number"},"radio.lastPacket":{"kind":4,"retType":"radio.RadioPacket","pyQName":"radio.last_packet"},"radio.onReceivedNumber":{"kind":-3,"attributes":{"help":"radio/on-received-number","blockId":"radio_on_number_drag","block":"on radio received","blockGap":"16","useLoc":"radio.onDataPacketReceived","draggableParameters":"reporter","group":"Receive","weight":20,"jsDoc":"Registers code to run when the radio receives a number.","_def":{"parts":[{"kind":"label","text":"on radio received","style":[]}],"parameters":[]}},"parameters":[{"name":"cb","type":"(receivedNumber: number) => void","handlerParameters":[{"name":"receivedNumber","type":"number"}]}],"pyQName":"radio.on_received_number"},"radio.onReceivedValue":{"kind":-3,"attributes":{"help":"radio/on-received-value","blockId":"radio_on_value_drag","block":"on radio received","blockGap":"16","useLoc":"radio.onDataPacketReceived","draggableParameters":"reporter","group":"Receive","weight":19,"jsDoc":"Registers code to run when the radio receives a key value pair.","_def":{"parts":[{"kind":"label","text":"on radio received","style":[]}],"parameters":[]}},"parameters":[{"name":"cb","type":"(name: string, value: number) => void","handlerParameters":[{"name":"name","type":"string"},{"name":"value","type":"number"}]}],"pyQName":"radio.on_received_value"},"radio.onReceivedString":{"kind":-3,"attributes":{"help":"radio/on-received-string","blockId":"radio_on_string_drag","block":"on radio received","blockGap":"16","useLoc":"radio.onDataPacketReceived","draggableParameters":"reporter","group":"Receive","weight":18,"jsDoc":"Registers code to run when the radio receives a string.","_def":{"parts":[{"kind":"label","text":"on radio received","style":[]}],"parameters":[]}},"parameters":[{"name":"cb","type":"(receivedString: string) => void","handlerParameters":[{"name":"receivedString","type":"string"}]}],"pyQName":"radio.on_received_string"},"radio.onReceivedBuffer":{"kind":-3,"attributes":{"help":"radio/on-received-buffer","blockHidden":true,"blockId":"radio_on_buffer_drag","block":"on radio received","blockGap":"16","useLoc":"radio.onDataPacketReceived","draggableParameters":"reporter","jsDoc":"Registers code to run when the radio receives a buffer.","_def":{"parts":[{"kind":"label","text":"on radio received","style":[]}],"parameters":[]}},"parameters":[{"name":"cb","type":"(receivedBuffer: Buffer) => void","handlerParameters":[{"name":"receivedBuffer","type":"Buffer"}]}],"pyQName":"radio.on_received_buffer"},"radio.receivedPacket":{"kind":-3,"retType":"number","attributes":{"help":"radio/received-packet","blockGap":"16","blockId":"radio_received_packet","block":"received packet %type=radio_packet_property","group":"Receive","weight":16,"paramHelp":{"type":"the type of property to retrieve from the last packet"},"jsDoc":"Returns properties of the last radio packet received.","_def":{"parts":[{"kind":"label","text":"received packet ","style":[]},{"kind":"param","name":"type","shadowBlockId":"radio_packet_property","ref":false}],"parameters":[{"kind":"param","name":"type","shadowBlockId":"radio_packet_property","ref":false}]}},"parameters":[{"name":"type","description":"the type of property to retrieve from the last packet"}],"pyQName":"radio.received_packet"},"radio._packetProperty":{"kind":-3,"retType":"number","attributes":{"paramDefl":{"type":"PacketProperty.time"},"blockId":"radio_packet_property","block":"%note","shim":"TD_ID","blockHidden":true,"paramHelp":{"type":"the packet property type, eg: PacketProperty.time"},"jsDoc":"Gets a packet property.","_def":{"parts":[{"kind":"param","name":"note","ref":false}],"parameters":[{"kind":"param","name":"note","ref":false}]}},"parameters":[{"name":"type","description":"the packet property type, eg: PacketProperty.time","type":"RadioPacketProperty","default":"PacketProperty.time","isEnum":true}],"pyQName":"radio._packet_property"},"radio.RadioPacket":{"kind":8,"retType":"radio.RadioPacket","extendsTypes":[]},"radio.RadioPacket.getPacket":{"kind":-1,"retType":"radio.RadioPacket","parameters":[{"name":"data","type":"Buffer"}],"pyQName":"radio.RadioPacket.get_packet"},"radio.RadioPacket.mkPacket":{"kind":-1,"retType":"radio.RadioPacket","parameters":[{"name":"packetType"}],"pyQName":"radio.RadioPacket.mk_packet"},"radio.RadioPacket.signal":{"kind":-2,"retType":"number","isInstance":true,"isReadOnly":true},"radio.RadioPacket.packetType":{"kind":-2,"retType":"number","isInstance":true,"isReadOnly":true,"pyQName":"radio.RadioPacket.packet_type"},"radio.RadioPacket.time":{"kind":-2,"retType":"number","isInstance":true,"isReadOnly":true},"radio.RadioPacket.time@set":{"kind":-2,"retType":"number","isInstance":true},"radio.RadioPacket.serial":{"kind":-2,"retType":"number","isInstance":true,"isReadOnly":true},"radio.RadioPacket.serial@set":{"kind":-2,"retType":"number","isInstance":true},"radio.RadioPacket.stringPayload":{"kind":-2,"retType":"string","isInstance":true,"isReadOnly":true,"pyQName":"radio.RadioPacket.string_payload"},"radio.RadioPacket.stringPayload@set":{"kind":-2,"retType":"string","isInstance":true,"pyQName":"radio.RadioPacket.string_payload@set"},"radio.RadioPacket.numberPayload":{"kind":-2,"retType":"number","isInstance":true,"isReadOnly":true,"pyQName":"radio.RadioPacket.number_payload"},"radio.RadioPacket.numberPayload@set":{"kind":-2,"retType":"number","isInstance":true,"pyQName":"radio.RadioPacket.number_payload@set"},"radio.RadioPacket.bufferPayload":{"kind":-2,"retType":"Buffer","isInstance":true,"isReadOnly":true,"pyQName":"radio.RadioPacket.buffer_payload"},"radio.RadioPacket.bufferPayload@set":{"kind":-2,"retType":"Buffer","isInstance":true,"pyQName":"radio.RadioPacket.buffer_payload@set"},"radio.RadioPacket.hasString":{"kind":-1,"retType":"boolean","parameters":[],"isInstance":true,"pyQName":"radio.RadioPacket.has_string"},"radio.RadioPacket.hasNumber":{"kind":-1,"retType":"boolean","parameters":[],"isInstance":true,"pyQName":"radio.RadioPacket.has_number"},"radio.sendNumber":{"kind":-3,"attributes":{"help":"radio/send-number","weight":60,"blockId":"radio_datagram_send","block":"radio send number %value","blockGap":"8","group":"Send","jsDoc":"Broadcasts a number over radio to any connected micro:bit in the group.","_def":{"parts":[{"kind":"label","text":"radio send number ","style":[]},{"kind":"param","name":"value","ref":false}],"parameters":[{"kind":"param","name":"value","ref":false}]}},"parameters":[{"name":"value"}],"pyQName":"radio.send_number"},"radio.sendValue":{"kind":-3,"attributes":{"paramDefl":{"name":"name"},"help":"radio/send-value","weight":59,"blockId":"radio_datagram_send_value","block":"radio send|value %name|= %value","blockGap":"8","group":"Send","paramHelp":{"name":"the field name (max 8 characters), eg: \"name\"","value":"the numeric value"},"jsDoc":"Broadcasts a name / value pair along with the device serial number\nand running time to any connected micro:bit in the group. The name can\ninclude no more than 8 characters.","_def":{"parts":[{"kind":"label","text":"radio send","style":[]},{"kind":"break"},{"kind":"label","text":"value ","style":[]},{"kind":"param","name":"name","ref":false},{"kind":"break"},{"kind":"label","text":"= ","style":[]},{"kind":"param","name":"value","ref":false}],"parameters":[{"kind":"param","name":"name","ref":false},{"kind":"param","name":"value","ref":false}]}},"parameters":[{"name":"name","description":"the field name (max 8 characters), eg: \"name\"","type":"string","default":"name"},{"name":"value","description":"the numeric value"}],"pyQName":"radio.send_value"},"radio.sendString":{"kind":-3,"attributes":{"help":"radio/send-string","weight":58,"blockId":"radio_datagram_send_string","block":"radio send string %msg","paramShadowOptions":{"msg":{"toString":"true"}},"group":"Send","jsDoc":"Broadcasts a string along with the device serial number\nand running time to any connected micro:bit in the group.","_def":{"parts":[{"kind":"label","text":"radio send string ","style":[]},{"kind":"param","name":"msg","ref":false}],"parameters":[{"kind":"param","name":"msg","ref":false}]}},"parameters":[{"name":"value","type":"string","options":{"fieldEditorOptions":{"value":{"toString":"true"}}}}],"pyQName":"radio.send_string"},"radio.sendBuffer":{"kind":-3,"attributes":{"help":"radio/send-buffer","weight":57,"advanced":true,"jsDoc":"Broadcasts a buffer (up to 19 bytes long) along with the device serial number\nand running time to any connected micro:bit in the group."},"parameters":[{"name":"msg","type":"Buffer"}],"pyQName":"radio.send_buffer"},"radio.setTransmitSerialNumber":{"kind":-3,"attributes":{"paramDefl":{"transmit":"true"},"help":"radio/set-transmit-serial-number","weight":8,"blockGap":"8","blockId":"radio_set_transmit_serial_number","block":"radio set transmit serial number %transmit","advanced":true,"paramHelp":{"transmit":"value indicating if the serial number is transmitted, eg: true"},"jsDoc":"Set the radio to transmit the serial number in each message.","_def":{"parts":[{"kind":"label","text":"radio set transmit serial number ","style":[]},{"kind":"param","name":"transmit","ref":false}],"parameters":[{"kind":"param","name":"transmit","ref":false}]}},"parameters":[{"name":"transmit","description":"value indicating if the serial number is transmitted, eg: true","type":"boolean","default":"true"}],"pyQName":"radio.set_transmit_serial_number"},"radio.Packet":{"kind":8,"retType":"radio.Packet","extendsTypes":[]},"radio.Packet.receivedNumber":{"kind":2,"retType":"number","attributes":{"jsDoc":"The number payload if a number was sent in this packet (via ``sendNumber()`` or ``sendValue()``)\nor 0 if this packet did not contain a number."},"isInstance":true,"pyQName":"radio.Packet.received_number"},"radio.Packet.receivedString":{"kind":2,"retType":"string","attributes":{"jsDoc":"The string payload if a string was sent in this packet (via ``sendString()`` or ``sendValue()``)\nor the empty string if this packet did not contain a string."},"isInstance":true,"pyQName":"radio.Packet.received_string"},"radio.Packet.receivedBuffer":{"kind":2,"retType":"Buffer","attributes":{"jsDoc":"The buffer payload if a buffer was sent in this packet\nor the empty buffer"},"isInstance":true,"pyQName":"radio.Packet.received_buffer"},"radio.Packet.time":{"kind":2,"retType":"number","attributes":{"jsDoc":"The system time of the sender of the packet at the time the packet was sent."},"isInstance":true},"radio.Packet.serial":{"kind":2,"retType":"number","attributes":{"jsDoc":"The serial number of the sender of the packet or 0 if the sender did not sent their serial number."},"isInstance":true},"radio.Packet.signal":{"kind":2,"retType":"number","attributes":{"jsDoc":"The received signal strength indicator (RSSI) of the packet."},"isInstance":true},"radio.onDataPacketReceived":{"kind":-3,"attributes":{"help":"radio/on-data-packet-received","blockHandlerKey":"radioreceived","deprecated":"true","mutate":"objectdestructuring","mutateText":"Packet","mutateDefaults":"receivedNumber;receivedString:name,receivedNumber:value;receivedString","blockId":"radio_on_packet","block":"on radio received","blockGap":"8","jsDoc":"Deprecated. Use onDataReceived() instead\nRegisters code to run when the radio receives a packet. Also takes the\nreceived packet from the radio queue.","_def":{"parts":[{"kind":"label","text":"on radio received","style":[]}],"parameters":[]}},"parameters":[{"name":"cb","type":"(packet: radio.Packet) => void"}],"pyQName":"radio.on_data_packet_received"},"radio.onReceivedNumberDeprecated":{"kind":-3,"attributes":{"help":"radio/on-received-number","blockHandlerKey":"radioreceived","blockId":"radio_on_number","block":"on radio received","blockGap":"16","useLoc":"radio.onDataPacketReceived","deprecated":"1","jsDoc":"Registers code to run when the radio receives a number. Deprecated, use\nonReceivedNumber instead.","_def":{"parts":[{"kind":"label","text":"on radio received","style":[]}],"parameters":[]}},"parameters":[{"name":"cb","type":"(receivedNumber: number) => void","handlerParameters":[{"name":"receivedNumber","type":"number"}]}],"pyQName":"radio.on_received_number_deprecated"},"radio.onReceivedValueDeprecated":{"kind":-3,"attributes":{"help":"radio/on-received-value","blockHandlerKey":"radioreceived","blockId":"radio_on_value","block":"on radio received","blockGap":"16","useLoc":"radio.onDataPacketReceived","deprecated":"1","jsDoc":"Registers code to run when the radio receives a key value pair. Deprecated, use\nonReceivedValue instead.","_def":{"parts":[{"kind":"label","text":"on radio received","style":[]}],"parameters":[]}},"parameters":[{"name":"cb","type":"(name: string, value: number) => void","handlerParameters":[{"name":"name","type":"string"},{"name":"value","type":"number"}]}],"pyQName":"radio.on_received_value_deprecated"},"radio.onReceivedStringDeprecated":{"kind":-3,"attributes":{"help":"radio/on-received-string","blockHandlerKey":"radioreceived","blockId":"radio_on_string","block":"on radio received","blockGap":"16","useLoc":"radio.onDataPacketReceived","deprecated":"1","jsDoc":"Registers code to run when the radio receives a string. Deprecated, use\nonReceivedString instead.","_def":{"parts":[{"kind":"label","text":"on radio received","style":[]}],"parameters":[]}},"parameters":[{"name":"cb","type":"(receivedString: string) => void","handlerParameters":[{"name":"receivedString","type":"string"}]}],"pyQName":"radio.on_received_string_deprecated"},"radio.onReceivedBufferDeprecated":{"kind":-3,"attributes":{"help":"radio/on-received-buffer","blockHandlerKey":"radioreceived","blockHidden":true,"blockId":"radio_on_buffer","block":"on radio received","blockGap":"16","useLoc":"radio.onDataPacketReceived","deprecated":"1","jsDoc":"Registers code to run when the radio receives a buffer. Deprecated, use\nonReceivedBuffer instead.","_def":{"parts":[{"kind":"label","text":"on radio received","style":[]}],"parameters":[]}},"parameters":[{"name":"cb","type":"(receivedBuffer: Buffer) => void","handlerParameters":[{"name":"receivedBuffer","type":"Buffer"}]}],"pyQName":"radio.on_received_buffer_deprecated"},"radio.receivedNumber":{"kind":-3,"retType":"number","attributes":{"help":"radio/received-number","deprecated":"1","jsDoc":"Returns the number payload from the last packet taken from the radio queue\n(via ``receiveNumber``, ``receiveString``, etc) or 0 if that packet did not\ncontain a number."},"parameters":[],"pyQName":"radio.received_number"},"radio.receivedSerial":{"kind":-3,"retType":"number","attributes":{"help":"radio/received-serial","deprecated":"1","jsDoc":"Returns the serial number of the sender micro:bit from the last packet taken\nfrom the radio queue (via ``receiveNumber``, ``receiveString``, etc) or 0 if\nthat packet did not send a serial number."},"parameters":[],"pyQName":"radio.received_serial"},"radio.receivedString":{"kind":-3,"retType":"string","attributes":{"help":"radio/received-string","deprecated":"1","jsDoc":"Returns the string payload from the last packet taken from the radio queue\n(via ``receiveNumber``, ``receiveString``, etc) or the empty string if that\npacket did not contain a string."},"parameters":[],"pyQName":"radio.received_string"},"radio.receivedBuffer":{"kind":-3,"retType":"Buffer","attributes":{"help":"radio/received-buffer","deprecated":"1","jsDoc":"Returns the buffer payload from the last packet taken from the radio queue\n(via ``receiveNumber``, ``receiveString``, etc) or the empty string if that\npacket did not contain a string."},"parameters":[],"pyQName":"radio.received_buffer"},"radio.receivedTime":{"kind":-3,"retType":"number","attributes":{"help":"radio/received-time","deprecated":"1","jsDoc":"Returns the system time of the sender micro:bit at the moment when it sent the\nlast packet taken from the radio queue (via ``receiveNumber``,\n``receiveString``, etc)."},"parameters":[],"pyQName":"radio.received_time"},"radio.receiveNumber":{"kind":-3,"retType":"number","attributes":{"help":"radio/receive-number","weight":46,"blockId":"radio_datagram_receive","block":"radio receive number","blockGap":"8","deprecated":"true","jsDoc":"Reads the next packet from the radio queue and returns the packet's number\npayload or 0 if the packet did not contain a number.","_def":{"parts":[{"kind":"label","text":"radio receive number","style":[]}],"parameters":[]}},"parameters":[],"pyQName":"radio.receive_number"},"radio.receiveString":{"kind":-3,"retType":"string","attributes":{"blockId":"radio_datagram_receive_string","block":"radio receive string","blockGap":"8","weight":44,"help":"radio/receive-string","deprecated":"true","jsDoc":"Reads the next packet from the radio queue and returns the packet's string\npayload or the empty string if the packet did not contain a string.","_def":{"parts":[{"kind":"label","text":"radio receive string","style":[]}],"parameters":[]}},"parameters":[],"pyQName":"radio.receive_string"},"radio.receivedSignalStrength":{"kind":-3,"retType":"number","attributes":{"help":"radio/received-signal-strength","weight":40,"blockId":"radio_datagram_rssi","block":"radio received signal strength","deprecated":"true","blockHidden":true,"jsDoc":"Gets the received signal strength indicator (RSSI) from the last packet taken\nfrom the radio queue (via ``receiveNumber``, ``receiveString``, etc). Not supported in simulator.","_def":{"parts":[{"kind":"label","text":"radio received signal strength","style":[]}],"parameters":[]}},"parameters":[],"pyQName":"radio.received_signal_strength"},"radio.writeValueToSerial":{"kind":-3,"attributes":{"help":"radio/write-value-to-serial","weight":3,"blockId":"radio_write_value_serial","block":"radio write value to serial","deprecated":"true","jsDoc":"Reads the next packet from the radio queue and and writes it to serial\nas JSON.","_def":{"parts":[{"kind":"label","text":"radio write value to serial","style":[]}],"parameters":[]}},"parameters":[],"pyQName":"radio.write_value_to_serial"},"radio.writeReceivedPacketToSerial":{"kind":-3,"attributes":{"help":"radio/write-received-packet-to-serial","weight":3,"blockId":"radio_write_packet_serial","block":"radio write received packet to serial","advanced":true,"deprecated":"true","jsDoc":"Writes the last received packet to serial as JSON. This should be called\nwithin an ``onDataPacketReceived`` callback.","_def":{"parts":[{"kind":"label","text":"radio write received packet to serial","style":[]}],"parameters":[]}},"parameters":[],"pyQName":"radio.write_received_packet_to_serial"},"radio.__message":{"kind":-3,"retType":"number","attributes":{"blockHidden":true,"shim":"ENUM_GET","blockId":"radioMessageCode","block":"$msg","enumInitialMembers":["message1"],"enumName":"RadioMessage","enumMemberName":"msg","enumPromptHint":"e.g. Start, Stop, Jump...","enumIsHash":true,"jsDoc":"Gets the message code","_def":{"parts":[{"kind":"param","name":"msg","ref":true}],"parameters":[{"kind":"param","name":"msg","ref":true}]}},"parameters":[{"name":"msg"}]},"radio.sendMessage":{"kind":-3,"attributes":{"blockId":"radioBroadcastMessage","block":"radio send $msg","_shadowOverrides":{"msg":"radioMessageCode"},"draggableParameters":"true","weight":200,"blockGap":"8","help":"radio/send-message","group":"Broadcast","paramHelp":{"msg":""},"jsDoc":"Broadcasts a message over radio","_def":{"parts":[{"kind":"label","text":"radio send ","style":[]},{"kind":"param","name":"msg","shadowBlockId":"radioMessageCode","ref":true}],"parameters":[{"kind":"param","name":"msg","shadowBlockId":"radioMessageCode","ref":true}]}},"parameters":[{"name":"msg"}],"pyQName":"radio.send_message"},"radio.onReceivedMessage":{"kind":-3,"attributes":{"blockId":"radioOnMessageReceived","block":"on radio $msg received","_shadowOverrides":{"msg":"radioMessageCode"},"draggableParameters":"true","weight":199,"help":"radio/on-received-message","group":"Broadcast","paramHelp":{"msg":"@param handler "},"jsDoc":"Registers code to run for a particular message","_def":{"parts":[{"kind":"label","text":"on radio ","style":[]},{"kind":"param","name":"msg","shadowBlockId":"radioMessageCode","ref":true},{"kind":"label","text":" received","style":[]}],"parameters":[{"kind":"param","name":"msg","shadowBlockId":"radioMessageCode","ref":true}]}},"parameters":[{"name":"msg","description":"@param handler "},{"name":"handler","type":"() => void","handlerParameters":[]}],"pyQName":"radio.on_received_message"}}},"sha":"c8c5e8458ff26c8944c862d8f73e85bd45058346ecebad183523d0e34bce6a3e"},"libs/microphone":{"apis":{"byQName":{"input":{"kind":5,"retType":"","attributes":{"color":"#D400D4","weight":111,"icon":"","jsDoc":"Events and data from sensors"}},"DetectedSound":{"kind":6,"retType":"DetectedSound","extendsTypes":["DetectedSound","Number"]},"DetectedSound.Loud":{"retType":"DetectedSound.Loud","attributes":{"block":"loud","_def":{"parts":[{"kind":"label","text":"loud","style":[]}],"parameters":[]}},"extendsTypes":["DetectedSound.Loud","Number"],"pyQName":"DetectedSound.LOUD"},"DetectedSound.Quiet":{"retType":"DetectedSound.Quiet","attributes":{"block":"quiet","_def":{"parts":[{"kind":"label","text":"quiet","style":[]}],"parameters":[]}},"extendsTypes":["DetectedSound.Quiet","Number"],"pyQName":"DetectedSound.QUIET"},"SoundThreshold":{"kind":6,"retType":"SoundThreshold","extendsTypes":["SoundThreshold","Number"]},"SoundThreshold.Loud":{"retType":"SoundThreshold.Loud","attributes":{"block":"loud","_def":{"parts":[{"kind":"label","text":"loud","style":[]}],"parameters":[]}},"extendsTypes":["SoundThreshold.Loud","Number"],"pyQName":"SoundThreshold.LOUD"},"SoundThreshold.Quiet":{"retType":"SoundThreshold.Quiet","attributes":{"block":"quiet","_def":{"parts":[{"kind":"label","text":"quiet","style":[]}],"parameters":[]}},"extendsTypes":["SoundThreshold.Quiet","Number"],"pyQName":"SoundThreshold.QUIET"},"input.onSound":{"kind":-3,"attributes":{"help":"input/on-sound","blockId":"input_on_sound","block":"on %sound sound","parts":"microphone","weight":88,"blockGap":"12","group":"micro:bit (V2)","jsDoc":"Registers an event that runs when a sound is detected","_def":{"parts":[{"kind":"label","text":"on ","style":[]},{"kind":"param","name":"sound","ref":false},{"kind":"label","text":" sound","style":[]}],"parameters":[{"kind":"param","name":"sound","ref":false}]}},"parameters":[{"name":"sound","type":"DetectedSound","isEnum":true},{"name":"handler","type":"() => void","handlerParameters":[]}],"pyQName":"input.on_sound"},"input.soundLevel":{"kind":-3,"retType":"number","attributes":{"help":"input/sound-level","blockId":"device_get_sound_level","block":"sound level","parts":"microphone","weight":34,"blockGap":"8","group":"micro:bit (V2)","jsDoc":"Reads the loudness through the microphone from 0 (silent) to 255 (loud)","_def":{"parts":[{"kind":"label","text":"sound level","style":[]}],"parameters":[]}},"parameters":[],"pyQName":"input.sound_level"},"input.setSoundThreshold":{"kind":-3,"attributes":{"paramDefl":{"threshold":"128"},"help":"input/set-sound-threshold","blockId":"input_set_sound_threshold","block":"set %sound sound threshold to %value","parts":"microphone","paramMin":{"threshold":"0"},"paramMax":{"threshold":"255"},"weight":14,"blockGap":"8","advanced":true,"group":"micro:bit (V2)","explicitDefaults":["threshold"],"jsDoc":"Sets the threshold for a sound type.","_def":{"parts":[{"kind":"label","text":"set ","style":[]},{"kind":"param","name":"sound","ref":false},{"kind":"label","text":" sound threshold to ","style":[]},{"kind":"param","name":"value","ref":false}],"parameters":[{"kind":"param","name":"sound","ref":false},{"kind":"param","name":"value","ref":false}]}},"parameters":[{"name":"sound","type":"SoundThreshold","isEnum":true},{"name":"threshold","initializer":"128","default":"128","options":{"min":{"value":"0"},"max":{"value":"255"}}}],"pyQName":"input.set_sound_threshold"}}},"sha":"657e630bc4b5a0b83305eeb8d42b16b691a8465d6a94eee721e1635eaf2d992b"},"libs/settings":{"apis":{"byQName":{"settings":{"kind":5,"retType":""},"settings.runNumber":{"kind":-3,"retType":"number","parameters":[],"pyQName":"settings.run_number"},"settings.clear":{"kind":-3,"attributes":{"jsDoc":"Delete all non-system settings."},"parameters":[]},"settings.writeBuffer":{"kind":-3,"attributes":{"jsDoc":"Set named setting to a given buffer."},"parameters":[{"name":"key","type":"string"},{"name":"value","type":"Buffer"}],"pyQName":"settings.write_buffer"},"settings.writeString":{"kind":-3,"attributes":{"jsDoc":"Set named settings to a given string."},"parameters":[{"name":"key","type":"string"},{"name":"value","type":"string"}],"pyQName":"settings.write_string"},"settings.writeJSON":{"kind":-3,"attributes":{"jsDoc":"Set named settings to a given JSON object."},"parameters":[{"name":"key","type":"string"},{"name":"value","type":"any"}],"pyQName":"settings.write_json"},"settings.writeNumber":{"kind":-3,"attributes":{"jsDoc":"Set named settings to a given number."},"parameters":[{"name":"key","type":"string"},{"name":"value"}],"pyQName":"settings.write_number"},"settings.writeNumberArray":{"kind":-3,"attributes":{"jsDoc":"Set named settings to a given array of numbers."},"parameters":[{"name":"key","type":"string"},{"name":"value","type":"number[]"}],"pyQName":"settings.write_number_array"},"settings.readBuffer":{"kind":-3,"retType":"Buffer","attributes":{"jsDoc":"Read named setting as a buffer. Returns undefined when setting not found."},"parameters":[{"name":"key","type":"string"}],"pyQName":"settings.read_buffer"},"settings.readString":{"kind":-3,"retType":"string","attributes":{"jsDoc":"Read named setting as a string."},"parameters":[{"name":"key","type":"string"}],"pyQName":"settings.read_string"},"settings.readJSON":{"kind":-3,"retType":"any","attributes":{"jsDoc":"Read named setting as a JSON object."},"parameters":[{"name":"key","type":"string"}],"pyQName":"settings.read_json"},"settings.readNumber":{"kind":-3,"retType":"number","attributes":{"jsDoc":"Read named setting as a number."},"parameters":[{"name":"key","type":"string"}],"pyQName":"settings.read_number"},"settings.readNumberArray":{"kind":-3,"retType":"number[]","attributes":{"jsDoc":"Read named setting as a number."},"parameters":[{"name":"key","type":"string"}],"pyQName":"settings.read_number_array"},"settings.list":{"kind":-3,"retType":"string[]","attributes":{"jsDoc":"Return a list of settings starting with a given prefix."},"parameters":[{"name":"prefix","type":"string","initializer":"undefined"}]},"settings.remove":{"kind":-3,"attributes":{"jsDoc":"Remove named setting."},"parameters":[{"name":"key","type":"string"}]},"settings.exists":{"kind":-3,"retType":"boolean","attributes":{"jsDoc":"Check if a named setting exists."},"parameters":[{"name":"key","type":"string"}]},"settings.SecretStore":{"kind":8,"retType":"settings.SecretStore","attributes":{"fixedInstances":"true"},"extendsTypes":[]},"settings.SecretStore.__constructor":{"kind":-3,"parameters":[{"name":"key","type":"string"}],"isInstance":true},"settings.SecretStore.setSecret":{"kind":-1,"parameters":[{"name":"name","type":"string"},{"name":"value","type":"any"}],"isInstance":true,"pyQName":"settings.SecretStore.set_secret"},"settings.SecretStore.updateSecret":{"kind":-1,"parameters":[{"name":"name","type":"string"},{"name":"value","type":"any"}],"isInstance":true,"pyQName":"settings.SecretStore.update_secret"},"settings.SecretStore.readSecret":{"kind":-1,"retType":"any","parameters":[{"name":"name","type":"string"},{"name":"ensure","type":"boolean","initializer":"false"}],"isInstance":true,"pyQName":"settings.SecretStore.read_secret"},"settings.SecretStore.clearSecrets":{"kind":-1,"parameters":[],"isInstance":true,"pyQName":"settings.SecretStore.clear_secrets"},"settings.SecretStore.readSecrets":{"kind":-1,"retType":"any","parameters":[],"isInstance":true,"pyQName":"settings.SecretStore.read_secrets"},"settings.deviceSecrets":{"kind":4,"retType":"settings.SecretStore","attributes":{"fixedInstance":"true","whenUsed":"true","block":"device secrets","jsDoc":"Secrets shared by any program on the device","_def":{"parts":[{"kind":"label","text":"device secrets","style":[]}],"parameters":[]}},"pyQName":"settings.device_secrets"},"settings.programSecrets":{"kind":4,"retType":"settings.SecretStore","attributes":{"fixedInstance":"true","whenUsed":"true","block":"program secrets","jsDoc":"Program secrets","_def":{"parts":[{"kind":"label","text":"program secrets","style":[]}],"parameters":[]}},"pyQName":"settings.program_secrets"},"config":{"kind":5,"retType":""},"config.SETTINGS_SIZE_DEFL":{"kind":4,"retType":"number"}}},"sha":"63c47288c281a81e0a783bbbffc43cd2f035b46603d6b95264a0430038b37c0e"},"libs/flashlog":{"apis":{"byQName":{"flashlog":{"kind":5,"retType":"","attributes":{"jsDoc":"Storing structured data in flash."}},"flashlog.beginRow":{"kind":-3,"retType":"number","attributes":{"help":"flashlog/begin-row","parts":"flashlog","blockGap":"8","group":"micro:bit (V2)","jsDoc":"Creates a new row in the log, ready to be populated by logData()"},"parameters":[],"pyQName":"flashlog.begin_row"},"flashlog.logData":{"kind":-3,"retType":"number","attributes":{"help":"flashlog/log-data","parts":"flashlog","blockGap":"8","group":"micro:bit (V2)","jsDoc":"Populates the current row with the given key/value pair."},"parameters":[{"name":"key","type":"string"},{"name":"value","type":"string"}],"pyQName":"flashlog.log_data"},"flashlog.logString":{"kind":-3,"retType":"number","attributes":{"help":"flashlog/log-string","parts":"flashlog","blockGap":"8","group":"micro:bit (V2)","jsDoc":"Inject the given row into the log as text, ignoring key/value pairs."},"parameters":[{"name":"value","type":"string"}],"pyQName":"flashlog.log_string"},"flashlog.endRow":{"kind":-3,"retType":"number","attributes":{"help":"flashlog/end-row","parts":"flashlog","blockGap":"8","group":"micro:bit (V2)","jsDoc":"Complete a row in the log, and pushes to persistent storage."},"parameters":[],"pyQName":"flashlog.end_row"},"flashlog.clear":{"kind":-3,"attributes":{"help":"flashlog/clear","parts":"flashlog","blockGap":"8","group":"micro:bit (V2)","jsDoc":"Resets all data stored in persistent storage."},"parameters":[{"name":"fullErase","type":"boolean"}]},"flashlog.setTimeStamp":{"kind":-3,"attributes":{"help":"flashlog/set-timestamp","parts":"flashlog","blockGap":"8","group":"micro:bit (V2)","jsDoc":"Determines the format of the timestamp data to be added (if any).\nIf requested, time stamps will be automatically added to each row of data\nas an integer value rounded down to the unit specified.\n* @param format The format of timestamp to use."},"parameters":[{"name":"format","type":"FlashLogTimeStampFormat","isEnum":true}],"pyQName":"flashlog.set_time_stamp"},"flashlog.setSerialMirroring":{"kind":-3,"attributes":{"help":"flashlog/set-serial-mirroring","parts":"flashlog","blockGap":"8","group":"micro:bit (V2)","jsDoc":"Defines if data logging should also be streamed over the serial port.\n* @param enable True to enable serial port streaming, false to disable."},"parameters":[{"name":"enable","type":"boolean"}],"pyQName":"flashlog.set_serial_mirroring"},"flashlog.getNumberOfRows":{"kind":-3,"retType":"number","attributes":{"paramDefl":{"fromRowIndex":"0"},"explicitDefaults":["fromRowIndex"],"paramHelp":{"fromRowIndex":"0-based index of start: Default value of 0"},"jsDoc":"Number of rows currently used by the datalogger, start counting at fromRowIndex\nTreats the header as the first row\n\n@returns header + rows"},"parameters":[{"name":"fromRowIndex","description":"0-based index of start: Default value of 0","initializer":"0","default":"0"}],"pyQName":"flashlog.get_number_of_rows"},"flashlog.getRows":{"kind":-3,"retType":"string","attributes":{"paramHelp":{"fromRowIndex":"0-based index of start","nRows":"inclusive count from fromRowIndex"},"jsDoc":"Get all rows separated by a newline & each column separated by a comma.\nStarting at the 0-based index fromRowIndex & counting inclusively until nRows.\n\n\n@returns String where newlines denote rows & commas denote columns"},"parameters":[{"name":"fromRowIndex","description":"0-based index of start"},{"name":"nRows","description":"inclusive count from fromRowIndex"}],"pyQName":"flashlog.get_rows"},"FlashLogTimeStampFormat":{"kind":6,"retType":"FlashLogTimeStampFormat","extendsTypes":["FlashLogTimeStampFormat","Number"]},"FlashLogTimeStampFormat.None":{"retType":"FlashLogTimeStampFormat.None","attributes":{"block":"none","_def":{"parts":[{"kind":"label","text":"none","style":[]}],"parameters":[]}},"extendsTypes":["FlashLogTimeStampFormat.None","Number"],"pyQName":"FlashLogTimeStampFormat.NONE"},"FlashLogTimeStampFormat.Milliseconds":{"retType":"FlashLogTimeStampFormat.Milliseconds","attributes":{"block":"milliseconds","_def":{"parts":[{"kind":"label","text":"milliseconds","style":[]}],"parameters":[]}},"extendsTypes":["FlashLogTimeStampFormat.Milliseconds","Number"],"pyQName":"FlashLogTimeStampFormat.MILLISECONDS"},"FlashLogTimeStampFormat.Seconds":{"retType":"FlashLogTimeStampFormat.Seconds","attributes":{"block":"seconds","_def":{"parts":[{"kind":"label","text":"seconds","style":[]}],"parameters":[]}},"extendsTypes":["FlashLogTimeStampFormat.Seconds","Number"],"pyQName":"FlashLogTimeStampFormat.SECONDS"},"FlashLogTimeStampFormat.Minutes":{"retType":"FlashLogTimeStampFormat.Minutes","attributes":{"block":"minutes","_def":{"parts":[{"kind":"label","text":"minutes","style":[]}],"parameters":[]}},"extendsTypes":["FlashLogTimeStampFormat.Minutes","Number"],"pyQName":"FlashLogTimeStampFormat.MINUTES"},"FlashLogTimeStampFormat.Hours":{"retType":"FlashLogTimeStampFormat.Hours","attributes":{"block":"hours","_def":{"parts":[{"kind":"label","text":"hours","style":[]}],"parameters":[]}},"extendsTypes":["FlashLogTimeStampFormat.Hours","Number"],"pyQName":"FlashLogTimeStampFormat.HOURS"},"FlashLogTimeStampFormat.Days":{"retType":"FlashLogTimeStampFormat.Days","attributes":{"block":"days","_def":{"parts":[{"kind":"label","text":"days","style":[]}],"parameters":[]}},"extendsTypes":["FlashLogTimeStampFormat.Days","Number"],"pyQName":"FlashLogTimeStampFormat.DAYS"}}},"sha":"fb21dc439f6ea395d5854a7b04d080ec645e739d3d2351fee46e1e78556f2bf0"},"libs/datalogger":{"apis":{"byQName":{"flashlog":{"kind":5,"retType":"","attributes":{"jsDoc":"Storing structured data in flash."}},"flashlog.beginRow":{"kind":-3,"retType":"number","attributes":{"help":"flashlog/begin-row","parts":"flashlog","blockGap":"8","group":"micro:bit (V2)","jsDoc":"Creates a new row in the log, ready to be populated by logData()"},"parameters":[],"pyQName":"flashlog.begin_row"},"flashlog.logData":{"kind":-3,"retType":"number","attributes":{"help":"flashlog/log-data","parts":"flashlog","blockGap":"8","group":"micro:bit (V2)","jsDoc":"Populates the current row with the given key/value pair."},"parameters":[{"name":"key","type":"string"},{"name":"value","type":"string"}],"pyQName":"flashlog.log_data"},"flashlog.logString":{"kind":-3,"retType":"number","attributes":{"help":"flashlog/log-string","parts":"flashlog","blockGap":"8","group":"micro:bit (V2)","jsDoc":"Inject the given row into the log as text, ignoring key/value pairs."},"parameters":[{"name":"value","type":"string"}],"pyQName":"flashlog.log_string"},"flashlog.endRow":{"kind":-3,"retType":"number","attributes":{"help":"flashlog/end-row","parts":"flashlog","blockGap":"8","group":"micro:bit (V2)","jsDoc":"Complete a row in the log, and pushes to persistent storage."},"parameters":[],"pyQName":"flashlog.end_row"},"flashlog.clear":{"kind":-3,"attributes":{"help":"flashlog/clear","parts":"flashlog","blockGap":"8","group":"micro:bit (V2)","jsDoc":"Resets all data stored in persistent storage."},"parameters":[{"name":"fullErase","type":"boolean"}]},"flashlog.setTimeStamp":{"kind":-3,"attributes":{"help":"flashlog/set-timestamp","parts":"flashlog","blockGap":"8","group":"micro:bit (V2)","jsDoc":"Determines the format of the timestamp data to be added (if any).\nIf requested, time stamps will be automatically added to each row of data\nas an integer value rounded down to the unit specified.\n* @param format The format of timestamp to use."},"parameters":[{"name":"format","type":"FlashLogTimeStampFormat","isEnum":true}],"pyQName":"flashlog.set_time_stamp"},"flashlog.setSerialMirroring":{"kind":-3,"attributes":{"help":"flashlog/set-serial-mirroring","parts":"flashlog","blockGap":"8","group":"micro:bit (V2)","jsDoc":"Defines if data logging should also be streamed over the serial port.\n* @param enable True to enable serial port streaming, false to disable."},"parameters":[{"name":"enable","type":"boolean"}],"pyQName":"flashlog.set_serial_mirroring"},"flashlog.getNumberOfRows":{"kind":-3,"retType":"number","attributes":{"paramDefl":{"fromRowIndex":"0"},"explicitDefaults":["fromRowIndex"],"paramHelp":{"fromRowIndex":"0-based index of start: Default value of 0"},"jsDoc":"Number of rows currently used by the datalogger, start counting at fromRowIndex\nTreats the header as the first row\n\n@returns header + rows"},"parameters":[{"name":"fromRowIndex","description":"0-based index of start: Default value of 0","initializer":"0","default":"0"}],"pyQName":"flashlog.get_number_of_rows"},"flashlog.getRows":{"kind":-3,"retType":"string","attributes":{"paramHelp":{"fromRowIndex":"0-based index of start","nRows":"inclusive count from fromRowIndex"},"jsDoc":"Get all rows separated by a newline & each column separated by a comma.\nStarting at the 0-based index fromRowIndex & counting inclusively until nRows.\n\n\n@returns String where newlines denote rows & commas denote columns"},"parameters":[{"name":"fromRowIndex","description":"0-based index of start"},{"name":"nRows","description":"inclusive count from fromRowIndex"}],"pyQName":"flashlog.get_rows"},"FlashLogTimeStampFormat":{"kind":6,"retType":"FlashLogTimeStampFormat","extendsTypes":["FlashLogTimeStampFormat","Number"]},"FlashLogTimeStampFormat.None":{"retType":"FlashLogTimeStampFormat.None","attributes":{"block":"none","_def":{"parts":[{"kind":"label","text":"none","style":[]}],"parameters":[]}},"extendsTypes":["FlashLogTimeStampFormat.None","Number"],"pyQName":"FlashLogTimeStampFormat.NONE"},"FlashLogTimeStampFormat.Milliseconds":{"retType":"FlashLogTimeStampFormat.Milliseconds","attributes":{"block":"milliseconds","_def":{"parts":[{"kind":"label","text":"milliseconds","style":[]}],"parameters":[]}},"extendsTypes":["FlashLogTimeStampFormat.Milliseconds","Number"],"pyQName":"FlashLogTimeStampFormat.MILLISECONDS"},"FlashLogTimeStampFormat.Seconds":{"retType":"FlashLogTimeStampFormat.Seconds","attributes":{"block":"seconds","_def":{"parts":[{"kind":"label","text":"seconds","style":[]}],"parameters":[]}},"extendsTypes":["FlashLogTimeStampFormat.Seconds","Number"],"pyQName":"FlashLogTimeStampFormat.SECONDS"},"FlashLogTimeStampFormat.Minutes":{"retType":"FlashLogTimeStampFormat.Minutes","attributes":{"block":"minutes","_def":{"parts":[{"kind":"label","text":"minutes","style":[]}],"parameters":[]}},"extendsTypes":["FlashLogTimeStampFormat.Minutes","Number"],"pyQName":"FlashLogTimeStampFormat.MINUTES"},"FlashLogTimeStampFormat.Hours":{"retType":"FlashLogTimeStampFormat.Hours","attributes":{"block":"hours","_def":{"parts":[{"kind":"label","text":"hours","style":[]}],"parameters":[]}},"extendsTypes":["FlashLogTimeStampFormat.Hours","Number"],"pyQName":"FlashLogTimeStampFormat.HOURS"},"FlashLogTimeStampFormat.Days":{"retType":"FlashLogTimeStampFormat.Days","attributes":{"block":"days","_def":{"parts":[{"kind":"label","text":"days","style":[]}],"parameters":[]}},"extendsTypes":["FlashLogTimeStampFormat.Days","Number"],"pyQName":"FlashLogTimeStampFormat.DAYS"},"datalogger":{"kind":5,"retType":"","attributes":{"block":"Data Logger","icon":"","color":"#378273","jsDoc":"Log data to flash storage","_def":{"parts":[{"kind":"label","text":"Data Logger","style":[]}],"parameters":[]}}},"datalogger.DeleteType":{"kind":6,"retType":"datalogger.DeleteType","extendsTypes":["datalogger.DeleteType","Number"]},"datalogger.DeleteType.Fast":{"retType":"datalogger.DeleteType.Fast","attributes":{"block":"fast","_def":{"parts":[{"kind":"label","text":"fast","style":[]}],"parameters":[]}},"extendsTypes":["datalogger.DeleteType.Fast","Number"],"pyQName":"datalogger.DeleteType.FAST"},"datalogger.DeleteType.Full":{"retType":"datalogger.DeleteType.Full","attributes":{"block":"full","_def":{"parts":[{"kind":"label","text":"full","style":[]}],"parameters":[]}},"extendsTypes":["datalogger.DeleteType.Full","Number"],"pyQName":"datalogger.DeleteType.FULL"},"datalogger.ColumnValue":{"kind":8,"retType":"datalogger.ColumnValue","extendsTypes":[]},"datalogger.ColumnValue.value":{"kind":2,"retType":"string","isInstance":true},"datalogger.ColumnValue.__constructor":{"kind":-3,"parameters":[{"name":"column","type":"string"},{"name":"value","type":"any"}],"isInstance":true},"datalogger.createCV":{"kind":-3,"retType":"datalogger.ColumnValue","attributes":{"block":"column $column value $value","_shadowOverrides":{"value":"math_number","column":"datalogger_columnfield"},"blockId":"dataloggercreatecolumnvalue","group":"micro:bit (V2)","weight":80,"help":"datalogger/create-cv","paramHelp":{"column":"the column to set","value":"the value to set."},"jsDoc":"A column and value to log to flash storage\n\n\n@returns A new value that can be stored in flash storage using log data","_def":{"parts":[{"kind":"label","text":"column ","style":[]},{"kind":"param","name":"column","shadowBlockId":"datalogger_columnfield","ref":true},{"kind":"label","text":" value ","style":[]},{"kind":"param","name":"value","shadowBlockId":"math_number","ref":true}],"parameters":[{"kind":"param","name":"column","shadowBlockId":"datalogger_columnfield","ref":true},{"kind":"param","name":"value","shadowBlockId":"math_number","ref":true}]}},"parameters":[{"name":"column","description":"the column to set","type":"string"},{"name":"value","description":"the value to set.","type":"any"}],"pyQName":"datalogger.create_cv"},"datalogger._columnField":{"kind":-3,"retType":"string","attributes":{"block":"$column","blockId":"datalogger_columnfield","group":"micro:bit (V2)","blockHidden":true,"shim":"TD_ID","paramFieldEditor":{"column":"autocomplete"},"paramFieldEditorOptions":{"column":{"decompileLiterals":"true","key":"dataloggercolumn"}},"_def":{"parts":[{"kind":"param","name":"column","ref":true}],"parameters":[{"kind":"param","name":"column","ref":true}]}},"parameters":[{"name":"column","type":"string"}],"pyQName":"datalogger._column_field"},"datalogger.logData":{"kind":-3,"attributes":{"paramDefl":{"data":"dataloggercreatecolumnvalue"},"block":"log data array $data","blockId":"dataloggerlogdata","_shadowOverrides":{"data":"lists_create_with"},"explicitDefaults":["data"],"group":"micro:bit (V2)","blockHidden":true,"weight":100,"paramHelp":{"data":"Array of data to be logged to flash storage"},"jsDoc":"Log data to flash storage","_def":{"parts":[{"kind":"label","text":"log data array ","style":[]},{"kind":"param","name":"data","shadowBlockId":"lists_create_with","ref":true}],"parameters":[{"kind":"param","name":"data","shadowBlockId":"lists_create_with","ref":true}]}},"parameters":[{"name":"data","description":"Array of data to be logged to flash storage","type":"datalogger.ColumnValue[]","initializer":"dataloggercreatecolumnvalue","default":"dataloggercreatecolumnvalue"}],"pyQName":"datalogger.log_data"},"datalogger.log":{"kind":-3,"attributes":{"block":"log data $data1||$data2 $data3 $data4 $data5 $data6 $data7 $data8 $data9 $data10","blockId":"dataloggerlog","_shadowOverrides":{"data1":"dataloggercreatecolumnvalue","data2":"dataloggercreatecolumnvalue","data3":"dataloggercreatecolumnvalue","data4":"dataloggercreatecolumnvalue","data5":"dataloggercreatecolumnvalue","data6":"dataloggercreatecolumnvalue","data7":"dataloggercreatecolumnvalue","data8":"dataloggercreatecolumnvalue","data9":"dataloggercreatecolumnvalue","data10":"dataloggercreatecolumnvalue"},"inlineInputMode":"variable","inlineInputModeLimit":1,"group":"micro:bit (V2)","weight":100,"help":"datalogger/log","paramHelp":{"data1":"First column and value to be logged","data2":"[optional] second column and value to be logged","data3":"[optional] third column and value to be logged","data4":"[optional] fourth column and value to be logged","data5":"[optional] fifth column and value to be logged","data6":"[optional] sixth column and value to be logged","data7":"[optional] seventh column and value to be logged","data8":"[optional] eighth column and value to be logged","data9":"[optional] ninth column and value to be logged","data10":"[optional] tenth column and value to be logged"},"jsDoc":"Log data to flash storage","_def":{"parts":[{"kind":"label","text":"log data ","style":[]},{"kind":"param","name":"data1","shadowBlockId":"dataloggercreatecolumnvalue","ref":true}],"parameters":[{"kind":"param","name":"data1","shadowBlockId":"dataloggercreatecolumnvalue","ref":true}]},"_expandedDef":{"parts":[{"kind":"param","name":"data2","shadowBlockId":"dataloggercreatecolumnvalue","ref":true},{"kind":"label","text":" ","style":[]},{"kind":"param","name":"data3","shadowBlockId":"dataloggercreatecolumnvalue","ref":true},{"kind":"label","text":" ","style":[]},{"kind":"param","name":"data4","shadowBlockId":"dataloggercreatecolumnvalue","ref":true},{"kind":"label","text":" ","style":[]},{"kind":"param","name":"data5","shadowBlockId":"dataloggercreatecolumnvalue","ref":true},{"kind":"label","text":" ","style":[]},{"kind":"param","name":"data6","shadowBlockId":"dataloggercreatecolumnvalue","ref":true},{"kind":"label","text":" ","style":[]},{"kind":"param","name":"data7","shadowBlockId":"dataloggercreatecolumnvalue","ref":true},{"kind":"label","text":" ","style":[]},{"kind":"param","name":"data8","shadowBlockId":"dataloggercreatecolumnvalue","ref":true},{"kind":"label","text":" ","style":[]},{"kind":"param","name":"data9","shadowBlockId":"dataloggercreatecolumnvalue","ref":true},{"kind":"label","text":" ","style":[]},{"kind":"param","name":"data10","shadowBlockId":"dataloggercreatecolumnvalue","ref":true}],"parameters":[{"kind":"param","name":"data2","shadowBlockId":"dataloggercreatecolumnvalue","ref":true},{"kind":"param","name":"data3","shadowBlockId":"dataloggercreatecolumnvalue","ref":true},{"kind":"param","name":"data4","shadowBlockId":"dataloggercreatecolumnvalue","ref":true},{"kind":"param","name":"data5","shadowBlockId":"dataloggercreatecolumnvalue","ref":true},{"kind":"param","name":"data6","shadowBlockId":"dataloggercreatecolumnvalue","ref":true},{"kind":"param","name":"data7","shadowBlockId":"dataloggercreatecolumnvalue","ref":true},{"kind":"param","name":"data8","shadowBlockId":"dataloggercreatecolumnvalue","ref":true},{"kind":"param","name":"data9","shadowBlockId":"dataloggercreatecolumnvalue","ref":true},{"kind":"param","name":"data10","shadowBlockId":"dataloggercreatecolumnvalue","ref":true}]}},"parameters":[{"name":"data1","description":"First column and value to be logged","type":"datalogger.ColumnValue"},{"name":"data2","description":"[optional] second column and value to be logged","type":"datalogger.ColumnValue","initializer":"undefined"},{"name":"data3","description":"[optional] third column and value to be logged","type":"datalogger.ColumnValue","initializer":"undefined"},{"name":"data4","description":"[optional] fourth column and value to be logged","type":"datalogger.ColumnValue","initializer":"undefined"},{"name":"data5","description":"[optional] fifth column and value to be logged","type":"datalogger.ColumnValue","initializer":"undefined"},{"name":"data6","description":"[optional] sixth column and value to be logged","type":"datalogger.ColumnValue","initializer":"undefined"},{"name":"data7","description":"[optional] seventh column and value to be logged","type":"datalogger.ColumnValue","initializer":"undefined"},{"name":"data8","description":"[optional] eighth column and value to be logged","type":"datalogger.ColumnValue","initializer":"undefined"},{"name":"data9","description":"[optional] ninth column and value to be logged","type":"datalogger.ColumnValue","initializer":"undefined"},{"name":"data10","description":"[optional] tenth column and value to be logged","type":"datalogger.ColumnValue","initializer":"undefined"}]},"datalogger.setColumns":{"kind":-3,"attributes":{"paramDefl":{"data":"datalogger_columnfield"},"block":"set columns $cols","blockId":"dataloggersetcolumns","_shadowOverrides":{"data":"list_create_with"},"explicitDefaults":["data"],"group":"micro:bit (V2)","blockHidden":true,"weight":70,"paramHelp":{"cols":"Array of the columns that will be logged."},"jsDoc":"Set the columns for future data logging","_def":{"parts":[{"kind":"label","text":"set columns ","style":[]},{"kind":"param","name":"cols","ref":true}],"parameters":[{"kind":"param","name":"cols","ref":true}]}},"parameters":[{"name":"cols","description":"Array of the columns that will be logged.","type":"string[]"}],"pyQName":"datalogger.set_columns"},"datalogger.setColumnTitles":{"kind":-3,"attributes":{"block":"set columns $col1||$col2 $col3 $col4 $col5 $col6 $col7 $col8 $col9 $col10","blockId":"dataloggersetcolumntitles","inlineInputMode":"variable","inlineInputModeLimit":1,"group":"micro:bit (V2)","weight":70,"help":"datalogger/set-column-titles","_shadowOverrides":{"col1":"datalogger_columnfield","col2":"datalogger_columnfield","col3":"datalogger_columnfield","col4":"datalogger_columnfield","col5":"datalogger_columnfield","col6":"datalogger_columnfield","col7":"datalogger_columnfield","col8":"datalogger_columnfield","col9":"datalogger_columnfield","col10":"datalogger_columnfield"},"paramHelp":{"col1":"Title for first column to be added","col2":"Title for second column to be added","col3":"Title for third column to be added","col4":"Title for fourth column to be added","col5":"Title for fifth column to be added","col6":"Title for sixth column to be added","col7":"Title for seventh column to be added","col8":"Title for eighth column to be added","col9":"Title for ninth column to be added","col10":"Title for tenth column to be added"},"jsDoc":"Set the columns for future data logging","_def":{"parts":[{"kind":"label","text":"set columns ","style":[]},{"kind":"param","name":"col1","shadowBlockId":"datalogger_columnfield","ref":true}],"parameters":[{"kind":"param","name":"col1","shadowBlockId":"datalogger_columnfield","ref":true}]},"_expandedDef":{"parts":[{"kind":"param","name":"col2","shadowBlockId":"datalogger_columnfield","ref":true},{"kind":"label","text":" ","style":[]},{"kind":"param","name":"col3","shadowBlockId":"datalogger_columnfield","ref":true},{"kind":"label","text":" ","style":[]},{"kind":"param","name":"col4","shadowBlockId":"datalogger_columnfield","ref":true},{"kind":"label","text":" ","style":[]},{"kind":"param","name":"col5","shadowBlockId":"datalogger_columnfield","ref":true},{"kind":"label","text":" ","style":[]},{"kind":"param","name":"col6","shadowBlockId":"datalogger_columnfield","ref":true},{"kind":"label","text":" ","style":[]},{"kind":"param","name":"col7","shadowBlockId":"datalogger_columnfield","ref":true},{"kind":"label","text":" ","style":[]},{"kind":"param","name":"col8","shadowBlockId":"datalogger_columnfield","ref":true},{"kind":"label","text":" ","style":[]},{"kind":"param","name":"col9","shadowBlockId":"datalogger_columnfield","ref":true},{"kind":"label","text":" ","style":[]},{"kind":"param","name":"col10","shadowBlockId":"datalogger_columnfield","ref":true}],"parameters":[{"kind":"param","name":"col2","shadowBlockId":"datalogger_columnfield","ref":true},{"kind":"param","name":"col3","shadowBlockId":"datalogger_columnfield","ref":true},{"kind":"param","name":"col4","shadowBlockId":"datalogger_columnfield","ref":true},{"kind":"param","name":"col5","shadowBlockId":"datalogger_columnfield","ref":true},{"kind":"param","name":"col6","shadowBlockId":"datalogger_columnfield","ref":true},{"kind":"param","name":"col7","shadowBlockId":"datalogger_columnfield","ref":true},{"kind":"param","name":"col8","shadowBlockId":"datalogger_columnfield","ref":true},{"kind":"param","name":"col9","shadowBlockId":"datalogger_columnfield","ref":true},{"kind":"param","name":"col10","shadowBlockId":"datalogger_columnfield","ref":true}]}},"parameters":[{"name":"col1","description":"Title for first column to be added","type":"string"},{"name":"col2","description":"Title for second column to be added","type":"string","initializer":"undefined"},{"name":"col3","description":"Title for third column to be added","type":"string","initializer":"undefined"},{"name":"col4","description":"Title for fourth column to be added","type":"string","initializer":"undefined"},{"name":"col5","description":"Title for fifth column to be added","type":"string","initializer":"undefined"},{"name":"col6","description":"Title for sixth column to be added","type":"string","initializer":"undefined"},{"name":"col7","description":"Title for seventh column to be added","type":"string","initializer":"undefined"},{"name":"col8","description":"Title for eighth column to be added","type":"string","initializer":"undefined"},{"name":"col9","description":"Title for ninth column to be added","type":"string","initializer":"undefined"},{"name":"col10","description":"Title for tenth column to be added","type":"string","initializer":"undefined"}],"pyQName":"datalogger.set_column_titles"},"datalogger.deleteLog":{"kind":-3,"attributes":{"block":"delete log||$deleteType","blockId":"dataloggerdeletelog","group":"micro:bit (V2)","weight":60,"help":"datalogger/delete-log","paramHelp":{"deleteType":"optional set whether a deletion will be fast or full"},"jsDoc":"Delete all existing logs, including column headers. By default this only marks the log as\noverwriteable / deletable in the future.","_def":{"parts":[{"kind":"label","text":"delete log","style":[]}],"parameters":[]},"_expandedDef":{"parts":[{"kind":"param","name":"deleteType","ref":true}],"parameters":[{"kind":"param","name":"deleteType","ref":true}]}},"parameters":[{"name":"deleteType","description":"optional set whether a deletion will be fast or full","type":"datalogger.DeleteType","initializer":"undefined","isEnum":true}],"pyQName":"datalogger.delete_log"},"datalogger.onLogFull":{"kind":-3,"attributes":{"block":"on log full","blockId":"on log full","group":"micro:bit (V2)","weight":40,"help":"datalogger/on-log-full","paramHelp":{"handler":"code to run when the log is full and no more data can be stored."},"jsDoc":"Register an event to run when no more data can be logged.","_def":{"parts":[{"kind":"label","text":"on log full","style":[]}],"parameters":[]}},"parameters":[{"name":"handler","description":"code to run when the log is full and no more data can be stored.","type":"() => void","handlerParameters":[]}],"pyQName":"datalogger.on_log_full"},"datalogger.includeTimestamp":{"kind":-3,"attributes":{"paramDefl":{"format":"FlashLogTimeStampFormat.None"},"block":"set timestamp $format","blockId":"dataloggertoggleincludetimestamp","explicitDefaults":["format"],"group":"micro:bit (V2)","weight":30,"help":"datalogger/include-timestamp","paramHelp":{"format":"Format in which to show the timestamp. Setting FlashLogTimeStampFormat.None will disable the timestamp."},"jsDoc":"Set the format for timestamps","_def":{"parts":[{"kind":"label","text":"set timestamp ","style":[]},{"kind":"param","name":"format","ref":true}],"parameters":[{"kind":"param","name":"format","ref":true}]}},"parameters":[{"name":"format","description":"Format in which to show the timestamp. Setting FlashLogTimeStampFormat.None will disable the timestamp.","type":"FlashLogTimeStampFormat","initializer":"FlashLogTimeStampFormat.None","default":"FlashLogTimeStampFormat.None","isEnum":true}],"pyQName":"datalogger.include_timestamp"},"datalogger.mirrorToSerial":{"kind":-3,"attributes":{"paramDefl":{"on":"false"},"block":"mirror data to serial $on","blockId":"dataloggertogglemirrortoserial","_shadowOverrides":{"on":"toggleOnOff"},"explicitDefaults":["on"],"weight":25,"help":"datalogger/mirror-to-serial","paramHelp":{"on":"if true, data that is logged will be mirrored to serial"},"jsDoc":"Set whether data is mirrored to serial or not.","_def":{"parts":[{"kind":"label","text":"mirror data to serial ","style":[]},{"kind":"param","name":"on","shadowBlockId":"toggleOnOff","ref":true}],"parameters":[{"kind":"param","name":"on","shadowBlockId":"toggleOnOff","ref":true}]}},"parameters":[{"name":"on","description":"if true, data that is logged will be mirrored to serial","type":"boolean","initializer":"false","default":"false"}],"pyQName":"datalogger.mirror_to_serial"},"datalogger.getNumberOfRows":{"kind":-3,"retType":"number","attributes":{"paramHelp":{"fromRowIndex":"0-based index of start"},"jsDoc":"Number of rows currently used by the datalogger, start counting at fromRowIndex\nTreats the header as the first row\n\n@returns header + rows"},"parameters":[{"name":"fromRowIndex","description":"0-based index of start","initializer":"0"}],"pyQName":"datalogger.get_number_of_rows"},"datalogger.getRows":{"kind":-3,"retType":"string","attributes":{"paramHelp":{"fromRowIndex":"0-based index of start","nRows":"inclusive count from fromRowIndex"},"jsDoc":"Get all rows seperated by a newline & each column seperated by a comma.\nStarting at the 0-based index fromRowIndex & counting inclusively until nRows.\n\n\n@returns String where newlines denote rows & commas denote columns"},"parameters":[{"name":"fromRowIndex","description":"0-based index of start"},{"name":"nRows","description":"inclusive count from fromRowIndex"}],"pyQName":"datalogger.get_rows"}}},"sha":"b16ca0b26df2633ef4e42cf6a7a5ef8a17713a1e77927dffacf253215723cca7"},"libs/bitmap":{"apis":{"byQName":{"helpers":{"kind":5,"retType":""},"bitmaps":{"kind":5,"retType":""},"bitmaps.repeatY":{"kind":-3,"retType":"Bitmap","parameters":[{"name":"count"},{"name":"image","type":"Bitmap"}],"pyQName":"bitmaps.repeat_y"},"bitmaps.concatY":{"kind":-3,"retType":"Bitmap","parameters":[{"name":"images","type":"Bitmap[]"}],"pyQName":"bitmaps.concat_y"},"Bitmap":{"kind":9,"retType":"Bitmap","attributes":{"snippet":"bmp` `","pySnippet":"bmp(\"\"\" \"\"\")"},"extendsTypes":[]},"Bitmap.drawIcon":{"kind":-1,"attributes":{"helper":"imageDrawIcon","jsDoc":"Draw an icon (monochromatic image) using given color"},"parameters":[{"name":"icon","type":"Buffer"},{"name":"x"},{"name":"y"},{"name":"c"}],"isInstance":true,"pyQName":"Bitmap.draw_icon"},"Bitmap.fillRect":{"kind":-1,"attributes":{"helper":"imageFillRect","jsDoc":"Fill a rectangle"},"parameters":[{"name":"x"},{"name":"y"},{"name":"w"},{"name":"h"},{"name":"c"}],"isInstance":true,"pyQName":"Bitmap.fill_rect"},"Bitmap.drawLine":{"kind":-1,"attributes":{"helper":"imageDrawLine","jsDoc":"Draw a line"},"parameters":[{"name":"x0"},{"name":"y0"},{"name":"x1"},{"name":"y1"},{"name":"c"}],"isInstance":true,"pyQName":"Bitmap.draw_line"},"Bitmap.drawRect":{"kind":-1,"attributes":{"helper":"imageDrawRect","jsDoc":"Draw an empty rectangle"},"parameters":[{"name":"x"},{"name":"y"},{"name":"w"},{"name":"h"},{"name":"c"}],"isInstance":true,"pyQName":"Bitmap.draw_rect"},"Bitmap.drawCircle":{"kind":-1,"attributes":{"helper":"imageDrawCircle","jsDoc":"Draw a circle"},"parameters":[{"name":"cx"},{"name":"cy"},{"name":"r"},{"name":"c"}],"isInstance":true,"pyQName":"Bitmap.draw_circle"},"Bitmap.fillCircle":{"kind":-1,"attributes":{"helper":"imageFillCircle","jsDoc":"Fills a circle"},"parameters":[{"name":"cx"},{"name":"cy"},{"name":"r"},{"name":"c"}],"isInstance":true,"pyQName":"Bitmap.fill_circle"},"Bitmap.fillTriangle":{"kind":-1,"attributes":{"helper":"imageFillTriangle","jsDoc":"Fills a triangle"},"parameters":[{"name":"x0"},{"name":"y0"},{"name":"x1"},{"name":"y1"},{"name":"x2"},{"name":"y2"},{"name":"col"}],"isInstance":true,"pyQName":"Bitmap.fill_triangle"},"Bitmap.fillPolygon4":{"kind":-1,"attributes":{"helper":"imageFillPolygon4","jsDoc":"Fills a 4-side-polygon"},"parameters":[{"name":"x0"},{"name":"y0"},{"name":"x1"},{"name":"y1"},{"name":"x2"},{"name":"y2"},{"name":"x3"},{"name":"y3"},{"name":"col"}],"isInstance":true,"pyQName":"Bitmap.fill_polygon4"},"Bitmap.rotated":{"kind":-1,"retType":"Bitmap","attributes":{"helper":"imageRotated","jsDoc":"Returns an image rotated by -90, 0, 90, 180, 270 deg clockwise"},"parameters":[{"name":"deg"}],"isInstance":true},"Bitmap.blitRow":{"kind":-1,"attributes":{"helper":"imageBlitRow","jsDoc":"Scale and copy a row of pixels from a texture."},"parameters":[{"name":"dstX"},{"name":"dstY"},{"name":"from","type":"Bitmap"},{"name":"fromX"},{"name":"fromH"}],"isInstance":true,"pyQName":"Bitmap.blit_row"},"Bitmap.blit":{"kind":-1,"retType":"boolean","attributes":{"helper":"imageBlit","jsDoc":"Copy an image from a source rectangle to a destination rectangle, stretching or\ncompressing to fit the dimensions of the destination rectangle, if necessary."},"parameters":[{"name":"xDst"},{"name":"yDst"},{"name":"wDst"},{"name":"hDst"},{"name":"src","type":"Bitmap"},{"name":"xSrc"},{"name":"ySrc"},{"name":"wSrc"},{"name":"hSrc"},{"name":"transparent","type":"boolean"},{"name":"check","type":"boolean"}],"isInstance":true},"helpers.imageBlit":{"kind":-3,"retType":"boolean","parameters":[{"name":"img","type":"Bitmap"},{"name":"xDst"},{"name":"yDst"},{"name":"wDst"},{"name":"hDst"},{"name":"src","type":"Bitmap"},{"name":"xSrc"},{"name":"ySrc"},{"name":"wSrc"},{"name":"hSrc"},{"name":"transparent","type":"boolean"},{"name":"check","type":"boolean"}],"pyQName":"helpers.image_blit"},"helpers.imageBlitRow":{"kind":-3,"parameters":[{"name":"img","type":"Bitmap"},{"name":"dstX"},{"name":"dstY"},{"name":"from","type":"Bitmap"},{"name":"fromX"},{"name":"fromH"}],"pyQName":"helpers.image_blit_row"},"helpers.imageDrawIcon":{"kind":-3,"parameters":[{"name":"img","type":"Bitmap"},{"name":"icon","type":"Buffer"},{"name":"x"},{"name":"y"},{"name":"c"}],"pyQName":"helpers.image_draw_icon"},"helpers.imageFillRect":{"kind":-3,"parameters":[{"name":"img","type":"Bitmap"},{"name":"x"},{"name":"y"},{"name":"w"},{"name":"h"},{"name":"c"}],"pyQName":"helpers.image_fill_rect"},"helpers.imageMapRect":{"kind":-3,"parameters":[{"name":"img","type":"Bitmap"},{"name":"x"},{"name":"y"},{"name":"w"},{"name":"h"},{"name":"m","type":"Buffer"}],"pyQName":"helpers.image_map_rect"},"helpers.imageDrawLine":{"kind":-3,"parameters":[{"name":"img","type":"Bitmap"},{"name":"x"},{"name":"y"},{"name":"w"},{"name":"h"},{"name":"c"}],"pyQName":"helpers.image_draw_line"},"helpers.imageDrawRect":{"kind":-3,"parameters":[{"name":"img","type":"Bitmap"},{"name":"x"},{"name":"y"},{"name":"w"},{"name":"h"},{"name":"c"}],"pyQName":"helpers.image_draw_rect"},"helpers.imageDrawCircle":{"kind":-3,"parameters":[{"name":"img","type":"Bitmap"},{"name":"cx"},{"name":"cy"},{"name":"r"},{"name":"col"}],"pyQName":"helpers.image_draw_circle"},"helpers.imageFillCircle":{"kind":-3,"parameters":[{"name":"img","type":"Bitmap"},{"name":"cx"},{"name":"cy"},{"name":"r"},{"name":"col"}],"pyQName":"helpers.image_fill_circle"},"helpers.imageFillTriangle":{"kind":-3,"parameters":[{"name":"img","type":"Bitmap"},{"name":"x0"},{"name":"y0"},{"name":"x1"},{"name":"y1"},{"name":"x2"},{"name":"y2"},{"name":"col"}],"pyQName":"helpers.image_fill_triangle"},"helpers.imageFillPolygon4":{"kind":-3,"parameters":[{"name":"img","type":"Bitmap"},{"name":"x0"},{"name":"y0"},{"name":"x1"},{"name":"y1"},{"name":"x2"},{"name":"y2"},{"name":"x3"},{"name":"y3"},{"name":"col"}],"pyQName":"helpers.image_fill_polygon4"},"helpers.imageRotated":{"kind":-3,"retType":"Bitmap","attributes":{"jsDoc":"Returns an image rotated by 90, 180, 270 deg clockwise"},"parameters":[{"name":"img","type":"Bitmap"},{"name":"deg"}],"pyQName":"helpers.image_rotated"},"Bitmap.__buffer":{"kind":2,"retType":"Buffer","attributes":{"property":"true","jsDoc":"Get underlying buffer"},"isInstance":true},"Bitmap.width":{"kind":2,"retType":"number","attributes":{"property":"true","jsDoc":"Get the width of the bitmap"},"isInstance":true},"Bitmap.height":{"kind":2,"retType":"number","attributes":{"property":"true","jsDoc":"Get the height of the bitmap"},"isInstance":true},"Bitmap.isMono":{"kind":2,"retType":"boolean","attributes":{"property":"true","jsDoc":"True if the bitmap is monochromatic (black and white)"},"isInstance":true,"pyQName":"Bitmap.is_mono"},"Bitmap.copyFrom":{"kind":-1,"attributes":{"jsDoc":"Sets all pixels in the current bitmap from the other bitmap, which has to be of the same size and\nbpp."},"parameters":[{"name":"from","type":"Bitmap"}],"isInstance":true,"pyQName":"Bitmap.copy_from"},"Bitmap.setPixel":{"kind":-1,"attributes":{"jsDoc":"Set pixel color"},"parameters":[{"name":"x"},{"name":"y"},{"name":"c"}],"isInstance":true,"pyQName":"Bitmap.set_pixel"},"Bitmap.getPixel":{"kind":-1,"retType":"number","attributes":{"jsDoc":"Get a pixel color"},"parameters":[{"name":"x"},{"name":"y"}],"isInstance":true,"pyQName":"Bitmap.get_pixel"},"Bitmap.fill":{"kind":-1,"attributes":{"jsDoc":"Fill entire bitmap with a given color"},"parameters":[{"name":"c"}],"isInstance":true},"Bitmap.getRows":{"kind":-1,"attributes":{"jsDoc":"Copy row(s) of pixel from bitmap to buffer (8 bit per pixel)."},"parameters":[{"name":"x"},{"name":"dst","type":"Buffer"}],"isInstance":true,"pyQName":"Bitmap.get_rows"},"Bitmap.setRows":{"kind":-1,"attributes":{"jsDoc":"Copy row(s) of pixel from buffer to bitmap."},"parameters":[{"name":"x"},{"name":"src","type":"Buffer"}],"isInstance":true,"pyQName":"Bitmap.set_rows"},"Bitmap.clone":{"kind":-1,"retType":"Bitmap","attributes":{"jsDoc":"Return a copy of the current bitmap"},"parameters":[],"isInstance":true},"Bitmap.flipX":{"kind":-1,"attributes":{"jsDoc":"Flips (mirrors) pixels horizontally in the current bitmap"},"parameters":[],"isInstance":true,"pyQName":"Bitmap.flip_x"},"Bitmap.flipY":{"kind":-1,"attributes":{"jsDoc":"Flips (mirrors) pixels vertically in the current bitmap"},"parameters":[],"isInstance":true,"pyQName":"Bitmap.flip_y"},"Bitmap.transposed":{"kind":-1,"retType":"Bitmap","attributes":{"jsDoc":"Returns a transposed bitmap (with X/Y swapped)"},"parameters":[],"isInstance":true},"Bitmap.scroll":{"kind":-1,"attributes":{"jsDoc":"Every pixel in bitmap is moved by (dx,dy)"},"parameters":[{"name":"dx"},{"name":"dy"}],"isInstance":true},"Bitmap.doubledX":{"kind":-1,"retType":"Bitmap","attributes":{"jsDoc":"Stretches the bitmap horizontally by 100%"},"parameters":[],"isInstance":true,"pyQName":"Bitmap.doubled_x"},"Bitmap.doubledY":{"kind":-1,"retType":"Bitmap","attributes":{"jsDoc":"Stretches the bitmap vertically by 100%"},"parameters":[],"isInstance":true,"pyQName":"Bitmap.doubled_y"},"Bitmap.replace":{"kind":-1,"attributes":{"jsDoc":"Replaces one color in an bitmap with another"},"parameters":[{"name":"from"},{"name":"to"}],"isInstance":true},"Bitmap.doubled":{"kind":-1,"retType":"Bitmap","attributes":{"jsDoc":"Stretches the bitmap in both directions by 100%"},"parameters":[],"isInstance":true},"Bitmap.drawBitmap":{"kind":-1,"attributes":{"jsDoc":"Draw given bitmap on the current bitmap"},"parameters":[{"name":"from","type":"Bitmap"},{"name":"x"},{"name":"y"}],"isInstance":true,"pyQName":"Bitmap.draw_bitmap"},"Bitmap.drawTransparentBitmap":{"kind":-1,"attributes":{"jsDoc":"Draw given bitmap with transparent background on the current bitmap"},"parameters":[{"name":"from","type":"Bitmap"},{"name":"x"},{"name":"y"}],"isInstance":true,"pyQName":"Bitmap.draw_transparent_bitmap"},"Bitmap.overlapsWith":{"kind":-1,"retType":"boolean","attributes":{"jsDoc":"Check if the current bitmap \"collides\" with another"},"parameters":[{"name":"other","type":"Bitmap"},{"name":"x"},{"name":"y"}],"isInstance":true,"pyQName":"Bitmap.overlaps_with"},"bitmaps.ofBuffer":{"kind":-3,"retType":"Bitmap","attributes":{"jsDoc":"Create new bitmap with given content"},"parameters":[{"name":"buf","type":"Buffer"}],"pyQName":"bitmaps.of_buffer"},"bitmaps.create":{"kind":-3,"retType":"Bitmap","attributes":{"jsDoc":"Create new empty (transparent) bitmap"},"parameters":[{"name":"width"},{"name":"height"}]},"bitmaps.doubledIcon":{"kind":-3,"retType":"Buffer","attributes":{"jsDoc":"Double the size of an icon"},"parameters":[{"name":"icon","type":"Buffer"}],"pyQName":"bitmaps.doubled_icon"}}},"sha":"8a51bf2e03b869284b8420064ead7aec7e6111ae1bdc3b3d79a58fec308ce9f1"},"libs/fonts":{"apis":{"byQName":{}},"sha":"24079e35eaae2cec9375d7d834678c0589c198ab560a461ebd24215f83cdd3a2"},"libs/color":{"apis":{"byQName":{"Colors":{"kind":6,"retType":"Colors","attributes":{"jsDoc":"Well known colors"},"extendsTypes":["Colors","Number"]},"Colors.Red":{"retType":"Colors.Red","attributes":{"block":"red","blockIdentity":"color.wellKnown","_def":{"parts":[{"kind":"label","text":"red","style":[]}],"parameters":[]}},"extendsTypes":["Colors.Red","Number"],"pyQName":"Colors.RED"},"Colors.Orange":{"retType":"Colors.Orange","attributes":{"block":"orange","blockIdentity":"color.wellKnown","_def":{"parts":[{"kind":"label","text":"orange","style":[]}],"parameters":[]}},"extendsTypes":["Colors.Orange","Number"],"pyQName":"Colors.ORANGE"},"Colors.Yellow":{"retType":"Colors.Yellow","attributes":{"block":"yellow","blockIdentity":"color.wellKnown","_def":{"parts":[{"kind":"label","text":"yellow","style":[]}],"parameters":[]}},"extendsTypes":["Colors.Yellow","Number"],"pyQName":"Colors.YELLOW"},"Colors.Green":{"retType":"Colors.Green","attributes":{"block":"green","blockIdentity":"color.wellKnown","_def":{"parts":[{"kind":"label","text":"green","style":[]}],"parameters":[]}},"extendsTypes":["Colors.Green","Number"],"pyQName":"Colors.GREEN"},"Colors.Blue":{"retType":"Colors.Blue","attributes":{"block":"blue","blockIdentity":"color.wellKnown","_def":{"parts":[{"kind":"label","text":"blue","style":[]}],"parameters":[]}},"extendsTypes":["Colors.Blue","Number"],"pyQName":"Colors.BLUE"},"Colors.Indigo":{"retType":"Colors.Indigo","attributes":{"block":"indigo","blockIdentity":"color.wellKnown","_def":{"parts":[{"kind":"label","text":"indigo","style":[]}],"parameters":[]}},"extendsTypes":["Colors.Indigo","Number"],"pyQName":"Colors.INDIGO"},"Colors.Violet":{"retType":"Colors.Violet","attributes":{"block":"violet","blockIdentity":"color.wellKnown","_def":{"parts":[{"kind":"label","text":"violet","style":[]}],"parameters":[]}},"extendsTypes":["Colors.Violet","Number"],"pyQName":"Colors.VIOLET"},"Colors.Purple":{"retType":"Colors.Purple","attributes":{"block":"purple","blockIdentity":"color.wellKnown","_def":{"parts":[{"kind":"label","text":"purple","style":[]}],"parameters":[]}},"extendsTypes":["Colors.Purple","Number"],"pyQName":"Colors.PURPLE"},"Colors.Pink":{"retType":"Colors.Pink","attributes":{"block":"pink","blockIdentity":"color.wellKnown","_def":{"parts":[{"kind":"label","text":"pink","style":[]}],"parameters":[]}},"extendsTypes":["Colors.Pink","Number"],"pyQName":"Colors.PINK"},"Colors.White":{"retType":"Colors.White","attributes":{"block":"white","blockIdentity":"color.wellKnown","_def":{"parts":[{"kind":"label","text":"white","style":[]}],"parameters":[]}},"extendsTypes":["Colors.White","Number"],"pyQName":"Colors.WHITE"},"Colors.Black":{"retType":"Colors.Black","attributes":{"block":"black","blockIdentity":"color.wellKnown","_def":{"parts":[{"kind":"label","text":"black","style":[]}],"parameters":[]}},"extendsTypes":["Colors.Black","Number"],"pyQName":"Colors.BLACK"},"ColorHues":{"kind":6,"retType":"ColorHues","attributes":{"jsDoc":"Well known color hues"},"extendsTypes":["ColorHues","Number"]},"ColorHues.Red":{"retType":"ColorHues.Red","attributes":{"block":"red","_def":{"parts":[{"kind":"label","text":"red","style":[]}],"parameters":[]}},"extendsTypes":["ColorHues.Red","Number"],"pyQName":"ColorHues.RED"},"ColorHues.Orange":{"retType":"ColorHues.Orange","attributes":{"block":"orange","_def":{"parts":[{"kind":"label","text":"orange","style":[]}],"parameters":[]}},"extendsTypes":["ColorHues.Orange","Number"],"pyQName":"ColorHues.ORANGE"},"ColorHues.Yellow":{"retType":"ColorHues.Yellow","attributes":{"block":"yellow","_def":{"parts":[{"kind":"label","text":"yellow","style":[]}],"parameters":[]}},"extendsTypes":["ColorHues.Yellow","Number"],"pyQName":"ColorHues.YELLOW"},"ColorHues.Green":{"retType":"ColorHues.Green","attributes":{"block":"green","_def":{"parts":[{"kind":"label","text":"green","style":[]}],"parameters":[]}},"extendsTypes":["ColorHues.Green","Number"],"pyQName":"ColorHues.GREEN"},"ColorHues.Aqua":{"retType":"ColorHues.Aqua","attributes":{"block":"aqua","_def":{"parts":[{"kind":"label","text":"aqua","style":[]}],"parameters":[]}},"extendsTypes":["ColorHues.Aqua","Number"],"pyQName":"ColorHues.AQUA"},"ColorHues.Blue":{"retType":"ColorHues.Blue","attributes":{"block":"blue","_def":{"parts":[{"kind":"label","text":"blue","style":[]}],"parameters":[]}},"extendsTypes":["ColorHues.Blue","Number"],"pyQName":"ColorHues.BLUE"},"ColorHues.Purple":{"retType":"ColorHues.Purple","attributes":{"block":"purple","_def":{"parts":[{"kind":"label","text":"purple","style":[]}],"parameters":[]}},"extendsTypes":["ColorHues.Purple","Number"],"pyQName":"ColorHues.PURPLE"},"ColorHues.Magenta":{"retType":"ColorHues.Magenta","attributes":{"block":"magenta","_def":{"parts":[{"kind":"label","text":"magenta","style":[]}],"parameters":[]}},"extendsTypes":["ColorHues.Magenta","Number"],"pyQName":"ColorHues.MAGENTA"},"ColorHues.Pink":{"retType":"ColorHues.Pink","attributes":{"block":"pink","_def":{"parts":[{"kind":"label","text":"pink","style":[]}],"parameters":[]}},"extendsTypes":["ColorHues.Pink","Number"],"pyQName":"ColorHues.PINK"},"color":{"kind":5,"retType":"","attributes":{"advanced":true,"jsDoc":"Color manipulation"}},"color.rgb":{"kind":-3,"retType":"number","attributes":{"paramDefl":{"red":"255","green":"255","blue":"255"},"blockId":"colorsrgb","block":"red %red|green %green|blue %blue","paramMin":{"red":"0","green":"0","blue":"0"},"paramMax":{"red":"255","green":"255","blue":"255"},"help":"colors/rgb","weight":19,"blockGap":"8","blockHidden":true,"paramHelp":{"red":"value of the red channel between 0 and 255. eg: 255","green":"value of the green channel between 0 and 255. eg: 255","blue":"value of the blue channel between 0 and 255. eg: 255"},"jsDoc":"Converts red, green, blue channels into a RGB color","_def":{"parts":[{"kind":"label","text":"red ","style":[]},{"kind":"param","name":"red","ref":false},{"kind":"break"},{"kind":"label","text":"green ","style":[]},{"kind":"param","name":"green","ref":false},{"kind":"break"},{"kind":"label","text":"blue ","style":[]},{"kind":"param","name":"blue","ref":false}],"parameters":[{"kind":"param","name":"red","ref":false},{"kind":"param","name":"green","ref":false},{"kind":"param","name":"blue","ref":false}]}},"parameters":[{"name":"red","description":"value of the red channel between 0 and 255. eg: 255","default":"255","options":{"min":{"value":"0"},"max":{"value":"255"}}},{"name":"green","description":"value of the green channel between 0 and 255. eg: 255","default":"255","options":{"min":{"value":"0"},"max":{"value":"255"}}},{"name":"blue","description":"value of the blue channel between 0 and 255. eg: 255","default":"255","options":{"min":{"value":"0"},"max":{"value":"255"}}}]},"color.argb":{"kind":-3,"retType":"number","parameters":[{"name":"alpha"},{"name":"red"},{"name":"green"},{"name":"blue"}]},"color.wellKnown":{"kind":-3,"retType":"number","attributes":{"blockId":"colorscolors","block":"%color","help":"colors/well-known","shim":"TD_ID","weight":20,"blockGap":"8","blockHidden":true,"jsDoc":"Get the RGB value of a known color","_def":{"parts":[{"kind":"param","name":"color","ref":false}],"parameters":[{"kind":"param","name":"color","ref":false}]}},"parameters":[{"name":"color","type":"Colors","isEnum":true}],"pyQName":"color.well_known"},"color.hsv":{"kind":-3,"retType":"number","attributes":{"paramDefl":{"hue":"255","sat":"255","val":"255"},"blockId":"colorshsv","block":"hue %hue|sat %sat|val %val","paramMin":{"hue":"0","sat":"0","val":"0"},"paramMax":{"hue":"255","sat":"255","val":"255"},"help":"colors/hsv","weight":17,"blockHidden":true,"paramHelp":{"hue":"value of the hue channel between 0 and 255. eg: 255","sat":"value of the saturation channel between 0 and 255. eg: 255","val":"value of the value channel between 0 and 255. eg: 255"},"jsDoc":"Convert an HSV (hue, saturation, value) color to RGB","_def":{"parts":[{"kind":"label","text":"hue ","style":[]},{"kind":"param","name":"hue","ref":false},{"kind":"break"},{"kind":"label","text":"sat ","style":[]},{"kind":"param","name":"sat","ref":false},{"kind":"break"},{"kind":"label","text":"val ","style":[]},{"kind":"param","name":"val","ref":false}],"parameters":[{"kind":"param","name":"hue","ref":false},{"kind":"param","name":"sat","ref":false},{"kind":"param","name":"val","ref":false}]}},"parameters":[{"name":"hue","description":"value of the hue channel between 0 and 255. eg: 255","default":"255","options":{"min":{"value":"0"},"max":{"value":"255"}}},{"name":"sat","description":"value of the saturation channel between 0 and 255. eg: 255","initializer":"255","default":"255","options":{"min":{"value":"0"},"max":{"value":"255"}}},{"name":"val","description":"value of the value channel between 0 and 255. eg: 255","initializer":"255","default":"255","options":{"min":{"value":"0"},"max":{"value":"255"}}}]},"color.fade":{"kind":-3,"retType":"number","attributes":{"paramDefl":{"brightness":"128"},"blockId":"colorsfade","block":"fade %color=neopixel_colors|by %brightness","paramMin":{"brightness":"0"},"paramMax":{"brightness":"255"},"help":"light/fade","group":"Color","weight":18,"blockGap":"8","blockHidden":true,"paramHelp":{"color":"color to fade","brightness":"the amount of brightness to apply to the color, eg: 128"},"jsDoc":"Fade the color by the brightness","_def":{"parts":[{"kind":"label","text":"fade ","style":[]},{"kind":"param","name":"color","shadowBlockId":"neopixel_colors","ref":false},{"kind":"break"},{"kind":"label","text":"by ","style":[]},{"kind":"param","name":"brightness","ref":false}],"parameters":[{"kind":"param","name":"color","shadowBlockId":"neopixel_colors","ref":false},{"kind":"param","name":"brightness","ref":false}]}},"parameters":[{"name":"color","description":"color to fade"},{"name":"brightness","description":"the amount of brightness to apply to the color, eg: 128","default":"128","options":{"min":{"value":"0"},"max":{"value":"255"}}}]},"color.blend":{"kind":-3,"retType":"number","parameters":[{"name":"color"},{"name":"alpha"},{"name":"otherColor"}]},"color.gradient":{"kind":-3,"retType":"color.ColorBuffer","parameters":[{"name":"startColor"},{"name":"endColor"},{"name":"steps"}]},"color.unpackR":{"kind":-3,"retType":"number","parameters":[{"name":"rgb"}],"pyQName":"color.unpack_r"},"color.unpackG":{"kind":-3,"retType":"number","parameters":[{"name":"rgb"}],"pyQName":"color.unpack_g"},"color.unpackB":{"kind":-3,"retType":"number","parameters":[{"name":"rgb"}],"pyQName":"color.unpack_b"},"color.parseColor":{"kind":-3,"retType":"number","parameters":[{"name":"color","type":"string"}],"pyQName":"color.parse_color"},"color.ColorBufferLayout":{"kind":6,"retType":"color.ColorBufferLayout","extendsTypes":["color.ColorBufferLayout","Number"]},"color.ColorBufferLayout.RGB":{"retType":"color.ColorBufferLayout.RGB","attributes":{"jsDoc":"24bit RGB color"},"extendsTypes":["color.ColorBufferLayout.RGB","Number"]},"color.ColorBufferLayout.ARGB":{"retType":"color.ColorBufferLayout.ARGB","attributes":{"jsDoc":"32bit RGB color with alpha"},"extendsTypes":["color.ColorBufferLayout.ARGB","Number"]},"color.ColorBuffer":{"kind":8,"retType":"color.ColorBuffer","attributes":{"jsDoc":"A buffer of colors"},"extendsTypes":[]},"color.ColorBuffer.layout":{"kind":2,"retType":"color.ColorBufferLayout","isInstance":true},"color.ColorBuffer.buf":{"kind":2,"retType":"Buffer","isInstance":true},"color.ColorBuffer.__constructor":{"kind":-3,"parameters":[{"name":"length"},{"name":"layout","type":"color.ColorBufferLayout","initializer":"undefined","isEnum":true}],"isInstance":true},"color.ColorBuffer.fromBuffer":{"kind":-1,"retType":"color.ColorBuffer","parameters":[{"name":"buffer","type":"Buffer"},{"name":"layout","type":"color.ColorBufferLayout","isEnum":true}],"pyQName":"color.ColorBuffer.from_buffer"},"color.ColorBuffer.stride":{"kind":-2,"retType":"number","isInstance":true,"isReadOnly":true},"color.ColorBuffer.length":{"kind":-2,"retType":"number","isInstance":true,"isReadOnly":true},"color.ColorBuffer.color":{"kind":-1,"retType":"number","parameters":[{"name":"index"}],"isInstance":true},"color.ColorBuffer.setColor":{"kind":-1,"parameters":[{"name":"index"},{"name":"color"}],"isInstance":true,"pyQName":"color.ColorBuffer.set_color"},"color.ColorBuffer.slice":{"kind":-1,"retType":"color.ColorBuffer","parameters":[{"name":"start","initializer":"undefined"},{"name":"length","initializer":"undefined"}],"isInstance":true},"color.ColorBuffer.write":{"kind":-1,"attributes":{"paramHelp":{"dstOffset":"@param src"},"jsDoc":"Writes the content of the src color buffer starting at the start dstOffset in the current buffer"},"parameters":[{"name":"dstOffset","description":"@param src"},{"name":"src","type":"color.ColorBuffer"}],"isInstance":true},"color.createBuffer":{"kind":-3,"retType":"color.ColorBuffer","attributes":{"jsDoc":"Converts an array of colors into a color buffer"},"parameters":[{"name":"colors","type":"number[]"},{"name":"layout","type":"color.ColorBufferLayout","initializer":"undefined","isEnum":true}],"pyQName":"color.create_buffer"}}},"sha":"b0b942a8f9a879d69da63261343aa79702c8f474f8535857eb384ebcb30479a4"},"libs/audio-recording":{"apis":{"byQName":{"record":{"kind":5,"retType":"","attributes":{"weight":5,"color":"#015f85","icon":"","block":"Record","advanced":false,"jsDoc":"Functions to operate the v2 on-board microphone and speaker.","_def":{"parts":[{"kind":"label","text":"Record","style":[]}],"parameters":[]}}},"record.AudioEvent":{"kind":6,"retType":"record.AudioEvent","extendsTypes":["record.AudioEvent","Number"]},"record.AudioEvent.StartedPlaying":{"retType":"record.AudioEvent.StartedPlaying","attributes":{"block":"starts playing","_def":{"parts":[{"kind":"label","text":"starts playing","style":[]}],"parameters":[]}},"extendsTypes":["record.AudioEvent.StartedPlaying","Number"],"pyQName":"record.AudioEvent.STARTED_PLAYING"},"record.AudioEvent.StoppedPlaying":{"retType":"record.AudioEvent.StoppedPlaying","attributes":{"block":"stops playing","_def":{"parts":[{"kind":"label","text":"stops playing","style":[]}],"parameters":[]}},"extendsTypes":["record.AudioEvent.StoppedPlaying","Number"],"pyQName":"record.AudioEvent.STOPPED_PLAYING"},"record.AudioEvent.StartedRecording":{"retType":"record.AudioEvent.StartedRecording","attributes":{"block":"starts recording","_def":{"parts":[{"kind":"label","text":"starts recording","style":[]}],"parameters":[]}},"extendsTypes":["record.AudioEvent.StartedRecording","Number"],"pyQName":"record.AudioEvent.STARTED_RECORDING"},"record.AudioEvent.StoppedRecording":{"retType":"record.AudioEvent.StoppedRecording","attributes":{"block":"stops recording","_def":{"parts":[{"kind":"label","text":"stops recording","style":[]}],"parameters":[]}},"extendsTypes":["record.AudioEvent.StoppedRecording","Number"],"pyQName":"record.AudioEvent.STOPPED_RECORDING"},"record.AudioLevels":{"kind":6,"retType":"record.AudioLevels","extendsTypes":["record.AudioLevels","Number"]},"record.AudioLevels.Low":{"retType":"record.AudioLevels.Low","attributes":{"block":"low","_def":{"parts":[{"kind":"label","text":"low","style":[]}],"parameters":[]}},"extendsTypes":["record.AudioLevels.Low","Number"],"pyQName":"record.AudioLevels.LOW"},"record.AudioLevels.Medium":{"retType":"record.AudioLevels.Medium","attributes":{"block":"medium","_def":{"parts":[{"kind":"label","text":"medium","style":[]}],"parameters":[]}},"extendsTypes":["record.AudioLevels.Medium","Number"],"pyQName":"record.AudioLevels.MEDIUM"},"record.AudioLevels.High":{"retType":"record.AudioLevels.High","attributes":{"block":"high","_def":{"parts":[{"kind":"label","text":"high","style":[]}],"parameters":[]}},"extendsTypes":["record.AudioLevels.High","Number"],"pyQName":"record.AudioLevels.HIGH"},"record.AudioSampleRateScope":{"kind":6,"retType":"record.AudioSampleRateScope","extendsTypes":["record.AudioSampleRateScope","Number"]},"record.AudioSampleRateScope.Everything":{"retType":"record.AudioSampleRateScope.Everything","attributes":{"block":"everything","_def":{"parts":[{"kind":"label","text":"everything","style":[]}],"parameters":[]}},"extendsTypes":["record.AudioSampleRateScope.Everything","Number"],"pyQName":"record.AudioSampleRateScope.EVERYTHING"},"record.AudioSampleRateScope.Playback":{"retType":"record.AudioSampleRateScope.Playback","attributes":{"block":"playback","_def":{"parts":[{"kind":"label","text":"playback","style":[]}],"parameters":[]}},"extendsTypes":["record.AudioSampleRateScope.Playback","Number"],"pyQName":"record.AudioSampleRateScope.PLAYBACK"},"record.AudioSampleRateScope.Recording":{"retType":"record.AudioSampleRateScope.Recording","attributes":{"block":"recording","_def":{"parts":[{"kind":"label","text":"recording","style":[]}],"parameters":[]}},"extendsTypes":["record.AudioSampleRateScope.Recording","Number"],"pyQName":"record.AudioSampleRateScope.RECORDING"},"record.AudioRecordingMode":{"kind":6,"retType":"record.AudioRecordingMode","extendsTypes":["record.AudioRecordingMode","Number"]},"record.AudioRecordingMode.Stopped":{"retType":"record.AudioRecordingMode.Stopped","attributes":{"block":"stopped","_def":{"parts":[{"kind":"label","text":"stopped","style":[]}],"parameters":[]}},"extendsTypes":["record.AudioRecordingMode.Stopped","Number"],"pyQName":"record.AudioRecordingMode.STOPPED"},"record.AudioRecordingMode.Recording":{"retType":"record.AudioRecordingMode.Recording","attributes":{"block":"recording","_def":{"parts":[{"kind":"label","text":"recording","style":[]}],"parameters":[]}},"extendsTypes":["record.AudioRecordingMode.Recording","Number"],"pyQName":"record.AudioRecordingMode.RECORDING"},"record.AudioRecordingMode.Playing":{"retType":"record.AudioRecordingMode.Playing","attributes":{"block":"playing","_def":{"parts":[{"kind":"label","text":"playing","style":[]}],"parameters":[]}},"extendsTypes":["record.AudioRecordingMode.Playing","Number"],"pyQName":"record.AudioRecordingMode.PLAYING"},"record.AudioStatus":{"kind":6,"retType":"record.AudioStatus","extendsTypes":["record.AudioStatus","Number"]},"record.AudioStatus.Playing":{"retType":"record.AudioStatus.Playing","attributes":{"block":"playing","_def":{"parts":[{"kind":"label","text":"playing","style":[]}],"parameters":[]}},"extendsTypes":["record.AudioStatus.Playing","Number"],"pyQName":"record.AudioStatus.PLAYING"},"record.AudioStatus.Recording":{"retType":"record.AudioStatus.Recording","attributes":{"block":"recording","_def":{"parts":[{"kind":"label","text":"recording","style":[]}],"parameters":[]}},"extendsTypes":["record.AudioStatus.Recording","Number"],"pyQName":"record.AudioStatus.RECORDING"},"record.AudioStatus.Stopped":{"retType":"record.AudioStatus.Stopped","attributes":{"block":"stopped","_def":{"parts":[{"kind":"label","text":"stopped","style":[]}],"parameters":[]}},"extendsTypes":["record.AudioStatus.Stopped","Number"],"pyQName":"record.AudioStatus.STOPPED"},"record.AudioStatus.BufferEmpty":{"retType":"record.AudioStatus.BufferEmpty","attributes":{"block":"empty","_def":{"parts":[{"kind":"label","text":"empty","style":[]}],"parameters":[]}},"extendsTypes":["record.AudioStatus.BufferEmpty","Number"],"pyQName":"record.AudioStatus.BUFFER_EMPTY"},"record.BlockingState":{"kind":6,"retType":"record.BlockingState","extendsTypes":["record.BlockingState","Number"]},"record.BlockingState.Blocking":{"retType":"record.BlockingState.Blocking","attributes":{"block":"until done","_def":{"parts":[{"kind":"label","text":"until done","style":[]}],"parameters":[]}},"extendsTypes":["record.BlockingState.Blocking","Number"],"pyQName":"record.BlockingState.BLOCKING"},"record.BlockingState.Nonblocking":{"retType":"record.BlockingState.Nonblocking","attributes":{"block":"in background","_def":{"parts":[{"kind":"label","text":"in background","style":[]}],"parameters":[]}},"extendsTypes":["record.BlockingState.Nonblocking","Number"],"pyQName":"record.BlockingState.NONBLOCKING"},"record.startRecording":{"kind":-3,"attributes":{"block":"record audio clip $mode","blockId":"record_startRecording","weight":70,"parts":"microphone","help":"record/start-recording","jsDoc":"Record an audio clip for a maximum of 3 seconds","_def":{"parts":[{"kind":"label","text":"record audio clip ","style":[]},{"kind":"param","name":"mode","ref":true}],"parameters":[{"kind":"param","name":"mode","ref":true}]}},"parameters":[{"name":"mode","type":"record.BlockingState","isEnum":true}],"pyQName":"record.start_recording"},"record.playAudio":{"kind":-3,"attributes":{"block":"play audio clip $mode","blockId":"record_playAudio","weight":60,"parts":"microphone","help":"record/play-audio","jsDoc":"Play recorded audio","_def":{"parts":[{"kind":"label","text":"play audio clip ","style":[]},{"kind":"param","name":"mode","ref":true}],"parameters":[{"kind":"param","name":"mode","ref":true}]}},"parameters":[{"name":"mode","type":"record.BlockingState","isEnum":true}],"pyQName":"record.play_audio"},"record.stopRecording":{"kind":-3,"parameters":[],"pyQName":"record.stop_recording"},"record.eraseRecording":{"kind":-3,"parameters":[],"pyQName":"record.erase_recording"},"record.audioStatus":{"kind":-3,"retType":"boolean","attributes":{"block":"audio is $status","blockId":"record_audioStatus","parts":"microphone","help":"record/audio-status","jsDoc":"Test what the audio is doing","_def":{"parts":[{"kind":"label","text":"audio is ","style":[]},{"kind":"param","name":"status","ref":true}],"parameters":[{"kind":"param","name":"status","ref":true}]}},"parameters":[{"name":"status","type":"record.AudioStatus","isEnum":true}],"pyQName":"record.audio_status"},"record.setMicGain":{"kind":-3,"attributes":{"block":"set microphone sensitivity to $gain","blockId":"record_setMicGain","parts":"microphone","weight":30,"help":"record/set-mic-gain","jsDoc":"Change how sensitive the microphone is. This changes the recording quality!","_def":{"parts":[{"kind":"label","text":"set microphone sensitivity to ","style":[]},{"kind":"param","name":"gain","ref":true}],"parameters":[{"kind":"param","name":"gain","ref":true}]}},"parameters":[{"name":"gain","type":"record.AudioLevels","isEnum":true}],"pyQName":"record.set_mic_gain"},"record.setSampleRate":{"kind":-3,"attributes":{"paramDefl":{"hz":"11000"},"block":"set sample rate to $hz || for $scope","blockId":"record_setSampleRate","paramMin":{"hz":"1000"},"paramMax":{"hz":"22000"},"explicitDefaults":["hz"],"expandableArgumentMode":"enabled","parts":"microphone","weight":40,"help":"record/set-sample-rate","jsDoc":"Set the sample frequency for recording, playback, or both (default)\n* @param hz The sample frequency, in Hz","_def":{"parts":[{"kind":"label","text":"set sample rate to ","style":[]},{"kind":"param","name":"hz","ref":true},{"kind":"label","text":" ","style":[]}],"parameters":[{"kind":"param","name":"hz","ref":true}]},"_expandedDef":{"parts":[{"kind":"label","text":" for ","style":[]},{"kind":"param","name":"scope","ref":true}],"parameters":[{"kind":"param","name":"scope","ref":true}]}},"parameters":[{"name":"hz","initializer":"11000","default":"11000","options":{"min":{"value":"1000"},"max":{"value":"22000"}}},{"name":"scope","type":"record.AudioSampleRateScope","initializer":"undefined","isEnum":true}],"pyQName":"record.set_sample_rate"},"record.record":{"kind":-3,"attributes":{"callingConvention":2,"promise":"true","jsDoc":"Record an audio clip"},"parameters":[]},"record.play":{"kind":-3,"attributes":{"jsDoc":"Play the audio clip that is saved in the buffer"},"parameters":[]},"record.stop":{"kind":-3,"attributes":{"jsDoc":"Stop recording"},"parameters":[]},"record.erase":{"kind":-3,"attributes":{"jsDoc":"Clear the buffer"},"parameters":[]},"record.setMicrophoneGain":{"kind":-3,"attributes":{"jsDoc":"Set sensitity of the microphone input"},"parameters":[{"name":"gain"}],"pyQName":"record.set_microphone_gain"},"record.audioDuration":{"kind":-3,"retType":"number","attributes":{"jsDoc":"Get how long the recorded audio clip is"},"parameters":[{"name":"sampleRate"}],"pyQName":"record.audio_duration"},"record.audioIsPlaying":{"kind":-3,"retType":"boolean","attributes":{"jsDoc":"Get whether the playback is active"},"parameters":[],"pyQName":"record.audio_is_playing"},"record.audioIsRecording":{"kind":-3,"retType":"boolean","attributes":{"jsDoc":"Get whether the microphone is listening"},"parameters":[],"pyQName":"record.audio_is_recording"},"record.audioIsStopped":{"kind":-3,"retType":"boolean","attributes":{"jsDoc":"Get whether the board is recording or playing back"},"parameters":[],"pyQName":"record.audio_is_stopped"},"record.setInputSampleRate":{"kind":-3,"attributes":{"jsDoc":"Change the sample rate of the splitter channel (audio input)"},"parameters":[{"name":"sampleRate"}],"pyQName":"record.set_input_sample_rate"},"record.setOutputSampleRate":{"kind":-3,"attributes":{"jsDoc":"Change the sample rate of the mixer channel (audio output)"},"parameters":[{"name":"sampleRate"}],"pyQName":"record.set_output_sample_rate"},"record.setBothSamples":{"kind":-3,"attributes":{"jsDoc":"Set the sample rate for both input and output"},"parameters":[{"name":"sampleRate"}],"pyQName":"record.set_both_samples"}}},"sha":"ec7e1610f430eabd6ef77938c66a0391a2e88be187c3ee063b6759b32d62cd33"},"libs/blocksprj":{"apis":{"byQName":{"input":{"kind":5,"retType":"","attributes":{"color":"#D400D4","weight":111,"icon":"","jsDoc":"Events and data from sensors"}},"DetectedSound":{"kind":6,"retType":"DetectedSound","extendsTypes":["DetectedSound","Number"]},"DetectedSound.Loud":{"retType":"DetectedSound.Loud","attributes":{"block":"loud","_def":{"parts":[{"kind":"label","text":"loud","style":[]}],"parameters":[]}},"extendsTypes":["DetectedSound.Loud","Number"],"pyQName":"DetectedSound.LOUD"},"DetectedSound.Quiet":{"retType":"DetectedSound.Quiet","attributes":{"block":"quiet","_def":{"parts":[{"kind":"label","text":"quiet","style":[]}],"parameters":[]}},"extendsTypes":["DetectedSound.Quiet","Number"],"pyQName":"DetectedSound.QUIET"},"SoundThreshold":{"kind":6,"retType":"SoundThreshold","extendsTypes":["SoundThreshold","Number"]},"SoundThreshold.Loud":{"retType":"SoundThreshold.Loud","attributes":{"block":"loud","_def":{"parts":[{"kind":"label","text":"loud","style":[]}],"parameters":[]}},"extendsTypes":["SoundThreshold.Loud","Number"],"pyQName":"SoundThreshold.LOUD"},"SoundThreshold.Quiet":{"retType":"SoundThreshold.Quiet","attributes":{"block":"quiet","_def":{"parts":[{"kind":"label","text":"quiet","style":[]}],"parameters":[]}},"extendsTypes":["SoundThreshold.Quiet","Number"],"pyQName":"SoundThreshold.QUIET"},"input.onSound":{"kind":-3,"attributes":{"help":"input/on-sound","blockId":"input_on_sound","block":"on %sound sound","parts":"microphone","weight":88,"blockGap":"12","group":"micro:bit (V2)","jsDoc":"Registers an event that runs when a sound is detected","_def":{"parts":[{"kind":"label","text":"on ","style":[]},{"kind":"param","name":"sound","ref":false},{"kind":"label","text":" sound","style":[]}],"parameters":[{"kind":"param","name":"sound","ref":false}]}},"parameters":[{"name":"sound","type":"DetectedSound","isEnum":true},{"name":"handler","type":"() => void","handlerParameters":[]}],"pyQName":"input.on_sound"},"input.soundLevel":{"kind":-3,"retType":"number","attributes":{"help":"input/sound-level","blockId":"device_get_sound_level","block":"sound level","parts":"microphone","weight":34,"blockGap":"8","group":"micro:bit (V2)","jsDoc":"Reads the loudness through the microphone from 0 (silent) to 255 (loud)","_def":{"parts":[{"kind":"label","text":"sound level","style":[]}],"parameters":[]}},"parameters":[],"pyQName":"input.sound_level"},"input.setSoundThreshold":{"kind":-3,"attributes":{"paramDefl":{"threshold":"128"},"help":"input/set-sound-threshold","blockId":"input_set_sound_threshold","block":"set %sound sound threshold to %value","parts":"microphone","paramMin":{"threshold":"0"},"paramMax":{"threshold":"255"},"weight":14,"blockGap":"8","advanced":true,"group":"micro:bit (V2)","explicitDefaults":["threshold"],"jsDoc":"Sets the threshold for a sound type.","_def":{"parts":[{"kind":"label","text":"set ","style":[]},{"kind":"param","name":"sound","ref":false},{"kind":"label","text":" sound threshold to ","style":[]},{"kind":"param","name":"value","ref":false}],"parameters":[{"kind":"param","name":"sound","ref":false},{"kind":"param","name":"value","ref":false}]}},"parameters":[{"name":"sound","type":"SoundThreshold","isEnum":true},{"name":"threshold","initializer":"128","default":"128","options":{"min":{"value":"0"},"max":{"value":"255"}}}],"pyQName":"input.set_sound_threshold"},"radio":{"kind":5,"retType":"","attributes":{"color":"#E3008C","weight":96,"icon":"","groups":["Group","Broadcast","Send","Receive"],"jsDoc":"Communicate data using radio packets"}},"radio.off":{"kind":-3,"attributes":{"help":"radio/off","jsDoc":"Disables the radio for use as a multipoint sender/receiver.\nDisabling radio will help conserve battery power when it is not in use."},"parameters":[]},"radio.on":{"kind":-3,"attributes":{"help":"radio/on","jsDoc":"Initialises the radio for use as a multipoint sender/receiver\nOnly useful when the radio.off() is used beforehand."},"parameters":[]},"radio.raiseEvent":{"kind":-3,"attributes":{"blockId":"radioRaiseEvent","block":"radio raise event|from source %src=control_event_source_id|with value %value=control_event_value_id","blockExternalInputs":"1","advanced":true,"weight":1,"help":"radio/raise-event","inlineInputMode":"external","jsDoc":"Sends an event over radio to neigboring devices","_def":{"parts":[{"kind":"label","text":"radio raise event","style":[]},{"kind":"break"},{"kind":"label","text":"from source ","style":[]},{"kind":"param","name":"src","shadowBlockId":"control_event_source_id","ref":false},{"kind":"break"},{"kind":"label","text":"with value ","style":[]},{"kind":"param","name":"value","shadowBlockId":"control_event_value_id","ref":false}],"parameters":[{"kind":"param","name":"src","shadowBlockId":"control_event_source_id","ref":false},{"kind":"param","name":"value","shadowBlockId":"control_event_value_id","ref":false}]}},"parameters":[{"name":"src"},{"name":"value"}],"pyQName":"radio.raise_event"},"radio.readRawPacket":{"kind":-3,"retType":"Buffer","attributes":{"jsDoc":"Internal use only. Takes the next packet from the radio queue and returns its contents + RSSI in a Buffer.\n@returns NULL if no packet available"},"parameters":[],"pyQName":"radio.read_raw_packet"},"radio.sendRawPacket":{"kind":-3,"attributes":{"callingConvention":1,"async":"true","jsDoc":"Internal use only. Sends a raw packet through the radio (assumes RSSI appened to packet)"},"parameters":[{"name":"msg","type":"Buffer"}],"pyQName":"radio.send_raw_packet"},"radio.onDataReceived":{"kind":-3,"attributes":{"help":"radio/on-data-received","weight":0,"blockId":"radio_datagram_received_event","block":"radio on data received","blockGap":"8","deprecated":"true","blockHidden":true,"jsDoc":"Used internally by the library.","_def":{"parts":[{"kind":"label","text":"radio on data received","style":[]}],"parameters":[]}},"parameters":[{"name":"body","type":"() => void","handlerParameters":[]}],"pyQName":"radio.on_data_received"},"radio.setGroup":{"kind":-3,"attributes":{"paramDefl":{"id":"1"},"help":"radio/set-group","weight":100,"blockId":"radio_set_group","block":"radio set group %ID","paramMin":{"id":"0"},"paramMax":{"id":"255"},"group":"Group","paramHelp":{"id":"the group id between ``0`` and ``255``, eg: 1"},"jsDoc":"Sets the group id for radio communications. A micro:bit can only listen to one group ID at any time.","_def":{"parts":[{"kind":"label","text":"radio set group ","style":[]},{"kind":"param","name":"ID","ref":false}],"parameters":[{"kind":"param","name":"ID","ref":false}]}},"parameters":[{"name":"id","description":"the group id between ``0`` and ``255``, eg: 1","default":"1","options":{"min":{"value":"0"},"max":{"value":"255"}}}],"pyQName":"radio.set_group"},"radio.setTransmitPower":{"kind":-3,"attributes":{"paramDefl":{"power":"7"},"help":"radio/set-transmit-power","weight":9,"blockGap":"8","blockId":"radio_set_transmit_power","block":"radio set transmit power %power","paramMin":{"power":"0"},"paramMax":{"power":"7"},"advanced":true,"paramHelp":{"power":"a value in the range 0..7, where 0 is the lowest power and 7 is the highest. eg: 7"},"jsDoc":"Change the output power level of the transmitter to the given value.","_def":{"parts":[{"kind":"label","text":"radio set transmit power ","style":[]},{"kind":"param","name":"power","ref":false}],"parameters":[{"kind":"param","name":"power","ref":false}]}},"parameters":[{"name":"power","description":"a value in the range 0..7, where 0 is the lowest power and 7 is the highest. eg: 7","default":"7","options":{"min":{"value":"0"},"max":{"value":"7"}}}],"pyQName":"radio.set_transmit_power"},"radio.setFrequencyBand":{"kind":-3,"attributes":{"help":"radio/set-frequency-band","weight":8,"blockGap":"8","blockId":"radio_set_frequency_band","block":"radio set frequency band %band","paramMin":{"band":"0"},"paramMax":{"band":"83"},"advanced":true,"paramHelp":{"band":"a frequency band in the range 0 - 83. Each step is 1MHz wide, based at 2400MHz."},"jsDoc":"Change the transmission and reception band of the radio to the given channel","_def":{"parts":[{"kind":"label","text":"radio set frequency band ","style":[]},{"kind":"param","name":"band","ref":false}],"parameters":[{"kind":"param","name":"band","ref":false}]}},"parameters":[{"name":"band","description":"a frequency band in the range 0 - 83. Each step is 1MHz wide, based at 2400MHz.","options":{"min":{"value":"0"},"max":{"value":"83"}}}],"pyQName":"radio.set_frequency_band"},"RadioPacketProperty":{"kind":6,"retType":"RadioPacketProperty","extendsTypes":["RadioPacketProperty","Number"]},"RadioPacketProperty.SignalStrength":{"retType":"RadioPacketProperty.SignalStrength","attributes":{"blockIdentity":"radio._packetProperty","block":"signal strength","_def":{"parts":[{"kind":"label","text":"signal strength","style":[]}],"parameters":[]}},"extendsTypes":["RadioPacketProperty.SignalStrength","Number"],"pyQName":"RadioPacketProperty.SIGNAL_STRENGTH"},"RadioPacketProperty.Time":{"retType":"RadioPacketProperty.Time","attributes":{"blockIdentity":"radio._packetProperty","block":"time","_def":{"parts":[{"kind":"label","text":"time","style":[]}],"parameters":[]}},"extendsTypes":["RadioPacketProperty.Time","Number"],"pyQName":"RadioPacketProperty.TIME"},"RadioPacketProperty.SerialNumber":{"retType":"RadioPacketProperty.SerialNumber","attributes":{"block":"serial number","blockIdentity":"radio._packetProperty","_def":{"parts":[{"kind":"label","text":"serial number","style":[]}],"parameters":[]}},"extendsTypes":["RadioPacketProperty.SerialNumber","Number"],"pyQName":"RadioPacketProperty.SERIAL_NUMBER"},"radio.PACKET_TYPE_NUMBER":{"kind":4,"retType":"number"},"radio.PACKET_TYPE_VALUE":{"kind":4,"retType":"number"},"radio.PACKET_TYPE_STRING":{"kind":4,"retType":"number"},"radio.PACKET_TYPE_BUFFER":{"kind":4,"retType":"number"},"radio.PACKET_TYPE_DOUBLE":{"kind":4,"retType":"number"},"radio.PACKET_TYPE_DOUBLE_VALUE":{"kind":4,"retType":"number"},"radio.lastPacket":{"kind":4,"retType":"radio.RadioPacket","pyQName":"radio.last_packet"},"radio.onReceivedNumber":{"kind":-3,"attributes":{"help":"radio/on-received-number","blockId":"radio_on_number_drag","block":"on radio received","blockGap":"16","useLoc":"radio.onDataPacketReceived","draggableParameters":"reporter","group":"Receive","weight":20,"jsDoc":"Registers code to run when the radio receives a number.","_def":{"parts":[{"kind":"label","text":"on radio received","style":[]}],"parameters":[]}},"parameters":[{"name":"cb","type":"(receivedNumber: number) => void","handlerParameters":[{"name":"receivedNumber","type":"number"}]}],"pyQName":"radio.on_received_number"},"radio.onReceivedValue":{"kind":-3,"attributes":{"help":"radio/on-received-value","blockId":"radio_on_value_drag","block":"on radio received","blockGap":"16","useLoc":"radio.onDataPacketReceived","draggableParameters":"reporter","group":"Receive","weight":19,"jsDoc":"Registers code to run when the radio receives a key value pair.","_def":{"parts":[{"kind":"label","text":"on radio received","style":[]}],"parameters":[]}},"parameters":[{"name":"cb","type":"(name: string, value: number) => void","handlerParameters":[{"name":"name","type":"string"},{"name":"value","type":"number"}]}],"pyQName":"radio.on_received_value"},"radio.onReceivedString":{"kind":-3,"attributes":{"help":"radio/on-received-string","blockId":"radio_on_string_drag","block":"on radio received","blockGap":"16","useLoc":"radio.onDataPacketReceived","draggableParameters":"reporter","group":"Receive","weight":18,"jsDoc":"Registers code to run when the radio receives a string.","_def":{"parts":[{"kind":"label","text":"on radio received","style":[]}],"parameters":[]}},"parameters":[{"name":"cb","type":"(receivedString: string) => void","handlerParameters":[{"name":"receivedString","type":"string"}]}],"pyQName":"radio.on_received_string"},"radio.onReceivedBuffer":{"kind":-3,"attributes":{"help":"radio/on-received-buffer","blockHidden":true,"blockId":"radio_on_buffer_drag","block":"on radio received","blockGap":"16","useLoc":"radio.onDataPacketReceived","draggableParameters":"reporter","jsDoc":"Registers code to run when the radio receives a buffer.","_def":{"parts":[{"kind":"label","text":"on radio received","style":[]}],"parameters":[]}},"parameters":[{"name":"cb","type":"(receivedBuffer: Buffer) => void","handlerParameters":[{"name":"receivedBuffer","type":"Buffer"}]}],"pyQName":"radio.on_received_buffer"},"radio.receivedPacket":{"kind":-3,"retType":"number","attributes":{"help":"radio/received-packet","blockGap":"16","blockId":"radio_received_packet","block":"received packet %type=radio_packet_property","group":"Receive","weight":16,"paramHelp":{"type":"the type of property to retrieve from the last packet"},"jsDoc":"Returns properties of the last radio packet received.","_def":{"parts":[{"kind":"label","text":"received packet ","style":[]},{"kind":"param","name":"type","shadowBlockId":"radio_packet_property","ref":false}],"parameters":[{"kind":"param","name":"type","shadowBlockId":"radio_packet_property","ref":false}]}},"parameters":[{"name":"type","description":"the type of property to retrieve from the last packet"}],"pyQName":"radio.received_packet"},"radio._packetProperty":{"kind":-3,"retType":"number","attributes":{"paramDefl":{"type":"PacketProperty.time"},"blockId":"radio_packet_property","block":"%note","shim":"TD_ID","blockHidden":true,"paramHelp":{"type":"the packet property type, eg: PacketProperty.time"},"jsDoc":"Gets a packet property.","_def":{"parts":[{"kind":"param","name":"note","ref":false}],"parameters":[{"kind":"param","name":"note","ref":false}]}},"parameters":[{"name":"type","description":"the packet property type, eg: PacketProperty.time","type":"RadioPacketProperty","default":"PacketProperty.time","isEnum":true}],"pyQName":"radio._packet_property"},"radio.RadioPacket":{"kind":8,"retType":"radio.RadioPacket","extendsTypes":[]},"radio.RadioPacket.getPacket":{"kind":-1,"retType":"radio.RadioPacket","parameters":[{"name":"data","type":"Buffer"}],"pyQName":"radio.RadioPacket.get_packet"},"radio.RadioPacket.mkPacket":{"kind":-1,"retType":"radio.RadioPacket","parameters":[{"name":"packetType"}],"pyQName":"radio.RadioPacket.mk_packet"},"radio.RadioPacket.signal":{"kind":-2,"retType":"number","isInstance":true,"isReadOnly":true},"radio.RadioPacket.packetType":{"kind":-2,"retType":"number","isInstance":true,"isReadOnly":true,"pyQName":"radio.RadioPacket.packet_type"},"radio.RadioPacket.time":{"kind":-2,"retType":"number","isInstance":true,"isReadOnly":true},"radio.RadioPacket.time@set":{"kind":-2,"retType":"number","isInstance":true},"radio.RadioPacket.serial":{"kind":-2,"retType":"number","isInstance":true,"isReadOnly":true},"radio.RadioPacket.serial@set":{"kind":-2,"retType":"number","isInstance":true},"radio.RadioPacket.stringPayload":{"kind":-2,"retType":"string","isInstance":true,"isReadOnly":true,"pyQName":"radio.RadioPacket.string_payload"},"radio.RadioPacket.stringPayload@set":{"kind":-2,"retType":"string","isInstance":true,"pyQName":"radio.RadioPacket.string_payload@set"},"radio.RadioPacket.numberPayload":{"kind":-2,"retType":"number","isInstance":true,"isReadOnly":true,"pyQName":"radio.RadioPacket.number_payload"},"radio.RadioPacket.numberPayload@set":{"kind":-2,"retType":"number","isInstance":true,"pyQName":"radio.RadioPacket.number_payload@set"},"radio.RadioPacket.bufferPayload":{"kind":-2,"retType":"Buffer","isInstance":true,"isReadOnly":true,"pyQName":"radio.RadioPacket.buffer_payload"},"radio.RadioPacket.bufferPayload@set":{"kind":-2,"retType":"Buffer","isInstance":true,"pyQName":"radio.RadioPacket.buffer_payload@set"},"radio.RadioPacket.hasString":{"kind":-1,"retType":"boolean","parameters":[],"isInstance":true,"pyQName":"radio.RadioPacket.has_string"},"radio.RadioPacket.hasNumber":{"kind":-1,"retType":"boolean","parameters":[],"isInstance":true,"pyQName":"radio.RadioPacket.has_number"},"radio.sendNumber":{"kind":-3,"attributes":{"help":"radio/send-number","weight":60,"blockId":"radio_datagram_send","block":"radio send number %value","blockGap":"8","group":"Send","jsDoc":"Broadcasts a number over radio to any connected micro:bit in the group.","_def":{"parts":[{"kind":"label","text":"radio send number ","style":[]},{"kind":"param","name":"value","ref":false}],"parameters":[{"kind":"param","name":"value","ref":false}]}},"parameters":[{"name":"value"}],"pyQName":"radio.send_number"},"radio.sendValue":{"kind":-3,"attributes":{"paramDefl":{"name":"name"},"help":"radio/send-value","weight":59,"blockId":"radio_datagram_send_value","block":"radio send|value %name|= %value","blockGap":"8","group":"Send","paramHelp":{"name":"the field name (max 8 characters), eg: \"name\"","value":"the numeric value"},"jsDoc":"Broadcasts a name / value pair along with the device serial number\nand running time to any connected micro:bit in the group. The name can\ninclude no more than 8 characters.","_def":{"parts":[{"kind":"label","text":"radio send","style":[]},{"kind":"break"},{"kind":"label","text":"value ","style":[]},{"kind":"param","name":"name","ref":false},{"kind":"break"},{"kind":"label","text":"= ","style":[]},{"kind":"param","name":"value","ref":false}],"parameters":[{"kind":"param","name":"name","ref":false},{"kind":"param","name":"value","ref":false}]}},"parameters":[{"name":"name","description":"the field name (max 8 characters), eg: \"name\"","type":"string","default":"name"},{"name":"value","description":"the numeric value"}],"pyQName":"radio.send_value"},"radio.sendString":{"kind":-3,"attributes":{"help":"radio/send-string","weight":58,"blockId":"radio_datagram_send_string","block":"radio send string %msg","paramShadowOptions":{"msg":{"toString":"true"}},"group":"Send","jsDoc":"Broadcasts a string along with the device serial number\nand running time to any connected micro:bit in the group.","_def":{"parts":[{"kind":"label","text":"radio send string ","style":[]},{"kind":"param","name":"msg","ref":false}],"parameters":[{"kind":"param","name":"msg","ref":false}]}},"parameters":[{"name":"value","type":"string","options":{"fieldEditorOptions":{"value":{"toString":"true"}}}}],"pyQName":"radio.send_string"},"radio.sendBuffer":{"kind":-3,"attributes":{"help":"radio/send-buffer","weight":57,"advanced":true,"jsDoc":"Broadcasts a buffer (up to 19 bytes long) along with the device serial number\nand running time to any connected micro:bit in the group."},"parameters":[{"name":"msg","type":"Buffer"}],"pyQName":"radio.send_buffer"},"radio.setTransmitSerialNumber":{"kind":-3,"attributes":{"paramDefl":{"transmit":"true"},"help":"radio/set-transmit-serial-number","weight":8,"blockGap":"8","blockId":"radio_set_transmit_serial_number","block":"radio set transmit serial number %transmit","advanced":true,"paramHelp":{"transmit":"value indicating if the serial number is transmitted, eg: true"},"jsDoc":"Set the radio to transmit the serial number in each message.","_def":{"parts":[{"kind":"label","text":"radio set transmit serial number ","style":[]},{"kind":"param","name":"transmit","ref":false}],"parameters":[{"kind":"param","name":"transmit","ref":false}]}},"parameters":[{"name":"transmit","description":"value indicating if the serial number is transmitted, eg: true","type":"boolean","default":"true"}],"pyQName":"radio.set_transmit_serial_number"},"radio.Packet":{"kind":8,"retType":"radio.Packet","extendsTypes":[]},"radio.Packet.receivedNumber":{"kind":2,"retType":"number","attributes":{"jsDoc":"The number payload if a number was sent in this packet (via ``sendNumber()`` or ``sendValue()``)\nor 0 if this packet did not contain a number."},"isInstance":true,"pyQName":"radio.Packet.received_number"},"radio.Packet.receivedString":{"kind":2,"retType":"string","attributes":{"jsDoc":"The string payload if a string was sent in this packet (via ``sendString()`` or ``sendValue()``)\nor the empty string if this packet did not contain a string."},"isInstance":true,"pyQName":"radio.Packet.received_string"},"radio.Packet.receivedBuffer":{"kind":2,"retType":"Buffer","attributes":{"jsDoc":"The buffer payload if a buffer was sent in this packet\nor the empty buffer"},"isInstance":true,"pyQName":"radio.Packet.received_buffer"},"radio.Packet.time":{"kind":2,"retType":"number","attributes":{"jsDoc":"The system time of the sender of the packet at the time the packet was sent."},"isInstance":true},"radio.Packet.serial":{"kind":2,"retType":"number","attributes":{"jsDoc":"The serial number of the sender of the packet or 0 if the sender did not sent their serial number."},"isInstance":true},"radio.Packet.signal":{"kind":2,"retType":"number","attributes":{"jsDoc":"The received signal strength indicator (RSSI) of the packet."},"isInstance":true},"radio.onDataPacketReceived":{"kind":-3,"attributes":{"help":"radio/on-data-packet-received","blockHandlerKey":"radioreceived","deprecated":"true","mutate":"objectdestructuring","mutateText":"Packet","mutateDefaults":"receivedNumber;receivedString:name,receivedNumber:value;receivedString","blockId":"radio_on_packet","block":"on radio received","blockGap":"8","jsDoc":"Deprecated. Use onDataReceived() instead\nRegisters code to run when the radio receives a packet. Also takes the\nreceived packet from the radio queue.","_def":{"parts":[{"kind":"label","text":"on radio received","style":[]}],"parameters":[]}},"parameters":[{"name":"cb","type":"(packet: radio.Packet) => void"}],"pyQName":"radio.on_data_packet_received"},"radio.onReceivedNumberDeprecated":{"kind":-3,"attributes":{"help":"radio/on-received-number","blockHandlerKey":"radioreceived","blockId":"radio_on_number","block":"on radio received","blockGap":"16","useLoc":"radio.onDataPacketReceived","deprecated":"1","jsDoc":"Registers code to run when the radio receives a number. Deprecated, use\nonReceivedNumber instead.","_def":{"parts":[{"kind":"label","text":"on radio received","style":[]}],"parameters":[]}},"parameters":[{"name":"cb","type":"(receivedNumber: number) => void","handlerParameters":[{"name":"receivedNumber","type":"number"}]}],"pyQName":"radio.on_received_number_deprecated"},"radio.onReceivedValueDeprecated":{"kind":-3,"attributes":{"help":"radio/on-received-value","blockHandlerKey":"radioreceived","blockId":"radio_on_value","block":"on radio received","blockGap":"16","useLoc":"radio.onDataPacketReceived","deprecated":"1","jsDoc":"Registers code to run when the radio receives a key value pair. Deprecated, use\nonReceivedValue instead.","_def":{"parts":[{"kind":"label","text":"on radio received","style":[]}],"parameters":[]}},"parameters":[{"name":"cb","type":"(name: string, value: number) => void","handlerParameters":[{"name":"name","type":"string"},{"name":"value","type":"number"}]}],"pyQName":"radio.on_received_value_deprecated"},"radio.onReceivedStringDeprecated":{"kind":-3,"attributes":{"help":"radio/on-received-string","blockHandlerKey":"radioreceived","blockId":"radio_on_string","block":"on radio received","blockGap":"16","useLoc":"radio.onDataPacketReceived","deprecated":"1","jsDoc":"Registers code to run when the radio receives a string. Deprecated, use\nonReceivedString instead.","_def":{"parts":[{"kind":"label","text":"on radio received","style":[]}],"parameters":[]}},"parameters":[{"name":"cb","type":"(receivedString: string) => void","handlerParameters":[{"name":"receivedString","type":"string"}]}],"pyQName":"radio.on_received_string_deprecated"},"radio.onReceivedBufferDeprecated":{"kind":-3,"attributes":{"help":"radio/on-received-buffer","blockHandlerKey":"radioreceived","blockHidden":true,"blockId":"radio_on_buffer","block":"on radio received","blockGap":"16","useLoc":"radio.onDataPacketReceived","deprecated":"1","jsDoc":"Registers code to run when the radio receives a buffer. Deprecated, use\nonReceivedBuffer instead.","_def":{"parts":[{"kind":"label","text":"on radio received","style":[]}],"parameters":[]}},"parameters":[{"name":"cb","type":"(receivedBuffer: Buffer) => void","handlerParameters":[{"name":"receivedBuffer","type":"Buffer"}]}],"pyQName":"radio.on_received_buffer_deprecated"},"radio.receivedNumber":{"kind":-3,"retType":"number","attributes":{"help":"radio/received-number","deprecated":"1","jsDoc":"Returns the number payload from the last packet taken from the radio queue\n(via ``receiveNumber``, ``receiveString``, etc) or 0 if that packet did not\ncontain a number."},"parameters":[],"pyQName":"radio.received_number"},"radio.receivedSerial":{"kind":-3,"retType":"number","attributes":{"help":"radio/received-serial","deprecated":"1","jsDoc":"Returns the serial number of the sender micro:bit from the last packet taken\nfrom the radio queue (via ``receiveNumber``, ``receiveString``, etc) or 0 if\nthat packet did not send a serial number."},"parameters":[],"pyQName":"radio.received_serial"},"radio.receivedString":{"kind":-3,"retType":"string","attributes":{"help":"radio/received-string","deprecated":"1","jsDoc":"Returns the string payload from the last packet taken from the radio queue\n(via ``receiveNumber``, ``receiveString``, etc) or the empty string if that\npacket did not contain a string."},"parameters":[],"pyQName":"radio.received_string"},"radio.receivedBuffer":{"kind":-3,"retType":"Buffer","attributes":{"help":"radio/received-buffer","deprecated":"1","jsDoc":"Returns the buffer payload from the last packet taken from the radio queue\n(via ``receiveNumber``, ``receiveString``, etc) or the empty string if that\npacket did not contain a string."},"parameters":[],"pyQName":"radio.received_buffer"},"radio.receivedTime":{"kind":-3,"retType":"number","attributes":{"help":"radio/received-time","deprecated":"1","jsDoc":"Returns the system time of the sender micro:bit at the moment when it sent the\nlast packet taken from the radio queue (via ``receiveNumber``,\n``receiveString``, etc)."},"parameters":[],"pyQName":"radio.received_time"},"radio.receiveNumber":{"kind":-3,"retType":"number","attributes":{"help":"radio/receive-number","weight":46,"blockId":"radio_datagram_receive","block":"radio receive number","blockGap":"8","deprecated":"true","jsDoc":"Reads the next packet from the radio queue and returns the packet's number\npayload or 0 if the packet did not contain a number.","_def":{"parts":[{"kind":"label","text":"radio receive number","style":[]}],"parameters":[]}},"parameters":[],"pyQName":"radio.receive_number"},"radio.receiveString":{"kind":-3,"retType":"string","attributes":{"blockId":"radio_datagram_receive_string","block":"radio receive string","blockGap":"8","weight":44,"help":"radio/receive-string","deprecated":"true","jsDoc":"Reads the next packet from the radio queue and returns the packet's string\npayload or the empty string if the packet did not contain a string.","_def":{"parts":[{"kind":"label","text":"radio receive string","style":[]}],"parameters":[]}},"parameters":[],"pyQName":"radio.receive_string"},"radio.receivedSignalStrength":{"kind":-3,"retType":"number","attributes":{"help":"radio/received-signal-strength","weight":40,"blockId":"radio_datagram_rssi","block":"radio received signal strength","deprecated":"true","blockHidden":true,"jsDoc":"Gets the received signal strength indicator (RSSI) from the last packet taken\nfrom the radio queue (via ``receiveNumber``, ``receiveString``, etc). Not supported in simulator.","_def":{"parts":[{"kind":"label","text":"radio received signal strength","style":[]}],"parameters":[]}},"parameters":[],"pyQName":"radio.received_signal_strength"},"radio.writeValueToSerial":{"kind":-3,"attributes":{"help":"radio/write-value-to-serial","weight":3,"blockId":"radio_write_value_serial","block":"radio write value to serial","deprecated":"true","jsDoc":"Reads the next packet from the radio queue and and writes it to serial\nas JSON.","_def":{"parts":[{"kind":"label","text":"radio write value to serial","style":[]}],"parameters":[]}},"parameters":[],"pyQName":"radio.write_value_to_serial"},"radio.writeReceivedPacketToSerial":{"kind":-3,"attributes":{"help":"radio/write-received-packet-to-serial","weight":3,"blockId":"radio_write_packet_serial","block":"radio write received packet to serial","advanced":true,"deprecated":"true","jsDoc":"Writes the last received packet to serial as JSON. This should be called\nwithin an ``onDataPacketReceived`` callback.","_def":{"parts":[{"kind":"label","text":"radio write received packet to serial","style":[]}],"parameters":[]}},"parameters":[],"pyQName":"radio.write_received_packet_to_serial"}}},"sha":"7a80515c7bcf6e39ba913e55a1bea2d381bf2fea6643103bc2af0667258e1f43"},"libs/bluetoothprj":{"apis":{"byQName":{"input":{"kind":5,"retType":"","attributes":{"color":"#D400D4","weight":111,"icon":"","jsDoc":"Events and data from sensors"}},"bluetooth":{"kind":5,"retType":"","attributes":{"color":"#007EF4","weight":96,"icon":"","jsDoc":"Support for additional Bluetooth services.\n\nSupport for additional Bluetooth services."}},"bluetooth.startAccelerometerService":{"kind":-3,"attributes":{"help":"bluetooth/start-accelerometer-service","blockId":"bluetooth_start_accelerometer_service","block":"bluetooth accelerometer service","parts":"bluetooth","weight":90,"blockGap":"8","jsDoc":"Starts the Bluetooth accelerometer service","_def":{"parts":[{"kind":"label","text":"bluetooth accelerometer service","style":[]}],"parameters":[]}},"parameters":[],"pyQName":"bluetooth.start_accelerometer_service"},"bluetooth.startButtonService":{"kind":-3,"attributes":{"help":"bluetooth/start-button-service","blockId":"bluetooth_start_button_service","block":"bluetooth button service","blockGap":"8","parts":"bluetooth","weight":89,"jsDoc":"Starts the Bluetooth button service","_def":{"parts":[{"kind":"label","text":"bluetooth button service","style":[]}],"parameters":[]}},"parameters":[],"pyQName":"bluetooth.start_button_service"},"bluetooth.startIOPinService":{"kind":-3,"attributes":{"help":"bluetooth/start-io-pin-service","blockId":"bluetooth_start_io_pin_service","block":"bluetooth io pin service","blockGap":"8","parts":"bluetooth","weight":88,"jsDoc":"Starts the Bluetooth IO pin service.","_def":{"parts":[{"kind":"label","text":"bluetooth io pin service","style":[]}],"parameters":[]}},"parameters":[],"pyQName":"bluetooth.start_io_pin_service"},"bluetooth.startLEDService":{"kind":-3,"attributes":{"help":"bluetooth/start-led-service","blockId":"bluetooth_start_led_service","block":"bluetooth led service","blockGap":"8","parts":"bluetooth","weight":87,"jsDoc":"Starts the Bluetooth LED service","_def":{"parts":[{"kind":"label","text":"bluetooth led service","style":[]}],"parameters":[]}},"parameters":[],"pyQName":"bluetooth.start_led_service"},"bluetooth.startTemperatureService":{"kind":-3,"attributes":{"help":"bluetooth/start-temperature-service","blockId":"bluetooth_start_temperature_service","block":"bluetooth temperature service","blockGap":"8","parts":"bluetooth","weight":86,"jsDoc":"Starts the Bluetooth temperature service","_def":{"parts":[{"kind":"label","text":"bluetooth temperature service","style":[]}],"parameters":[]}},"parameters":[],"pyQName":"bluetooth.start_temperature_service"},"bluetooth.startMagnetometerService":{"kind":-3,"attributes":{"help":"bluetooth/start-magnetometer-service","blockId":"bluetooth_start_magnetometer_service","block":"bluetooth magnetometer service","parts":"bluetooth","weight":85,"jsDoc":"Starts the Bluetooth magnetometer service","_def":{"parts":[{"kind":"label","text":"bluetooth magnetometer service","style":[]}],"parameters":[]}},"parameters":[],"pyQName":"bluetooth.start_magnetometer_service"},"bluetooth.startUartService":{"kind":-3,"attributes":{"help":"bluetooth/start-uart-service","blockId":"bluetooth_start_uart_service","block":"bluetooth uart service","parts":"bluetooth","advanced":true,"jsDoc":"Starts the Bluetooth UART service","_def":{"parts":[{"kind":"label","text":"bluetooth uart service","style":[]}],"parameters":[]}},"parameters":[],"pyQName":"bluetooth.start_uart_service"},"bluetooth.uartWriteBuffer":{"kind":-3,"attributes":{"jsDoc":"Sends a buffer of data via Bluetooth UART"},"parameters":[{"name":"buffer","type":"Buffer"}],"pyQName":"bluetooth.uart_write_buffer"},"bluetooth.uartReadBuffer":{"kind":-3,"retType":"Buffer","attributes":{"jsDoc":"Reads buffered UART data into a buffer"},"parameters":[],"pyQName":"bluetooth.uart_read_buffer"},"bluetooth.onUartDataReceived":{"kind":-3,"attributes":{"help":"bluetooth/on-uart-data-received","weight":18,"blockId":"bluetooth_on_data_received","block":"bluetooth|on data received %delimiters=serial_delimiter_conv","paramHelp":{"delimiters":"the characters to match received characters against."},"jsDoc":"Registers an event to be fired when one of the delimiter is matched.","_def":{"parts":[{"kind":"label","text":"bluetooth","style":[]},{"kind":"break"},{"kind":"label","text":"on data received ","style":[]},{"kind":"param","name":"delimiters","shadowBlockId":"serial_delimiter_conv","ref":false}],"parameters":[{"kind":"param","name":"delimiters","shadowBlockId":"serial_delimiter_conv","ref":false}]}},"parameters":[{"name":"delimiters","description":"the characters to match received characters against.","type":"string"},{"name":"body","type":"() => void","handlerParameters":[]}],"pyQName":"bluetooth.on_uart_data_received"},"bluetooth.onBluetoothConnected":{"kind":-3,"attributes":{"help":"bluetooth/on-bluetooth-connected","weight":20,"blockId":"bluetooth_on_connected","block":"on bluetooth connected","blockGap":"8","parts":"bluetooth","paramHelp":{"body":"Code to run when a Bluetooth connection is established"},"jsDoc":"Register code to run when the micro:bit is connected to over Bluetooth","_def":{"parts":[{"kind":"label","text":"on bluetooth connected","style":[]}],"parameters":[]}},"parameters":[{"name":"body","description":"Code to run when a Bluetooth connection is established","type":"() => void","handlerParameters":[]}],"pyQName":"bluetooth.on_bluetooth_connected"},"bluetooth.onBluetoothDisconnected":{"kind":-3,"attributes":{"help":"bluetooth/on-bluetooth-disconnected","weight":19,"blockId":"bluetooth_on_disconnected","block":"on bluetooth disconnected","parts":"bluetooth","paramHelp":{"body":"Code to run when a Bluetooth connection is lost"},"jsDoc":"Register code to run when a bluetooth connection to the micro:bit is lost","_def":{"parts":[{"kind":"label","text":"on bluetooth disconnected","style":[]}],"parameters":[]}},"parameters":[{"name":"body","description":"Code to run when a Bluetooth connection is lost","type":"() => void","handlerParameters":[]}],"pyQName":"bluetooth.on_bluetooth_disconnected"},"bluetooth.advertiseUrl":{"kind":-3,"attributes":{"paramDefl":{"url":"https://makecode.com","power":"7"},"blockId":"eddystone_advertise_url","block":"bluetooth advertise url %url|with power %power|connectable %connectable","parts":"bluetooth","weight":11,"blockGap":"8","help":"bluetooth/advertise-url","blockExternalInputs":"1","hidden":"1","deprecated":"1","inlineInputMode":"external","paramHelp":{"url":"the url to transmit. Must be no longer than the supported eddystone url length, eg: \"https://makecode.com\"","power":"power level between 0 and 7, eg: 7","connectable":"true to keep bluetooth connectable for other services, false otherwise."},"jsDoc":"Advertise an Eddystone URL","_def":{"parts":[{"kind":"label","text":"bluetooth advertise url ","style":[]},{"kind":"param","name":"url","ref":false},{"kind":"break"},{"kind":"label","text":"with power ","style":[]},{"kind":"param","name":"power","ref":false},{"kind":"break"},{"kind":"label","text":"connectable ","style":[]},{"kind":"param","name":"connectable","ref":false}],"parameters":[{"kind":"param","name":"url","ref":false},{"kind":"param","name":"power","ref":false},{"kind":"param","name":"connectable","ref":false}]}},"parameters":[{"name":"url","description":"the url to transmit. Must be no longer than the supported eddystone url length, eg: \"https://makecode.com\"","type":"string","default":"https://makecode.com"},{"name":"power","description":"power level between 0 and 7, eg: 7","default":"7"},{"name":"connectable","description":"true to keep bluetooth connectable for other services, false otherwise.","type":"boolean"}],"pyQName":"bluetooth.advertise_url"},"bluetooth.advertiseUidBuffer":{"kind":-3,"attributes":{"paramDefl":{"power":"7"},"parts":"bluetooth","weight":12,"advanced":true,"deprecated":"1","paramHelp":{"nsAndInstance":"16 bytes buffer of namespace (bytes 0-9) and instance (bytes 10-15)","power":"power level between 0 and 7, eg: 7","connectable":"true to keep bluetooth connectable for other services, false otherwise."},"jsDoc":"Advertise an Eddystone UID"},"parameters":[{"name":"nsAndInstance","description":"16 bytes buffer of namespace (bytes 0-9) and instance (bytes 10-15)","type":"Buffer"},{"name":"power","description":"power level between 0 and 7, eg: 7","default":"7"},{"name":"connectable","description":"true to keep bluetooth connectable for other services, false otherwise.","type":"boolean"}],"pyQName":"bluetooth.advertise_uid_buffer"},"bluetooth.setTransmitPower":{"kind":-3,"attributes":{"paramDefl":{"power":"7."},"parts":"bluetooth","weight":5,"help":"bluetooth/set-transmit-power","advanced":true,"blockId":"bluetooth_settransmitpower","block":"bluetooth set transmit power %power","paramHelp":{"power":"power level between 0 (minimal) and 7 (maximum), eg: 7."},"jsDoc":"Sets the bluetooth transmit power between 0 (minimal) and 7 (maximum).","_def":{"parts":[{"kind":"label","text":"bluetooth set transmit power ","style":[]},{"kind":"param","name":"power","ref":false}],"parameters":[{"kind":"param","name":"power","ref":false}]}},"parameters":[{"name":"power","description":"power level between 0 (minimal) and 7 (maximum), eg: 7.","default":"7."}],"pyQName":"bluetooth.set_transmit_power"},"bluetooth.stopAdvertising":{"kind":-3,"attributes":{"blockId":"eddystone_stop_advertising","block":"bluetooth stop advertising","parts":"bluetooth","weight":10,"help":"bluetooth/stop-advertising","advanced":true,"hidden":"1","deprecated":"1","jsDoc":"Stops advertising Eddystone end points","_def":{"parts":[{"kind":"label","text":"bluetooth stop advertising","style":[]}],"parameters":[]}},"parameters":[],"pyQName":"bluetooth.stop_advertising"},"bluetooth.NEW_LINE":{"kind":4,"retType":"string"},"bluetooth.__log":{"kind":-3,"attributes":{"jsDoc":"Internal use"},"parameters":[{"name":"priority"},{"name":"msg","type":"string"}]},"bluetooth.uartWriteString":{"kind":-3,"attributes":{"help":"bluetooth/uart-write-string","weight":80,"blockId":"bluetooth_uart_write","block":"bluetooth uart|write string %data","blockGap":"8","parts":"bluetooth","advanced":true,"jsDoc":"Writes to the Bluetooth UART service buffer. From there the data is transmitted over Bluetooth to a connected device.","_def":{"parts":[{"kind":"label","text":"bluetooth uart","style":[]},{"kind":"break"},{"kind":"label","text":"write string ","style":[]},{"kind":"param","name":"data","ref":false}],"parameters":[{"kind":"param","name":"data","ref":false}]}},"parameters":[{"name":"data","type":"string"}],"pyQName":"bluetooth.uart_write_string"},"bluetooth.uartWriteLine":{"kind":-3,"attributes":{"help":"bluetooth/uart-write-line","weight":79,"blockId":"bluetooth_uart_line","block":"bluetooth uart|write line %data","blockGap":"8","parts":"bluetooth","advanced":true,"jsDoc":"Writes to the Bluetooth UART service buffer. From there the data is transmitted over Bluetooth to a connected device.","_def":{"parts":[{"kind":"label","text":"bluetooth uart","style":[]},{"kind":"break"},{"kind":"label","text":"write line ","style":[]},{"kind":"param","name":"data","ref":false}],"parameters":[{"kind":"param","name":"data","ref":false}]}},"parameters":[{"name":"data","type":"string"}],"pyQName":"bluetooth.uart_write_line"},"bluetooth.uartWriteNumber":{"kind":-3,"attributes":{"help":"bluetooth/uart-write-number","weight":89,"blockGap":"8","advanced":true,"blockId":"bluetooth_uart_writenumber","block":"bluetooth uart|write number %value","jsDoc":"Prints a numeric value to the serial","_def":{"parts":[{"kind":"label","text":"bluetooth uart","style":[]},{"kind":"break"},{"kind":"label","text":"write number ","style":[]},{"kind":"param","name":"value","ref":false}],"parameters":[{"kind":"param","name":"value","ref":false}]}},"parameters":[{"name":"value"}],"pyQName":"bluetooth.uart_write_number"},"bluetooth.uartWriteValue":{"kind":-3,"attributes":{"paramDefl":{"name":"x"},"weight":78,"help":"bluetooth/uart-write-value","advanced":true,"blockId":"bluetooth_uart_writevalue","block":"bluetooth uart|write value %name|= %value","paramHelp":{"name":"name of the value stream, eg: x","value":"to write"},"jsDoc":"Writes a ``name: value`` pair line to the serial.","_def":{"parts":[{"kind":"label","text":"bluetooth uart","style":[]},{"kind":"break"},{"kind":"label","text":"write value ","style":[]},{"kind":"param","name":"name","ref":false},{"kind":"break"},{"kind":"label","text":"= ","style":[]},{"kind":"param","name":"value","ref":false}],"parameters":[{"kind":"param","name":"name","ref":false},{"kind":"param","name":"value","ref":false}]}},"parameters":[{"name":"name","description":"name of the value stream, eg: x","type":"string","default":"x"},{"name":"value","description":"to write"}],"pyQName":"bluetooth.uart_write_value"},"bluetooth.uartReadUntil":{"kind":-3,"retType":"string","attributes":{"help":"bluetooth/uart-read-until","weight":75,"blockId":"bluetooth_uart_read","block":"bluetooth uart|read until %del=serial_delimiter_conv","parts":"bluetooth","advanced":true,"jsDoc":"Reads from the Bluetooth UART service buffer, returning its contents when the specified delimiter character is encountered.","_def":{"parts":[{"kind":"label","text":"bluetooth uart","style":[]},{"kind":"break"},{"kind":"label","text":"read until ","style":[]},{"kind":"param","name":"del","shadowBlockId":"serial_delimiter_conv","ref":false}],"parameters":[{"kind":"param","name":"del","shadowBlockId":"serial_delimiter_conv","ref":false}]}},"parameters":[{"name":"del","type":"string"}],"pyQName":"bluetooth.uart_read_until"},"bluetooth.advertiseUid":{"kind":-3,"attributes":{"paramDefl":{"power":"7"},"blockId":"eddystone_advertise_uid","block":"bluetooth advertise UID|namespace (bytes 6-9)%ns|instance (bytes 2-6)%instance|with power %power|connectable %connectable","parts":"bluetooth","weight":12,"blockGap":"8","help":"bluetooth/advertise-uid","blockExternalInputs":"1","hidden":"1","deprecated":"1","inlineInputMode":"external","paramHelp":{"ns":"4 last bytes of the namespace uid","instance":"4 last bytes of the instance uid","power":"power level between 0 and 7, eg: 7","connectable":"true to keep bluetooth connectable for other services, false otherwise."},"jsDoc":"Advertise an Eddystone UID","_def":{"parts":[{"kind":"label","text":"bluetooth advertise UID","style":[]},{"kind":"break"},{"kind":"label","text":"namespace (bytes 6-9)","style":[]},{"kind":"param","name":"ns","ref":false},{"kind":"break"},{"kind":"label","text":"instance (bytes 2-6)","style":[]},{"kind":"param","name":"instance","ref":false},{"kind":"break"},{"kind":"label","text":"with power ","style":[]},{"kind":"param","name":"power","ref":false},{"kind":"break"},{"kind":"label","text":"connectable ","style":[]},{"kind":"param","name":"connectable","ref":false}],"parameters":[{"kind":"param","name":"ns","ref":false},{"kind":"param","name":"instance","ref":false},{"kind":"param","name":"power","ref":false},{"kind":"param","name":"connectable","ref":false}]}},"parameters":[{"name":"ns","description":"4 last bytes of the namespace uid"},{"name":"instance","description":"4 last bytes of the instance uid"},{"name":"power","description":"power level between 0 and 7, eg: 7","default":"7"},{"name":"connectable","description":"true to keep bluetooth connectable for other services, false otherwise.","type":"boolean"}],"pyQName":"bluetooth.advertise_uid"},"DetectedSound":{"kind":6,"retType":"DetectedSound","extendsTypes":["DetectedSound","Number"]},"DetectedSound.Loud":{"retType":"DetectedSound.Loud","attributes":{"block":"loud","_def":{"parts":[{"kind":"label","text":"loud","style":[]}],"parameters":[]}},"extendsTypes":["DetectedSound.Loud","Number"],"pyQName":"DetectedSound.LOUD"},"DetectedSound.Quiet":{"retType":"DetectedSound.Quiet","attributes":{"block":"quiet","_def":{"parts":[{"kind":"label","text":"quiet","style":[]}],"parameters":[]}},"extendsTypes":["DetectedSound.Quiet","Number"],"pyQName":"DetectedSound.QUIET"},"SoundThreshold":{"kind":6,"retType":"SoundThreshold","extendsTypes":["SoundThreshold","Number"]},"SoundThreshold.Loud":{"retType":"SoundThreshold.Loud","attributes":{"block":"loud","_def":{"parts":[{"kind":"label","text":"loud","style":[]}],"parameters":[]}},"extendsTypes":["SoundThreshold.Loud","Number"],"pyQName":"SoundThreshold.LOUD"},"SoundThreshold.Quiet":{"retType":"SoundThreshold.Quiet","attributes":{"block":"quiet","_def":{"parts":[{"kind":"label","text":"quiet","style":[]}],"parameters":[]}},"extendsTypes":["SoundThreshold.Quiet","Number"],"pyQName":"SoundThreshold.QUIET"},"input.onSound":{"kind":-3,"attributes":{"help":"input/on-sound","blockId":"input_on_sound","block":"on %sound sound","parts":"microphone","weight":88,"blockGap":"12","group":"micro:bit (V2)","jsDoc":"Registers an event that runs when a sound is detected","_def":{"parts":[{"kind":"label","text":"on ","style":[]},{"kind":"param","name":"sound","ref":false},{"kind":"label","text":" sound","style":[]}],"parameters":[{"kind":"param","name":"sound","ref":false}]}},"parameters":[{"name":"sound","type":"DetectedSound","isEnum":true},{"name":"handler","type":"() => void","handlerParameters":[]}],"pyQName":"input.on_sound"},"input.soundLevel":{"kind":-3,"retType":"number","attributes":{"help":"input/sound-level","blockId":"device_get_sound_level","block":"sound level","parts":"microphone","weight":34,"blockGap":"8","group":"micro:bit (V2)","jsDoc":"Reads the loudness through the microphone from 0 (silent) to 255 (loud)","_def":{"parts":[{"kind":"label","text":"sound level","style":[]}],"parameters":[]}},"parameters":[],"pyQName":"input.sound_level"},"input.setSoundThreshold":{"kind":-3,"attributes":{"paramDefl":{"threshold":"128"},"help":"input/set-sound-threshold","blockId":"input_set_sound_threshold","block":"set %sound sound threshold to %value","parts":"microphone","paramMin":{"threshold":"0"},"paramMax":{"threshold":"255"},"weight":14,"blockGap":"8","advanced":true,"group":"micro:bit (V2)","explicitDefaults":["threshold"],"jsDoc":"Sets the threshold for a sound type.","_def":{"parts":[{"kind":"label","text":"set ","style":[]},{"kind":"param","name":"sound","ref":false},{"kind":"label","text":" sound threshold to ","style":[]},{"kind":"param","name":"value","ref":false}],"parameters":[{"kind":"param","name":"sound","ref":false},{"kind":"param","name":"value","ref":false}]}},"parameters":[{"name":"sound","type":"SoundThreshold","isEnum":true},{"name":"threshold","initializer":"128","default":"128","options":{"min":{"value":"0"},"max":{"value":"255"}}}],"pyQName":"input.set_sound_threshold"}}},"sha":"7e7a43118046ffc82efd249dbda8e6ba3fa5cc1394ad8456fe5e4ba5e0a8d922"},"libs/tsprj":{"apis":{"byQName":{"input":{"kind":5,"retType":"","attributes":{"color":"#D400D4","weight":111,"icon":"","jsDoc":"Events and data from sensors"}},"DetectedSound":{"kind":6,"retType":"DetectedSound","extendsTypes":["DetectedSound","Number"]},"DetectedSound.Loud":{"retType":"DetectedSound.Loud","attributes":{"block":"loud","_def":{"parts":[{"kind":"label","text":"loud","style":[]}],"parameters":[]}},"extendsTypes":["DetectedSound.Loud","Number"],"pyQName":"DetectedSound.LOUD"},"DetectedSound.Quiet":{"retType":"DetectedSound.Quiet","attributes":{"block":"quiet","_def":{"parts":[{"kind":"label","text":"quiet","style":[]}],"parameters":[]}},"extendsTypes":["DetectedSound.Quiet","Number"],"pyQName":"DetectedSound.QUIET"},"SoundThreshold":{"kind":6,"retType":"SoundThreshold","extendsTypes":["SoundThreshold","Number"]},"SoundThreshold.Loud":{"retType":"SoundThreshold.Loud","attributes":{"block":"loud","_def":{"parts":[{"kind":"label","text":"loud","style":[]}],"parameters":[]}},"extendsTypes":["SoundThreshold.Loud","Number"],"pyQName":"SoundThreshold.LOUD"},"SoundThreshold.Quiet":{"retType":"SoundThreshold.Quiet","attributes":{"block":"quiet","_def":{"parts":[{"kind":"label","text":"quiet","style":[]}],"parameters":[]}},"extendsTypes":["SoundThreshold.Quiet","Number"],"pyQName":"SoundThreshold.QUIET"},"input.onSound":{"kind":-3,"attributes":{"help":"input/on-sound","blockId":"input_on_sound","block":"on %sound sound","parts":"microphone","weight":88,"blockGap":"12","group":"micro:bit (V2)","jsDoc":"Registers an event that runs when a sound is detected","_def":{"parts":[{"kind":"label","text":"on ","style":[]},{"kind":"param","name":"sound","ref":false},{"kind":"label","text":" sound","style":[]}],"parameters":[{"kind":"param","name":"sound","ref":false}]}},"parameters":[{"name":"sound","type":"DetectedSound","isEnum":true},{"name":"handler","type":"() => void","handlerParameters":[]}],"pyQName":"input.on_sound"},"input.soundLevel":{"kind":-3,"retType":"number","attributes":{"help":"input/sound-level","blockId":"device_get_sound_level","block":"sound level","parts":"microphone","weight":34,"blockGap":"8","group":"micro:bit (V2)","jsDoc":"Reads the loudness through the microphone from 0 (silent) to 255 (loud)","_def":{"parts":[{"kind":"label","text":"sound level","style":[]}],"parameters":[]}},"parameters":[],"pyQName":"input.sound_level"},"input.setSoundThreshold":{"kind":-3,"attributes":{"paramDefl":{"threshold":"128"},"help":"input/set-sound-threshold","blockId":"input_set_sound_threshold","block":"set %sound sound threshold to %value","parts":"microphone","paramMin":{"threshold":"0"},"paramMax":{"threshold":"255"},"weight":14,"blockGap":"8","advanced":true,"group":"micro:bit (V2)","explicitDefaults":["threshold"],"jsDoc":"Sets the threshold for a sound type.","_def":{"parts":[{"kind":"label","text":"set ","style":[]},{"kind":"param","name":"sound","ref":false},{"kind":"label","text":" sound threshold to ","style":[]},{"kind":"param","name":"value","ref":false}],"parameters":[{"kind":"param","name":"sound","ref":false},{"kind":"param","name":"value","ref":false}]}},"parameters":[{"name":"sound","type":"SoundThreshold","isEnum":true},{"name":"threshold","initializer":"128","default":"128","options":{"min":{"value":"0"},"max":{"value":"255"}}}],"pyQName":"input.set_sound_threshold"},"radio":{"kind":5,"retType":"","attributes":{"color":"#E3008C","weight":96,"icon":"","groups":["Group","Broadcast","Send","Receive"],"jsDoc":"Communicate data using radio packets"}},"radio.off":{"kind":-3,"attributes":{"help":"radio/off","jsDoc":"Disables the radio for use as a multipoint sender/receiver.\nDisabling radio will help conserve battery power when it is not in use."},"parameters":[]},"radio.on":{"kind":-3,"attributes":{"help":"radio/on","jsDoc":"Initialises the radio for use as a multipoint sender/receiver\nOnly useful when the radio.off() is used beforehand."},"parameters":[]},"radio.raiseEvent":{"kind":-3,"attributes":{"blockId":"radioRaiseEvent","block":"radio raise event|from source %src=control_event_source_id|with value %value=control_event_value_id","blockExternalInputs":"1","advanced":true,"weight":1,"help":"radio/raise-event","inlineInputMode":"external","jsDoc":"Sends an event over radio to neigboring devices","_def":{"parts":[{"kind":"label","text":"radio raise event","style":[]},{"kind":"break"},{"kind":"label","text":"from source ","style":[]},{"kind":"param","name":"src","shadowBlockId":"control_event_source_id","ref":false},{"kind":"break"},{"kind":"label","text":"with value ","style":[]},{"kind":"param","name":"value","shadowBlockId":"control_event_value_id","ref":false}],"parameters":[{"kind":"param","name":"src","shadowBlockId":"control_event_source_id","ref":false},{"kind":"param","name":"value","shadowBlockId":"control_event_value_id","ref":false}]}},"parameters":[{"name":"src"},{"name":"value"}],"pyQName":"radio.raise_event"},"radio.readRawPacket":{"kind":-3,"retType":"Buffer","attributes":{"jsDoc":"Internal use only. Takes the next packet from the radio queue and returns its contents + RSSI in a Buffer.\n@returns NULL if no packet available"},"parameters":[],"pyQName":"radio.read_raw_packet"},"radio.sendRawPacket":{"kind":-3,"attributes":{"callingConvention":1,"async":"true","jsDoc":"Internal use only. Sends a raw packet through the radio (assumes RSSI appened to packet)"},"parameters":[{"name":"msg","type":"Buffer"}],"pyQName":"radio.send_raw_packet"},"radio.onDataReceived":{"kind":-3,"attributes":{"help":"radio/on-data-received","weight":0,"blockId":"radio_datagram_received_event","block":"radio on data received","blockGap":"8","deprecated":"true","blockHidden":true,"jsDoc":"Used internally by the library.","_def":{"parts":[{"kind":"label","text":"radio on data received","style":[]}],"parameters":[]}},"parameters":[{"name":"body","type":"() => void","handlerParameters":[]}],"pyQName":"radio.on_data_received"},"radio.setGroup":{"kind":-3,"attributes":{"paramDefl":{"id":"1"},"help":"radio/set-group","weight":100,"blockId":"radio_set_group","block":"radio set group %ID","paramMin":{"id":"0"},"paramMax":{"id":"255"},"group":"Group","paramHelp":{"id":"the group id between ``0`` and ``255``, eg: 1"},"jsDoc":"Sets the group id for radio communications. A micro:bit can only listen to one group ID at any time.","_def":{"parts":[{"kind":"label","text":"radio set group ","style":[]},{"kind":"param","name":"ID","ref":false}],"parameters":[{"kind":"param","name":"ID","ref":false}]}},"parameters":[{"name":"id","description":"the group id between ``0`` and ``255``, eg: 1","default":"1","options":{"min":{"value":"0"},"max":{"value":"255"}}}],"pyQName":"radio.set_group"},"radio.setTransmitPower":{"kind":-3,"attributes":{"paramDefl":{"power":"7"},"help":"radio/set-transmit-power","weight":9,"blockGap":"8","blockId":"radio_set_transmit_power","block":"radio set transmit power %power","paramMin":{"power":"0"},"paramMax":{"power":"7"},"advanced":true,"paramHelp":{"power":"a value in the range 0..7, where 0 is the lowest power and 7 is the highest. eg: 7"},"jsDoc":"Change the output power level of the transmitter to the given value.","_def":{"parts":[{"kind":"label","text":"radio set transmit power ","style":[]},{"kind":"param","name":"power","ref":false}],"parameters":[{"kind":"param","name":"power","ref":false}]}},"parameters":[{"name":"power","description":"a value in the range 0..7, where 0 is the lowest power and 7 is the highest. eg: 7","default":"7","options":{"min":{"value":"0"},"max":{"value":"7"}}}],"pyQName":"radio.set_transmit_power"},"radio.setFrequencyBand":{"kind":-3,"attributes":{"help":"radio/set-frequency-band","weight":8,"blockGap":"8","blockId":"radio_set_frequency_band","block":"radio set frequency band %band","paramMin":{"band":"0"},"paramMax":{"band":"83"},"advanced":true,"paramHelp":{"band":"a frequency band in the range 0 - 83. Each step is 1MHz wide, based at 2400MHz."},"jsDoc":"Change the transmission and reception band of the radio to the given channel","_def":{"parts":[{"kind":"label","text":"radio set frequency band ","style":[]},{"kind":"param","name":"band","ref":false}],"parameters":[{"kind":"param","name":"band","ref":false}]}},"parameters":[{"name":"band","description":"a frequency band in the range 0 - 83. Each step is 1MHz wide, based at 2400MHz.","options":{"min":{"value":"0"},"max":{"value":"83"}}}],"pyQName":"radio.set_frequency_band"},"RadioPacketProperty":{"kind":6,"retType":"RadioPacketProperty","extendsTypes":["RadioPacketProperty","Number"]},"RadioPacketProperty.SignalStrength":{"retType":"RadioPacketProperty.SignalStrength","attributes":{"blockIdentity":"radio._packetProperty","block":"signal strength","_def":{"parts":[{"kind":"label","text":"signal strength","style":[]}],"parameters":[]}},"extendsTypes":["RadioPacketProperty.SignalStrength","Number"],"pyQName":"RadioPacketProperty.SIGNAL_STRENGTH"},"RadioPacketProperty.Time":{"retType":"RadioPacketProperty.Time","attributes":{"blockIdentity":"radio._packetProperty","block":"time","_def":{"parts":[{"kind":"label","text":"time","style":[]}],"parameters":[]}},"extendsTypes":["RadioPacketProperty.Time","Number"],"pyQName":"RadioPacketProperty.TIME"},"RadioPacketProperty.SerialNumber":{"retType":"RadioPacketProperty.SerialNumber","attributes":{"block":"serial number","blockIdentity":"radio._packetProperty","_def":{"parts":[{"kind":"label","text":"serial number","style":[]}],"parameters":[]}},"extendsTypes":["RadioPacketProperty.SerialNumber","Number"],"pyQName":"RadioPacketProperty.SERIAL_NUMBER"},"radio.PACKET_TYPE_NUMBER":{"kind":4,"retType":"number"},"radio.PACKET_TYPE_VALUE":{"kind":4,"retType":"number"},"radio.PACKET_TYPE_STRING":{"kind":4,"retType":"number"},"radio.PACKET_TYPE_BUFFER":{"kind":4,"retType":"number"},"radio.PACKET_TYPE_DOUBLE":{"kind":4,"retType":"number"},"radio.PACKET_TYPE_DOUBLE_VALUE":{"kind":4,"retType":"number"},"radio.lastPacket":{"kind":4,"retType":"radio.RadioPacket","pyQName":"radio.last_packet"},"radio.onReceivedNumber":{"kind":-3,"attributes":{"help":"radio/on-received-number","blockId":"radio_on_number_drag","block":"on radio received","blockGap":"16","useLoc":"radio.onDataPacketReceived","draggableParameters":"reporter","group":"Receive","weight":20,"jsDoc":"Registers code to run when the radio receives a number.","_def":{"parts":[{"kind":"label","text":"on radio received","style":[]}],"parameters":[]}},"parameters":[{"name":"cb","type":"(receivedNumber: number) => void","handlerParameters":[{"name":"receivedNumber","type":"number"}]}],"pyQName":"radio.on_received_number"},"radio.onReceivedValue":{"kind":-3,"attributes":{"help":"radio/on-received-value","blockId":"radio_on_value_drag","block":"on radio received","blockGap":"16","useLoc":"radio.onDataPacketReceived","draggableParameters":"reporter","group":"Receive","weight":19,"jsDoc":"Registers code to run when the radio receives a key value pair.","_def":{"parts":[{"kind":"label","text":"on radio received","style":[]}],"parameters":[]}},"parameters":[{"name":"cb","type":"(name: string, value: number) => void","handlerParameters":[{"name":"name","type":"string"},{"name":"value","type":"number"}]}],"pyQName":"radio.on_received_value"},"radio.onReceivedString":{"kind":-3,"attributes":{"help":"radio/on-received-string","blockId":"radio_on_string_drag","block":"on radio received","blockGap":"16","useLoc":"radio.onDataPacketReceived","draggableParameters":"reporter","group":"Receive","weight":18,"jsDoc":"Registers code to run when the radio receives a string.","_def":{"parts":[{"kind":"label","text":"on radio received","style":[]}],"parameters":[]}},"parameters":[{"name":"cb","type":"(receivedString: string) => void","handlerParameters":[{"name":"receivedString","type":"string"}]}],"pyQName":"radio.on_received_string"},"radio.onReceivedBuffer":{"kind":-3,"attributes":{"help":"radio/on-received-buffer","blockHidden":true,"blockId":"radio_on_buffer_drag","block":"on radio received","blockGap":"16","useLoc":"radio.onDataPacketReceived","draggableParameters":"reporter","jsDoc":"Registers code to run when the radio receives a buffer.","_def":{"parts":[{"kind":"label","text":"on radio received","style":[]}],"parameters":[]}},"parameters":[{"name":"cb","type":"(receivedBuffer: Buffer) => void","handlerParameters":[{"name":"receivedBuffer","type":"Buffer"}]}],"pyQName":"radio.on_received_buffer"},"radio.receivedPacket":{"kind":-3,"retType":"number","attributes":{"help":"radio/received-packet","blockGap":"16","blockId":"radio_received_packet","block":"received packet %type=radio_packet_property","group":"Receive","weight":16,"paramHelp":{"type":"the type of property to retrieve from the last packet"},"jsDoc":"Returns properties of the last radio packet received.","_def":{"parts":[{"kind":"label","text":"received packet ","style":[]},{"kind":"param","name":"type","shadowBlockId":"radio_packet_property","ref":false}],"parameters":[{"kind":"param","name":"type","shadowBlockId":"radio_packet_property","ref":false}]}},"parameters":[{"name":"type","description":"the type of property to retrieve from the last packet"}],"pyQName":"radio.received_packet"},"radio._packetProperty":{"kind":-3,"retType":"number","attributes":{"paramDefl":{"type":"PacketProperty.time"},"blockId":"radio_packet_property","block":"%note","shim":"TD_ID","blockHidden":true,"paramHelp":{"type":"the packet property type, eg: PacketProperty.time"},"jsDoc":"Gets a packet property.","_def":{"parts":[{"kind":"param","name":"note","ref":false}],"parameters":[{"kind":"param","name":"note","ref":false}]}},"parameters":[{"name":"type","description":"the packet property type, eg: PacketProperty.time","type":"RadioPacketProperty","default":"PacketProperty.time","isEnum":true}],"pyQName":"radio._packet_property"},"radio.RadioPacket":{"kind":8,"retType":"radio.RadioPacket","extendsTypes":[]},"radio.RadioPacket.getPacket":{"kind":-1,"retType":"radio.RadioPacket","parameters":[{"name":"data","type":"Buffer"}],"pyQName":"radio.RadioPacket.get_packet"},"radio.RadioPacket.mkPacket":{"kind":-1,"retType":"radio.RadioPacket","parameters":[{"name":"packetType"}],"pyQName":"radio.RadioPacket.mk_packet"},"radio.RadioPacket.signal":{"kind":-2,"retType":"number","isInstance":true,"isReadOnly":true},"radio.RadioPacket.packetType":{"kind":-2,"retType":"number","isInstance":true,"isReadOnly":true,"pyQName":"radio.RadioPacket.packet_type"},"radio.RadioPacket.time":{"kind":-2,"retType":"number","isInstance":true,"isReadOnly":true},"radio.RadioPacket.time@set":{"kind":-2,"retType":"number","isInstance":true},"radio.RadioPacket.serial":{"kind":-2,"retType":"number","isInstance":true,"isReadOnly":true},"radio.RadioPacket.serial@set":{"kind":-2,"retType":"number","isInstance":true},"radio.RadioPacket.stringPayload":{"kind":-2,"retType":"string","isInstance":true,"isReadOnly":true,"pyQName":"radio.RadioPacket.string_payload"},"radio.RadioPacket.stringPayload@set":{"kind":-2,"retType":"string","isInstance":true,"pyQName":"radio.RadioPacket.string_payload@set"},"radio.RadioPacket.numberPayload":{"kind":-2,"retType":"number","isInstance":true,"isReadOnly":true,"pyQName":"radio.RadioPacket.number_payload"},"radio.RadioPacket.numberPayload@set":{"kind":-2,"retType":"number","isInstance":true,"pyQName":"radio.RadioPacket.number_payload@set"},"radio.RadioPacket.bufferPayload":{"kind":-2,"retType":"Buffer","isInstance":true,"isReadOnly":true,"pyQName":"radio.RadioPacket.buffer_payload"},"radio.RadioPacket.bufferPayload@set":{"kind":-2,"retType":"Buffer","isInstance":true,"pyQName":"radio.RadioPacket.buffer_payload@set"},"radio.RadioPacket.hasString":{"kind":-1,"retType":"boolean","parameters":[],"isInstance":true,"pyQName":"radio.RadioPacket.has_string"},"radio.RadioPacket.hasNumber":{"kind":-1,"retType":"boolean","parameters":[],"isInstance":true,"pyQName":"radio.RadioPacket.has_number"},"radio.sendNumber":{"kind":-3,"attributes":{"help":"radio/send-number","weight":60,"blockId":"radio_datagram_send","block":"radio send number %value","blockGap":"8","group":"Send","jsDoc":"Broadcasts a number over radio to any connected micro:bit in the group.","_def":{"parts":[{"kind":"label","text":"radio send number ","style":[]},{"kind":"param","name":"value","ref":false}],"parameters":[{"kind":"param","name":"value","ref":false}]}},"parameters":[{"name":"value"}],"pyQName":"radio.send_number"},"radio.sendValue":{"kind":-3,"attributes":{"paramDefl":{"name":"name"},"help":"radio/send-value","weight":59,"blockId":"radio_datagram_send_value","block":"radio send|value %name|= %value","blockGap":"8","group":"Send","paramHelp":{"name":"the field name (max 8 characters), eg: \"name\"","value":"the numeric value"},"jsDoc":"Broadcasts a name / value pair along with the device serial number\nand running time to any connected micro:bit in the group. The name can\ninclude no more than 8 characters.","_def":{"parts":[{"kind":"label","text":"radio send","style":[]},{"kind":"break"},{"kind":"label","text":"value ","style":[]},{"kind":"param","name":"name","ref":false},{"kind":"break"},{"kind":"label","text":"= ","style":[]},{"kind":"param","name":"value","ref":false}],"parameters":[{"kind":"param","name":"name","ref":false},{"kind":"param","name":"value","ref":false}]}},"parameters":[{"name":"name","description":"the field name (max 8 characters), eg: \"name\"","type":"string","default":"name"},{"name":"value","description":"the numeric value"}],"pyQName":"radio.send_value"},"radio.sendString":{"kind":-3,"attributes":{"help":"radio/send-string","weight":58,"blockId":"radio_datagram_send_string","block":"radio send string %msg","paramShadowOptions":{"msg":{"toString":"true"}},"group":"Send","jsDoc":"Broadcasts a string along with the device serial number\nand running time to any connected micro:bit in the group.","_def":{"parts":[{"kind":"label","text":"radio send string ","style":[]},{"kind":"param","name":"msg","ref":false}],"parameters":[{"kind":"param","name":"msg","ref":false}]}},"parameters":[{"name":"value","type":"string","options":{"fieldEditorOptions":{"value":{"toString":"true"}}}}],"pyQName":"radio.send_string"},"radio.sendBuffer":{"kind":-3,"attributes":{"help":"radio/send-buffer","weight":57,"advanced":true,"jsDoc":"Broadcasts a buffer (up to 19 bytes long) along with the device serial number\nand running time to any connected micro:bit in the group."},"parameters":[{"name":"msg","type":"Buffer"}],"pyQName":"radio.send_buffer"},"radio.setTransmitSerialNumber":{"kind":-3,"attributes":{"paramDefl":{"transmit":"true"},"help":"radio/set-transmit-serial-number","weight":8,"blockGap":"8","blockId":"radio_set_transmit_serial_number","block":"radio set transmit serial number %transmit","advanced":true,"paramHelp":{"transmit":"value indicating if the serial number is transmitted, eg: true"},"jsDoc":"Set the radio to transmit the serial number in each message.","_def":{"parts":[{"kind":"label","text":"radio set transmit serial number ","style":[]},{"kind":"param","name":"transmit","ref":false}],"parameters":[{"kind":"param","name":"transmit","ref":false}]}},"parameters":[{"name":"transmit","description":"value indicating if the serial number is transmitted, eg: true","type":"boolean","default":"true"}],"pyQName":"radio.set_transmit_serial_number"},"radio.Packet":{"kind":8,"retType":"radio.Packet","extendsTypes":[]},"radio.Packet.receivedNumber":{"kind":2,"retType":"number","attributes":{"jsDoc":"The number payload if a number was sent in this packet (via ``sendNumber()`` or ``sendValue()``)\nor 0 if this packet did not contain a number."},"isInstance":true,"pyQName":"radio.Packet.received_number"},"radio.Packet.receivedString":{"kind":2,"retType":"string","attributes":{"jsDoc":"The string payload if a string was sent in this packet (via ``sendString()`` or ``sendValue()``)\nor the empty string if this packet did not contain a string."},"isInstance":true,"pyQName":"radio.Packet.received_string"},"radio.Packet.receivedBuffer":{"kind":2,"retType":"Buffer","attributes":{"jsDoc":"The buffer payload if a buffer was sent in this packet\nor the empty buffer"},"isInstance":true,"pyQName":"radio.Packet.received_buffer"},"radio.Packet.time":{"kind":2,"retType":"number","attributes":{"jsDoc":"The system time of the sender of the packet at the time the packet was sent."},"isInstance":true},"radio.Packet.serial":{"kind":2,"retType":"number","attributes":{"jsDoc":"The serial number of the sender of the packet or 0 if the sender did not sent their serial number."},"isInstance":true},"radio.Packet.signal":{"kind":2,"retType":"number","attributes":{"jsDoc":"The received signal strength indicator (RSSI) of the packet."},"isInstance":true},"radio.onDataPacketReceived":{"kind":-3,"attributes":{"help":"radio/on-data-packet-received","blockHandlerKey":"radioreceived","deprecated":"true","mutate":"objectdestructuring","mutateText":"Packet","mutateDefaults":"receivedNumber;receivedString:name,receivedNumber:value;receivedString","blockId":"radio_on_packet","block":"on radio received","blockGap":"8","jsDoc":"Deprecated. Use onDataReceived() instead\nRegisters code to run when the radio receives a packet. Also takes the\nreceived packet from the radio queue.","_def":{"parts":[{"kind":"label","text":"on radio received","style":[]}],"parameters":[]}},"parameters":[{"name":"cb","type":"(packet: radio.Packet) => void"}],"pyQName":"radio.on_data_packet_received"},"radio.onReceivedNumberDeprecated":{"kind":-3,"attributes":{"help":"radio/on-received-number","blockHandlerKey":"radioreceived","blockId":"radio_on_number","block":"on radio received","blockGap":"16","useLoc":"radio.onDataPacketReceived","deprecated":"1","jsDoc":"Registers code to run when the radio receives a number. Deprecated, use\nonReceivedNumber instead.","_def":{"parts":[{"kind":"label","text":"on radio received","style":[]}],"parameters":[]}},"parameters":[{"name":"cb","type":"(receivedNumber: number) => void","handlerParameters":[{"name":"receivedNumber","type":"number"}]}],"pyQName":"radio.on_received_number_deprecated"},"radio.onReceivedValueDeprecated":{"kind":-3,"attributes":{"help":"radio/on-received-value","blockHandlerKey":"radioreceived","blockId":"radio_on_value","block":"on radio received","blockGap":"16","useLoc":"radio.onDataPacketReceived","deprecated":"1","jsDoc":"Registers code to run when the radio receives a key value pair. Deprecated, use\nonReceivedValue instead.","_def":{"parts":[{"kind":"label","text":"on radio received","style":[]}],"parameters":[]}},"parameters":[{"name":"cb","type":"(name: string, value: number) => void","handlerParameters":[{"name":"name","type":"string"},{"name":"value","type":"number"}]}],"pyQName":"radio.on_received_value_deprecated"},"radio.onReceivedStringDeprecated":{"kind":-3,"attributes":{"help":"radio/on-received-string","blockHandlerKey":"radioreceived","blockId":"radio_on_string","block":"on radio received","blockGap":"16","useLoc":"radio.onDataPacketReceived","deprecated":"1","jsDoc":"Registers code to run when the radio receives a string. Deprecated, use\nonReceivedString instead.","_def":{"parts":[{"kind":"label","text":"on radio received","style":[]}],"parameters":[]}},"parameters":[{"name":"cb","type":"(receivedString: string) => void","handlerParameters":[{"name":"receivedString","type":"string"}]}],"pyQName":"radio.on_received_string_deprecated"},"radio.onReceivedBufferDeprecated":{"kind":-3,"attributes":{"help":"radio/on-received-buffer","blockHandlerKey":"radioreceived","blockHidden":true,"blockId":"radio_on_buffer","block":"on radio received","blockGap":"16","useLoc":"radio.onDataPacketReceived","deprecated":"1","jsDoc":"Registers code to run when the radio receives a buffer. Deprecated, use\nonReceivedBuffer instead.","_def":{"parts":[{"kind":"label","text":"on radio received","style":[]}],"parameters":[]}},"parameters":[{"name":"cb","type":"(receivedBuffer: Buffer) => void","handlerParameters":[{"name":"receivedBuffer","type":"Buffer"}]}],"pyQName":"radio.on_received_buffer_deprecated"},"radio.receivedNumber":{"kind":-3,"retType":"number","attributes":{"help":"radio/received-number","deprecated":"1","jsDoc":"Returns the number payload from the last packet taken from the radio queue\n(via ``receiveNumber``, ``receiveString``, etc) or 0 if that packet did not\ncontain a number."},"parameters":[],"pyQName":"radio.received_number"},"radio.receivedSerial":{"kind":-3,"retType":"number","attributes":{"help":"radio/received-serial","deprecated":"1","jsDoc":"Returns the serial number of the sender micro:bit from the last packet taken\nfrom the radio queue (via ``receiveNumber``, ``receiveString``, etc) or 0 if\nthat packet did not send a serial number."},"parameters":[],"pyQName":"radio.received_serial"},"radio.receivedString":{"kind":-3,"retType":"string","attributes":{"help":"radio/received-string","deprecated":"1","jsDoc":"Returns the string payload from the last packet taken from the radio queue\n(via ``receiveNumber``, ``receiveString``, etc) or the empty string if that\npacket did not contain a string."},"parameters":[],"pyQName":"radio.received_string"},"radio.receivedBuffer":{"kind":-3,"retType":"Buffer","attributes":{"help":"radio/received-buffer","deprecated":"1","jsDoc":"Returns the buffer payload from the last packet taken from the radio queue\n(via ``receiveNumber``, ``receiveString``, etc) or the empty string if that\npacket did not contain a string."},"parameters":[],"pyQName":"radio.received_buffer"},"radio.receivedTime":{"kind":-3,"retType":"number","attributes":{"help":"radio/received-time","deprecated":"1","jsDoc":"Returns the system time of the sender micro:bit at the moment when it sent the\nlast packet taken from the radio queue (via ``receiveNumber``,\n``receiveString``, etc)."},"parameters":[],"pyQName":"radio.received_time"},"radio.receiveNumber":{"kind":-3,"retType":"number","attributes":{"help":"radio/receive-number","weight":46,"blockId":"radio_datagram_receive","block":"radio receive number","blockGap":"8","deprecated":"true","jsDoc":"Reads the next packet from the radio queue and returns the packet's number\npayload or 0 if the packet did not contain a number.","_def":{"parts":[{"kind":"label","text":"radio receive number","style":[]}],"parameters":[]}},"parameters":[],"pyQName":"radio.receive_number"},"radio.receiveString":{"kind":-3,"retType":"string","attributes":{"blockId":"radio_datagram_receive_string","block":"radio receive string","blockGap":"8","weight":44,"help":"radio/receive-string","deprecated":"true","jsDoc":"Reads the next packet from the radio queue and returns the packet's string\npayload or the empty string if the packet did not contain a string.","_def":{"parts":[{"kind":"label","text":"radio receive string","style":[]}],"parameters":[]}},"parameters":[],"pyQName":"radio.receive_string"},"radio.receivedSignalStrength":{"kind":-3,"retType":"number","attributes":{"help":"radio/received-signal-strength","weight":40,"blockId":"radio_datagram_rssi","block":"radio received signal strength","deprecated":"true","blockHidden":true,"jsDoc":"Gets the received signal strength indicator (RSSI) from the last packet taken\nfrom the radio queue (via ``receiveNumber``, ``receiveString``, etc). Not supported in simulator.","_def":{"parts":[{"kind":"label","text":"radio received signal strength","style":[]}],"parameters":[]}},"parameters":[],"pyQName":"radio.received_signal_strength"},"radio.writeValueToSerial":{"kind":-3,"attributes":{"help":"radio/write-value-to-serial","weight":3,"blockId":"radio_write_value_serial","block":"radio write value to serial","deprecated":"true","jsDoc":"Reads the next packet from the radio queue and and writes it to serial\nas JSON.","_def":{"parts":[{"kind":"label","text":"radio write value to serial","style":[]}],"parameters":[]}},"parameters":[],"pyQName":"radio.write_value_to_serial"},"radio.writeReceivedPacketToSerial":{"kind":-3,"attributes":{"help":"radio/write-received-packet-to-serial","weight":3,"blockId":"radio_write_packet_serial","block":"radio write received packet to serial","advanced":true,"deprecated":"true","jsDoc":"Writes the last received packet to serial as JSON. This should be called\nwithin an ``onDataPacketReceived`` callback.","_def":{"parts":[{"kind":"label","text":"radio write received packet to serial","style":[]}],"parameters":[]}},"parameters":[],"pyQName":"radio.write_received_packet_to_serial"}}},"sha":"4a57ce1c9bd5fdb20257b6f23f7dec4624417c1d1a5f2628f3d86e0ebc45cd12"}}}